VC环境下安装配置过程如下: 1、添加路径: 内容来自www.paper51.com 工具(Tools)->选择(Options)->目录(Directories)同下图图7进行设置。 copyright paper51.com 图7 Winpcap环境配置1 paper51.com
这里添加路径要注意自己Winpcap安装时的WPCAP和Include的文件夹的位置,要不然在代码编译和连接的时候都会报:Cannot open include file: 'pcap.h': No such file or directory。刚开始写代码的时候就吃了这方面的亏,对于这个Winpcap的环境配置不来,教程和相应的参考书籍里面写的非常的模糊,当时配置起来选项和栏目又多不知道该要填在哪儿,对于一个Winpcap的初学者来说实在时有一定的难度,后来在MSDN论坛上面求教后才明白该怎么弄,所以在论文中特别将这点加入进来。 内容来自www.paper51.com 添加路径时要注意这里不仅要添加头文件相关的路径,还要加入Libpcap的的路径。否则编译过了,连接时也会报错:cannot open file"wpcap.lib"。 内容来自www.paper51.com 图8 Winpcap环境设置2 paper51.com
2、设置工程参数 copyright paper51.com 新建一个工程后, copyright paper51.com
工程(Project)->设置(Settings) copyright paper51.com 选择C/C++;在预处理程序定义(Preprocessor definition)里面添加 http://www.paper51.com 图9 Winpcap环境设置3 内容来自论文无忧网 www.paper51.com WPCAP即可。 内容来自www.paper51.com 同理设置link,如下图图10: http://www.paper51.com
图10 Winpcap环境配置4 内容来自www.paper51.com 4.2 MFC控件相关 copyright paper51.com
通过设置不同的按钮来实现不同的控制功能,还可以通过设置list表来显示信息。其中这里主要说下关于list表的问题。其他的控件都比较简单就不在这里多说了。 内容来自论文无忧网 www.paper51.com 将list的属性中的style里查看选项改成了report格式,然后通过插入语句来实现对表项中每一列显示信息种类的设置。 内容来自论文无忧网 www.paper51.com //设置监听状况表项 http://www.paper51.com m_list1.InsertColumn( 0,_T("协议类型"), LVCFMT_LEFT, 60); http://www.paper51.com m_list1.InsertColumn( 1,_T("时间"), LVCFMT_LEFT, 70); paper51.com m_list1.InsertColumn( 2,_T("包头长"), LVCFMT_LEFT, 60); http://www.paper51.com
m_list1.InsertColumn( 3,_T("源IP地址"), LVCFMT_LEFT, 125); paper51.com m_list1.InsertColumn( 4,_T("目的IP地址"), LVCFMT_LEFT, 125); paper51.com m_list1.InsertColumn( 5,_T("源端口号"), LVCFMT_LEFT, 60); 内容来自www.paper51.com m_list1.InsertColumn( 6,_T("目的端口号"), LVCFMT_LEFT, 80); copyright paper51.com
copyright paper51.com 设置第一列为协议类型,然后第二到七列分别为捕获到数据包的时间戳、包头长度、源IP、目的IP、源端口号和目的端口号。 内容来自论文无忧网 www.paper51.com 然后在抓包函数执行后得到我们需要的信息后执行和列的插入来将数据返回界面并显示出来。 paper51.com row=m_list1.GetItemCount(); 内容来自论文无忧网 www.paper51.com row=m_list1.InsertItem(row,ip_header_proto); //协议类型 m_list1.SetItemText(row,1,time1); //捕获数据包的时间戳 内容来自论文无忧网 www.paper51.com m_list1.SetItemText(row,2,bag_header_len); //包头长度 内容来自论文无忧网 www.paper51.com m_list1.SetItemText(row,3,sourceip); //源IP paper51.com m_list1.SetItemText(row,4,desip); //目的IP http://www.paper51.com m_list1.SetItemText(row,5,sourceport); //源端口号 copyright paper51.com m_list1.SetItemText(row,6,desport); //目的端口号 copyright paper51.com
其中数据包的显示是通过定时器每隔一秒钟触发调用一次将捕捉到的数据包信息返回插入到list表中 http://www.paper51.com 4.3 定时器和系统时间的获得 内容来自论文无忧网 www.paper51.com SetTimer(1,1000,NULL); //设置定时器,1000ms触发一次 内容来自论文无忧网 www.paper51.com
… http://www.paper51.com … 内容来自论文无忧网 www.paper51.com
CDialog::OnTimer(nIDEvent); // 获得系统当前时间 内容来自论文无忧网 www.paper51.com SYSTEMTIME tNow; http://www.paper51.com GetLocalTime(&tNow); 内容来自www.paper51.com m_tc.Format("%2d:%2d:%2d",tNow.wHour,tNow.wMinute,tNow.wSecond); paper51.com
UpdateData(false); 内容来自www.paper51.com 其中设置定时器放在程序的初始化里边,通过控件显示定时器每个一秒触发一次获取当前时间函数所得到的时间。定时器的设置在捕获网络数据包函数还将会使用到,后面会详细说明。 copyright paper51.com 4.4 捕获并显示本机信息 内容来自www.paper51.com int getnetworkcardinfo() //捕获网卡信息函数 http://www.paper51.com pcap_findalldevs(&alldevs,errbuf); // 获得设备列表 paper51.com Description=d->description; //将网卡描述传递到Description中 paper51.com IP_Address=iptos(((structsockaddr_in*)a->addr)->sin_addr.s_addr); 内容来自www.paper51.com
Submask=iptos(((structsockaddr_in*)a->netmask)->sin_addr.s_addr); http://www.paper51.com 通过下面的函数把u_long型的数据转换可读的IP地址和子网掩码 copyright paper51.com char *iptos(u_long in) paper51.com
{ 内容来自论文无忧网 www.paper51.com staticchar output[IPTOSBUFFERS][3*4+3+1]; 内容来自论文无忧网 www.paper51.com //定义buffers的大小3*4+3+1,后面的+3+1分别是代表3个“.”和1个结束符 paper51.com staticshort which; paper51.com
u_char*p; http://www.paper51.com p= (u_char *)∈ 内容来自论文无忧网 www.paper51.com which= (which + 1 == IPTOSBUFFERS ? 0 : which + 1); copyright paper51.com sprintf(output[which],"%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 内容来自www.paper51.com
//输出IP: *.*.*.* http://www.paper51.com
returnoutput[which]; http://www.paper51.com
} 内容来自www.paper51.com 在初始化程序通过调用和文本设置语句将获取的本机信息传递到MFC界面中显示出来 copyright paper51.com //调用获取网卡及本机信息函数 http://www.paper51.com
getnetworkcardinfo() 内容来自论文无忧网 www.paper51.com //输出网卡基本信息 http://www.paper51.com m_des.SetWindowText(Description); 内容来自论文无忧网 www.paper51.com m_ip.SetWindowText(IP_Address); copyright paper51.com m_submask.SetWindowText(Submask); 内容来自www.paper51.com m_addressfamilyname.SetWindowText(Address_Family_Name); 内容来自www.paper51.com 通过设置的文本框来接收并显示这些信息。 http://www.paper51.com
4.5 捕获数据包及相关操作 http://www.paper51.com 接下来就是重中之重的数据包捕获等相关操作了。首先要了解一些基本信息,以便更加容易理解这段代码。当然这里所给出的都是实现每一个功能的主要代码,如头文件还有一些结构(TCP、UDP等首部的结构)的定义这里并没有给出。这些东西将不会特别给出给出,如有需要可以自行参考。因为这些只是一些struct定义而已,将各个首部中的各种相关属性定义到一起。所以这里为了大家方便理解就形象化的把个首部的信息用excel作出了插入到这里大家可以看看,代码中很多地方都用到了一些相关信息。 内容来自www.paper51.com 内容来自www.paper51.com 图11 IP首部 http://www.paper51.com 图12 TCP首部 http://www.paper51.com 图13 UDP首部 copyright paper51.com 从图11、12和13中可以轻易的看出每一种协议的数据包首部所包含的信息,这些信息很多都是可以解析看到,也是我们分析判断的依据。不论是监听网络状况还是防火墙的过滤规则安全策略,捕获数据包并分析其中所包含的内容绝对都是其中的关键和绝对的前提。 内容来自www.paper51.com 当初在写抓包程序这段代码的时候遇到了一定的问题,最开始打算通过NDIS网络驱动程序来实现这段代码,但是通过一段时间的初步学习鉴于对驱动程序的各种特性的不了解最终在韩斌韩老师和宋波宋老师的建议下改用Winpcap来实现。 内容来自www.paper51.com 刚开始在使用Winpcap来实现抓包功能的时候采用了pcap_loop()这个函数来实现,但是当使用这个函数将抓包程序写出来的时候发现调用这个函数来实现抓包功能的时候存在一定的缺陷。首先这个函数在没有数据包到来的时候将会出现阻塞的情况,而且还会增加程序的复杂程度。基于回调包捕获机制的pcap_loop()在某些情况下是不错的选择。一般程序不大的情况下使用。但是在一些情况下处理回调并不特别好:这会使程序变的复杂并且在象多线程或C++类这些情况下它看起来到像一块绊脚石。 内容来自论文无忧网 www.paper51.com 于是同样用pcap_next_ex()来编写了一个捕获网络数据包的小程序来实验比较,最终决定是用pcap_next_ex()来实现抓包功能。pcap_next_ex()是在pcap_next()的基础出现的,pcap_next()因为pcap_next()有许多限制在很多情况下并不鼓励用它。首先它的效率很低因为它隐藏了回掉方法并且还依赖于pcap_dispatch()这个函数。再次它不能够识别文件结束标志EOF所以对来自文件的数据流它几乎无能为力。 内容来自论文无忧网 www.paper51.com |