NetAnalyzer笔记 之 三. 用C++做一个抓包程序
2015-08-29 21:04
369 查看
[创建时间:2015-08-27 22:15:17]
NetAnalyzer下载地址
经过前两篇的瞎扯,你是不是已经厌倦了呢,那么这篇让我们来点有意思的吧,什么,用C#。不,这篇我们先来C++的
Winpcap开发环境配置
完成了对Winpcap的介绍,什么,你没看到Winpcap的介绍,左转,百度(其实,真的是不想复制)。我们就需要做一点有用的事情,比如写一个简单的数据采集工具。当然在此之前,我们需要配置Winpcap的开发环境。
(1) 运行环境设置
Win32 平台下Winpcap应用程序需要以下四个动态链接库才能正常运行:wpcap.dll Packet.dll WanPacket.dll pthreadVC.dll,这四个动态链接库在WinPcap驱动程序里。如果没有这个驱动程序,需要到WinPcap官方网站上下载,下载地址为:www.WinPcap.org。下载完后点击安装即可完成Winpcap核心驱动的配置,即计算机有了最初的运行基础。
(2) 开发环境的配置
本次开发使用的组件是由Winpcap官方提供的SDK,从http://www.WinPcap.org 下载Winpcap 的SDK ——WpdPack,
也可以直接在这里下载:http://pan.baidu.com/s/1hqKtsOk
当然在此之前你的爱机一定要装Winpcap
WinPcap SDk里面包含库文件,头文件,文档文件和一些例子。解压到一个指定的目录。
图1 WpdPack
其中的docs为E文,如果E实在不行 点这里http://pan.baidu.com/s/1hqHB6Pu
示例我已经在Visual Studio 2010 下成功过通过
接下来我们看看如何配置
解压缩后把Include目录与Lib目录添加到开发环境中。VC6.0环境如图2所示,
VC6.0: 菜单栏Tools->Option->Directory,在下拉列表Show directories for:中选择Include files对话框中配置Include目录,我将该文件放在D:\WPDPACK\INCLUDE文件夹下。同样改变Show directories for:选中Library files配置Lib目录。
图2 VC6.0环境下Include目录与Lib目录配置
VS2010环境如图3所示,
Visual Studio 2010: 菜单栏 工具->选项->项目和解决方案/项目->VC++目录。有时候可能出现“目录编辑功能被否决”的情况,可以通过 菜单栏 项目->XXX属性->配置属性->VC++目录 中配置,本次使用的就是这种方式。
图3 Visual Studio 2010环境下Include目录与Lib目录配置
通过上面的方式完成了文件引入部分的配置,接下来是导入库文件的方法,在VC6.0中也叫做链接库的配置。
VC6.0:菜单栏Project->Settings->Link->Object/library modules,在其中添加wpcap.lib,Packet.lib,点击OK即可。如图4
图4 VC6.0环境下链接库文件配置
Visual Studio 2010:右击 解决方案资源管理器->添加->现有项…导入Packet.lib和wpacp.lib库文件即可。如图5
图5 .Net中导入的库文件
完成了库文件的配置,现在开始本次配置的最后一步:
新的版本里WinPcap支持远程数据包获取,所以还应当添加一个头文件remote-ext.h ,即#include "remote-ext.h"(记住这条语句要放在#include”pcap.h”之后,否则会出错!)
否则会发生下面的错误:
error C2065: “PCAP_SRC_IF_STRING”: 未声明的标识符
error C3861: “pcap_findalldevs_ex”: 找不到标识符
error C2065: “PCAP_OPENFLAG_PROMISCUOUS”: 未声明的标识符
error C3861: “pcap_open”: 找不到标识符
虽然上面提供了一些解决方法,但似乎没什么作用,于是需要在开发环境中进行配置,因为VC6.0在Windows7下兼容问题,尝试多次未成功运行,所以此处只给出Visual Studio 2010中的配置结果
或者不用添加#include "remote-ext.h".在VC.NET提供的IDE环境中,可以通过执行“项目”菜单中的的“属性”进入该项目的属性配置页,通过选择“配置属性”树中的“C/C++预处理库”选项就增加”WPCAP”和”HAVE_REMOTE”两个标号,。如图6所示
图6 Visual Studio 2010环境下WPCAP与HAVE_REMOTE标号的配置
Winpcap编程实现
通过上面的配置完成了对Winpcap开发环境搭建,接下来我们就可以做一个小程序了。在做抓包程序之前,我们首先要确定从何处采集数据,大家首先想到的就是网卡,所以,第一步就是要获取网卡:
步骤:
(a) 打开Visual Studio 2010 新建项目,语言选择C++,类型选择Win32控制台应用程序,点击确定按钮。
图7 新建项目
(b) 进入想到页面,直接点击下一步,进入第二个页面,因为我们要使用C语言来制作该程序,但是在Visual Studio 2010并没用提供专用的C开发环境,所以上一步中我们选择的是C++模板,因此在接下来的页面,我们要在附加选项中选择“空项目”,这样开发环境就不会导入一些关于C++的东西了,点击完成。
图8 选择空项目
(c) 于是开发环境为我们配置了一个空项目,在解决方案资源管理器中选择源文件,右击在菜单中添加选择新建项,此时打开新建项对话框,找到C++文件,输入文件名称,注意,同时键入扩展名“.c”,这样就可以建立一个C源文件,
图9 配置方案结果
(d) 然后按照上面的环境配置方案,对项目中Include目录lib目录进行配置;导入库文件;配置标识号;最后写入如下代码:
该段代码来自Winpcap开发文档中的第一节,主要的任务是获取主机网卡设备。
(e) 最后按Ctrl+F5启动,开始编译执行该段。
结果:如图10
这里的编程实现仅仅是为了演示,Winpcap的开发配置过程,更多更为详尽的实现过程请参阅Winpcap开发文档,从Winpcap官网即可获得,所以之后的一些实现原理并不是本书的重点,故不再赘述。
图10 获取网卡执行结果
如果只是,获取到网卡,那也没什么好讲的了,下面是一段示例中的代码,在这段代码中我们不但可以取到网卡,还可以进行数据分析
在代码中只获取了UDP数据包,具体代码如下
在Winpcap 的开发包中还有其他示例额,自己慢慢去看吧
本篇有卖弄嫌疑,但是也是让大家深入理解Winpcap的具体开发方法,在下一篇我们就一起使用winpcap抓包吧 ^_^
NetAnalyzer下载地址
NetAnalzyer交流群:39753670 (PS 只提供交流平台,群主基本不说话^_^)
[转载请保留作者信息 作者:冯天文 网址:/article/5261201.html]
NetAnalyzer下载地址
经过前两篇的瞎扯,你是不是已经厌倦了呢,那么这篇让我们来点有意思的吧,什么,用C#。不,这篇我们先来C++的
Winpcap开发环境配置
完成了对Winpcap的介绍,什么,你没看到Winpcap的介绍,左转,百度(其实,真的是不想复制)。我们就需要做一点有用的事情,比如写一个简单的数据采集工具。当然在此之前,我们需要配置Winpcap的开发环境。
(1) 运行环境设置
Win32 平台下Winpcap应用程序需要以下四个动态链接库才能正常运行:wpcap.dll Packet.dll WanPacket.dll pthreadVC.dll,这四个动态链接库在WinPcap驱动程序里。如果没有这个驱动程序,需要到WinPcap官方网站上下载,下载地址为:www.WinPcap.org。下载完后点击安装即可完成Winpcap核心驱动的配置,即计算机有了最初的运行基础。
(2) 开发环境的配置
本次开发使用的组件是由Winpcap官方提供的SDK,从http://www.WinPcap.org 下载Winpcap 的SDK ——WpdPack,
也可以直接在这里下载:http://pan.baidu.com/s/1hqKtsOk
当然在此之前你的爱机一定要装Winpcap
WinPcap SDk里面包含库文件,头文件,文档文件和一些例子。解压到一个指定的目录。
图1 WpdPack
其中的docs为E文,如果E实在不行 点这里http://pan.baidu.com/s/1hqHB6Pu
示例我已经在Visual Studio 2010 下成功过通过
接下来我们看看如何配置
解压缩后把Include目录与Lib目录添加到开发环境中。VC6.0环境如图2所示,
VC6.0: 菜单栏Tools->Option->Directory,在下拉列表Show directories for:中选择Include files对话框中配置Include目录,我将该文件放在D:\WPDPACK\INCLUDE文件夹下。同样改变Show directories for:选中Library files配置Lib目录。
图2 VC6.0环境下Include目录与Lib目录配置
VS2010环境如图3所示,
Visual Studio 2010: 菜单栏 工具->选项->项目和解决方案/项目->VC++目录。有时候可能出现“目录编辑功能被否决”的情况,可以通过 菜单栏 项目->XXX属性->配置属性->VC++目录 中配置,本次使用的就是这种方式。
图3 Visual Studio 2010环境下Include目录与Lib目录配置
通过上面的方式完成了文件引入部分的配置,接下来是导入库文件的方法,在VC6.0中也叫做链接库的配置。
VC6.0:菜单栏Project->Settings->Link->Object/library modules,在其中添加wpcap.lib,Packet.lib,点击OK即可。如图4
图4 VC6.0环境下链接库文件配置
Visual Studio 2010:右击 解决方案资源管理器->添加->现有项…导入Packet.lib和wpacp.lib库文件即可。如图5
图5 .Net中导入的库文件
完成了库文件的配置,现在开始本次配置的最后一步:
新的版本里WinPcap支持远程数据包获取,所以还应当添加一个头文件remote-ext.h ,即#include "remote-ext.h"(记住这条语句要放在#include”pcap.h”之后,否则会出错!)
否则会发生下面的错误:
error C2065: “PCAP_SRC_IF_STRING”: 未声明的标识符
error C3861: “pcap_findalldevs_ex”: 找不到标识符
error C2065: “PCAP_OPENFLAG_PROMISCUOUS”: 未声明的标识符
error C3861: “pcap_open”: 找不到标识符
虽然上面提供了一些解决方法,但似乎没什么作用,于是需要在开发环境中进行配置,因为VC6.0在Windows7下兼容问题,尝试多次未成功运行,所以此处只给出Visual Studio 2010中的配置结果
或者不用添加#include "remote-ext.h".在VC.NET提供的IDE环境中,可以通过执行“项目”菜单中的的“属性”进入该项目的属性配置页,通过选择“配置属性”树中的“C/C++预处理库”选项就增加”WPCAP”和”HAVE_REMOTE”两个标号,。如图6所示
图6 Visual Studio 2010环境下WPCAP与HAVE_REMOTE标号的配置
Winpcap编程实现
通过上面的配置完成了对Winpcap开发环境搭建,接下来我们就可以做一个小程序了。在做抓包程序之前,我们首先要确定从何处采集数据,大家首先想到的就是网卡,所以,第一步就是要获取网卡:
步骤:
(a) 打开Visual Studio 2010 新建项目,语言选择C++,类型选择Win32控制台应用程序,点击确定按钮。
图7 新建项目
(b) 进入想到页面,直接点击下一步,进入第二个页面,因为我们要使用C语言来制作该程序,但是在Visual Studio 2010并没用提供专用的C开发环境,所以上一步中我们选择的是C++模板,因此在接下来的页面,我们要在附加选项中选择“空项目”,这样开发环境就不会导入一些关于C++的东西了,点击完成。
图8 选择空项目
(c) 于是开发环境为我们配置了一个空项目,在解决方案资源管理器中选择源文件,右击在菜单中添加选择新建项,此时打开新建项对话框,找到C++文件,输入文件名称,注意,同时键入扩展名“.c”,这样就可以建立一个C源文件,
图9 配置方案结果
(d) 然后按照上面的环境配置方案,对项目中Include目录lib目录进行配置;导入库文件;配置标识号;最后写入如下代码:
#include "pcap.h" main() { pcap_if_t *alldevs; pcap_if_t *d; int i=0; char errbuf[PCAP_ERRBUF_SIZE]; /* 获取本地机器设备列表 */ if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf); exit(1); } /* 打印列表 */ for(d= alldevs; d != NULL; d= d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (No description available)\n"); } if (i == 0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return; } /* 不再需要设备列表了,释放它 */ pcap_freealldevs(alldevs); }
该段代码来自Winpcap开发文档中的第一节,主要的任务是获取主机网卡设备。
(e) 最后按Ctrl+F5启动,开始编译执行该段。
结果:如图10
这里的编程实现仅仅是为了演示,Winpcap的开发配置过程,更多更为详尽的实现过程请参阅Winpcap开发文档,从Winpcap官网即可获得,所以之后的一些实现原理并不是本书的重点,故不再赘述。
图10 获取网卡执行结果
如果只是,获取到网卡,那也没什么好讲的了,下面是一段示例中的代码,在这段代码中我们不但可以取到网卡,还可以进行数据分析
#ifdef _MSC_VER /* * we do not want the warnings about the old deprecated and unsecure CRT functions * since these examples can be compiled under *nix as well */ #define _CRT_SECURE_NO_WARNINGS #endif #include "pcap.h" /* 4 bytes IP address */ typedef struct ip_address { u_char byte1; u_char byte2; u_char byte3; u_char byte4; }ip_address; /* IPv4 header */ typedef struct ip_header { u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits) u_char tos; // Type of service u_short tlen; // Total length u_short identification; // Identification u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits) u_char ttl; // Time to live u_char proto; // Protocol u_short crc; // Header checksum ip_address saddr; // Source address ip_address daddr; // Destination address u_int op_pad; // Option + Padding }ip_header; /* UDP header*/ typedef struct udp_header { u_short sport; // Source port u_short dport; // Destination port u_short len; // Datagram length u_short crc; // Checksum }udp_header; /* prototype of the packet handler */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); int main() { pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle; char errbuf[PCAP_ERRBUF_SIZE]; u_int netmask; char packet_filter[] = "ip and udp"; struct bpf_program fcode; /* Retrieve the device list */ if(pcap_findalldevs(&alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf); exit(1); } /* Print the list */ for(d=alldevs; d; d=d->next) { printf("%d. %s", ++i, d->name); if (d->description) printf(" (%s)\n", d->description); else printf(" (No description available)\n"); } if(i==0) { printf("\nNo interfaces found! Make sure WinPcap is installed.\n"); return -1; } printf("Enter the interface number (1-%d):",i); scanf("%d", &inum); /* Check if the user specified a valid adapter */ if(inum < 1 || inum > i) { printf("\nAdapter number out of range.\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } /* Jump to the selected adapter */ for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); /* Open the adapter */ if ((adhandle= pcap_open_live(d->name, // name of the device 65536, // portion of the packet to capture. // 65536 grants that the whole packet will be captured on all the MACs. 1, // promiscuous mode (nonzero means promiscuous) 1000, // read timeout errbuf // error buffer )) == NULL) { fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } /* Check the link layer. We support only Ethernet for simplicity. */ if(pcap_datalink(adhandle) != DLT_EN10MB) { fprintf(stderr,"\nThis program works only on Ethernet networks.\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } if(d->addresses != NULL) /* Retrieve the mask of the first address of the interface */ netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr; else /* If the interface is without addresses we suppose to be in a C class network */ netmask=0xffffff; //compile the filter if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 ) { fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } //set the filter if (pcap_setfilter(adhandle, &fcode)<0) { fprintf(stderr,"\nError setting the filter.\n"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } printf("\nlistening on %s...\n", d->description); /* At this point, we don't need any more the device list. Free it */ pcap_freealldevs(alldevs); /* start the capture */ pcap_loop(adhandle, 0, packet_handler, NULL); return 0; } /* Callback function invoked by libpcap for every incoming packet */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { struct tm *ltime; char timestr[16]; ip_header *ih; udp_header *uh; u_int ip_len; u_short sport,dport; time_t local_tv_sec; /* * unused parameter */ (VOID)(param); /* convert the timestamp to readable format */ local_tv_sec = header->ts.tv_sec; ltime=localtime(&local_tv_sec); strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); /* print timestamp and length of the packet */ printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec, header->len); /* retireve the position of the ip header */ ih = (ip_header *) (pkt_data + 14); //length of ethernet header /* retireve the position of the udp header */ ip_len = (ih->ver_ihl & 0xf) * 4; uh = (udp_header *) ((u_char*)ih + ip_len); /* convert from network byte order to host byte order */ sport = ntohs( uh->sport ); dport = ntohs( uh->dport ); /* print ip addresses and udp ports */ printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n", ih->saddr.byte1, ih->saddr.byte2, ih->saddr.byte3, ih->saddr.byte4, sport, ih->daddr.byte1, ih->daddr.byte2, ih->daddr.byte3, ih->daddr.byte4, dport); }
在代码中只获取了UDP数据包,具体代码如下
char packet_filter[] = "ip and udp"; 执行结果: 图11 UDP数据包分析结果 为了操作方便我把其他网卡禁用了
在Winpcap 的开发包中还有其他示例额,自己慢慢去看吧
本篇有卖弄嫌疑,但是也是让大家深入理解Winpcap的具体开发方法,在下一篇我们就一起使用winpcap抓包吧 ^_^
NetAnalyzer下载地址
NetAnalzyer交流群:39753670 (PS 只提供交流平台,群主基本不说话^_^)
[转载请保留作者信息 作者:冯天文 网址:/article/5261201.html]
相关文章推荐
- 链表的删除和插入
- 《IOS_C语言》高级指针(结构体指针、结构体数组指针、结构体数组指针,作为函数的参数使用、预编译指令)
- 有向图深度优先与广度优先算法的C++实现
- 《IOS_C语言》指针
- LeetCode:Summary Ranges
- DEV-C++官方下载地址
- C++11 并发(一道笔试题目)
- configure: error: C++ compiler cannot create executables
- 简单魔板[Special judge]
- 《IOS_C语言》指针
- C++类的构造、拷贝构造、析构函数等
- C++ 指针与引用的区别 小结
- C++不能中断构造函数来拒绝产生对象(在构造和析构中抛出异常)
- 我的C++程序
- C++的运算符重载
- C中对于结构体成员的两种引用方式适用场合的区别
- 【C/C++】纯虚函数
- 【C/C++】多态的概念
- C++函数的返回值——返回引用类型&非引用类型
- 【C/C++】构造函数和析构函数