WinPcap编程
基于libcap、winpcap的网络编程
第五章基于libpcap的网络编程技术5. 1常见的包捕获机制简介包捕获就是利用以太网的介质共享的特性,通过将网络适配器设置为混杂模式的方法,接收到所有网络上的以太网帧。
包捕获的机制大致可以分为两类:一类是由操作系统内核提供的捕获机制。
另一类是由应用软件或系统开发包捕获驱动程序提供的捕获机制。
常见的包捕获机制如表5-1所示。
其中最主要的是下列4种:BPF ( Berkeley Packet Filter )DLPI ( Data Link Provider In terface )NIT ( Network In terface Tap ) SOCK-PACKET 类型套接口。
BPF由基于BSD的Unix系统内核所实现。
DLPI是Solaris (和其他System V UNIX ) 系统的内嵌子系统。
NIT是SUN OS4 系统的一部分,但在Solaris /SUN OS5 中被DLPI 所取代。
Linux核心则实现了SOCK-PACKET 的包捕获机制。
从性能上看,BPF比DLPI 和NIT 好得多,SOCK-PACKET 最弱。
表5-1常用的包捕获机制由于现在很多局域网为NT网,其网络传输方式大多采用以太网标准,所以涉及的编程也是在Windows 环境下实现的。
Windows 操作系统没有提供包捕获机制,只提供了数量很少并且功能有限的API调用。
在Windows 环境下由于其自身的封装性,很难对其底层进行编程。
本章将对BSD系列的libpcap进行深入地介绍。
5.2 Libpcap 与 BPF(1) libpcap 概述libpcap(Packet Capturelibrary),即数据包捕获函数库。
该库提供的 C 函数接口可用于捕获经过网络接口 (只要经过该接口,目标地址不一定为本机)的数据包。
它是由洛仑兹 伯克利试验室的研究人员 Steven McCanne 和Van Jacobson 于1993 年在Usenix'93 会议上正式提出的一种用于 Unix 内核数据包过滤体制。
WinPcap开发-零基础知识入门基础
WinPcap开发(一):零基础入门*原创作者:追影人0×00 前言网络编程在网络安全方面具有举足轻重的作用,如何快捷高效的监听、分析、构造网络流量,成为很多安全从业者需要解决的重点问题。
而winpcap这一免费开源项目恰好可以为win32应用程序提供访问网络底层的能力,所以其成为了相关网络编程的首选开发工具。
0×01 winpcap是什么?winpcap(windows packet capture)是windows平台下一个免费的网络访问系统,可用于windows系统下的网络编程。
著名的wireshark便是基于winpcap开发的,大家在安装wireshark中可以看到winpcap驱动程序的安装过程。
有关winpcap的介绍网络上很多,百科里面介绍的也很详细,我就不再copy了。
需要注意的一点是,winpcap并不是一个简单的library,而是一个针对Win32平台上的抓包和网络分析的一个架构,它包括一个核心态的包过滤器,一个底层的动态链接库(packet.dll)和一个高层的不依赖于系统的库(wpcap.dll)。
所以它只能“嗅探”到物理线路上的数据包,而不具备拦截的能力,因此不适用于个人防火墙等项目。
0×02 你需要准备些什么?本系列文章主要带大家认识和了解如何利用winpcap网络编程技术进行网络的协议分析、流量统计及网络探测扫描等,这里我们并不会去深硬的解读相关源代码,而是以轻松的方式结合实验来对相关原理进行深入理解。
在本系列文章中,笔者从简到难,简明介绍winpcap架构原理、相关环境搭建及快速编写核心代码。
但是在开始前,读者需要有一些相关基础:了解网络协议相关基础知识,掌握一门winpc ap开发库支持的编程语言,自己能动手实践编写一些例子。
Winpcap提供的开发接口原生是c语言的,不过热心肠的程序猿们已经为其他语言的使用提供了封装,比如java、.net、python,好像连易语言都有。
使用WinPcap编写Sniffer程序
typedef struct pcap_if pcap_if_t struct pcap_if {
struct pcap_if *next; char *name; char *description; struct pcap_addr *addresses; bpf_u_int32 flags; /* PCAP_IF_ interface flags */ }; struct pcap_addr { struct pcap_addr *next; struct sockaddr *addr; struct sockaddr *netmask; struct sockaddr *broadaddr; struct sockaddr *dstaddr; };
pcap_compile() 编译一种包过滤器。将一种高级旳、布尔形式表 示旳字符串转换成低档旳、二进制过滤语句,以便被包驱动使用。 pcap_setfilter() 在关键驱动中将过滤器和捕获过程结合在一起。从 这一时刻起,全部网络旳数据包都要经过过滤,经过过滤旳数据 包将被传入应用程序。
过滤设置举例
设备标识 (字符串)
抓包长度
混杂模式
超时时间
捕获数据包(回调机制)
int pcap_loop ( pcap_t * p,
int cnt,
pcap_handler callback,
例如:
u_char * user )
pcap_loop(adhandle, 0, packet_handler, NULL);
打开一种适配器开始捕获数据包
pcap_t * pcap_open_live ( const char * device, int snaplen, int promisc, int to_ms, char * ebuf )
winpcap编程_适合当讲授课件
要向VC++6.0中添加一个新的包含文件所在的路径,你必 须打开Tool菜单,选择Options,然后选择Directories选项卡, 在Show directories下拉框中选择Include files,并且将新的 路径添加到Directories中去 。
二、获得设备列表
通常,编写基于WinPcap应用程序的第一件事情,就是获得已 连接的网络适配器列表。WinPcap提供了 pcap_findalldevs_ex( ) 函数来实现这个功能:
由 pcap_findalldevs_ex()返回的每一个 pcap_if 结构体, 都包含一个 pcap_addr 结构体,这个结构体由如下元素组成:
通过返回的结构,我们可以得到探测到的网卡设备的更 详尽信息。
例子:
二、打开适配器开始捕获数据包
现在,我们已经知道如何获取适配器的信息了,那我们就开始 一项更具意义的工作,打开适配器并捕获数据包。本节中,我们会 编写一个程序,将每一个通过适配器的数据包打印出来。
Sniffer,中文可以翻译为嗅探器,是一种基于被动侦听原理的网络 分析方式。使用这种技术方式,可以监视网络的状态、数据流动情况 以及网络上传输的信息。当信息以明文的形式在网络上传输时,便可 以使用网络监听的方式来进行攻击。将网络接口设置在监听模式,便 可以将网上传输的源源不断的信息截获。 wireshark(2006年之前称为Ethereal)一是全球相当行流行的开放 源代码的网络协议分析软件,功能强大而且支持平台最多,它可以实 时检测网络通讯数据,也可以检测其抓取的网络通讯数据快照文件;可 以通过图形界面浏览这些数据,可以查看网络通讯数据包中每一层的 详细内容;Wireshark还拥有许多强大的特性:包含有强显示过滤器语 言和查看TCP会话重构流的能力。它可以支持七百多种协议的解析和 多种媒体类型。
WinpCap 编写抓包程序
利用WinpCap 编写抓包程序网友:yeahilly 发布于:2008.05.20 11:12(共有条评论) 查看评论| 我要评论WinpCap是一个公开的免费的抓包驱动加开发包,利用它,可以大大缩短我们的开发周期。
首先,先枚举系统中的所有网卡:/* 获取设备列表*/if (pcap_findalldevs(&alldevs, errbuf) == -1){fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);exit(1);}/* 数据列表*/for(d=alldevs; d; d=d->next){printf("%d. %s", ++i, d->name);if (d->description)printf(" (%s)\n", d->description);elseprintf(" (No description available)\n");}然后选择网卡,然后设备。
if ( (adhandle= pcap_open_live(d->name, //设备名65536, // 捕捉完整的数据包1 , // 混在模式1, // 读入超时errbuf // 错误缓冲) ) == NULL){printf("Unable to open the adapter");pcap_freealldevs(alldevs);return;}打开设备之后,我们就可以利用adhandle句柄来正式抓包了,先新建一个回调函数,形如void packet_handler(u_char* packets,const struct pcap_pkthdr *header,const u_char *data){}然后调用pcap_loop(adhandle, 0, packet_handler,NULL);pcap_loop的最后一个参数和packet_handler的packets参数是对应的,用于在函数间传递数据。
第7章 Winpcap编程技术
PacketSetHwFilter() 设置接收模式(一般设置为混杂模式) 设置接收模式(一般设置为混杂模式) PacketSetBpf() PacketSetBuff() 编辑设置过滤规则 设置核心缓冲区大小
PacketSetReadTimeout() 设置读操作等待时间 PacketAllocatePacket() 设置(分配)用户缓冲区 设置(分配) PacketInitPacket() PacketReceivePacket() 初始化
Winpcap的各个组成部分
6
常州大学信息学院
网络编程
1、NPF驱动
网络数据包过滤器(Netgroup Filter, NPF)是Winpcap的核心部分。它处理网络 上传输的数据包,并且对用户级提供捕获、 发送和分析等功能。 NPF是一个协议驱动,它包括Network Tap和Packet Filter两个主要部件。
30
常州大学信息学院
网络编程
3、接口数据结构
struct pcap_if { struct pcap_if *next; char *name; char *description; struct pcap_addr *addresses; u_int flags; };
31
常州大学信息学院
网络编程
10
常州大学信息学院
网络编程
2、typedef struct _PACKET *LPPACKET
描述一组网络数据包的结构。它包含 了以下几个域: OVERLAPPED OverLapped PVOID Buffer UINT Length PVOID ulBytesReceived BOOLEAN bIoComplete
发送一个或多个数据报的副本。
WinPcap编程
WinPcap编程WinPcap是一个开源的、运行于Win32平台下的体系结构,它的主要功能是进行数据包捕获和网络分析。
它允许应用程序通过协议栈捕获和传输网络数据包,也包括内核级别的数据包过滤、网络静态引擎和支持远程数据包捕获等有用的功能。
WinPcap由两部分组成:1. 驱动程序: 扩展操作系统功能提供低层次的网络访问2. 动态链接库:运行在Win32平台上的应用程序可以非常方便地访问网络低层次的数据。
Ethereal是大名鼎鼎的捕获数据包专业软件,它的运行是在WinPcap的支持之下的,如果没有安装WinPcap,Ethereal也无法正常捕获数据包。
在正式WinPcap编程之前,要配置运行环境。
Win32 平台下WinPcap应用程序需要以下四个动态链接库才能正常运行:wpcap.dllPacket.dllWanPacket.dllpthreadVC.dll这四个动态链接库在WinPcap驱动程序里。
如果没有这个驱动程序,需要到WinPcap官方网站上下载,下载地址为: 如果应用程序出现一下提示,那就是没有安装驱动程序的原因了。
被过滤广告也可以不安装WinPcap驱动程序。
但是需要把上面提到的四个动态链接库文件拷贝到系统分区/WINDOWS/system32目录下或者接下来配置编程环境。
如果一个源文件使用了WinPcap提供的库函数,那么就需要在该文件开始的位置添加pcap.h 包含文件(或者在引用的文件中),即#include “pcap.h”也许会出现下面的错误:fatal error C1083: 无法打开包括文件:“pcap.h”: No such file or directory这个错误表明找不到pcap.h文件这个头文件在驱动程序安装完成后也是没有的,它是开发包里面的一个头文件所以,如果要运行程序还需要到官方网站上去下载WinPcap SDK―WpdPackWinPcap SDk里面包含库文件,头文件,文档文件和一些例子。
winpcap 编程
[中原工学院] [TCP/IP作业]——WinPcap编程学生:郑仙玉学号:201300824401 班级:网络13卓越目录3.WinPcap编程 (3)3.1获取网络适配器信息 (3)3.2 抓包 (22)创建一个使用wpcap.dll的应用程序 (22)3.3 包过滤 (27)3.4 数据包统计 (29)3.WinPcap编程3.1获取网络适配器信息任务目标:获取本机网络适配器的信息任务描述:(1)安装配置WinPcap开发环境(2)获取本机所有网络适配器,并显示每个适配器的名称、描述、是否Loopback、地址家族、地址家族名称、IP地址、子网掩码、广播地址。
任务提示:参考WinPcap开发包下“Examples-pcap”目录中的例程。
实验内容:(1).安装配置WinPcap开发环境:1.下载并安装最新版本的WinPcap安装包。
地址是:/install/default.htm2.下载最新版本的WinPcap开发包。
地址是:/devel.htm3.安装WinPcap,可以复制步骤1的链接到浏览器上进行下载,并进行安装。
安装步骤如下:1.点击1或2进行下载、安装2.点next3.选i agree4.点install5.选finish,然后就行了6.解压开发包到你想要的位置,我把自己的开发包解压到了E盘的winpcap文件夹下,如下图所示:其中docs目录中包含了WinPcap相关文档,Examples-pcap和Examples-remote都是使用WinPcap的一些例子程序,Include目录包含的是头文件,Lib目录中包含的是库文件。
4.双击打开老师给的程序ServerClientDemo5.双击ServerClientDemo的运行程序在2013运行环境下:6.(1)在菜单栏中选中视图(2)在下拉窗口选中其他窗口(3)选中属性管理器,如下图:7.双击Debug | Win32下的“er“,或者右键单击->Properties。
winpcap编程解析数据包
winpcap编程解析数据包WinPcap和Libpcap的最强⼤的特性之⼀,是拥有过滤数据包的引擎。
它提供了有效的⽅法去获取⽹络中的某些数据包,这也是WinPcap捕获机制中的⼀个组成部分。
⽤来过滤数据包的函数是和。
它将⼀个⾼层的布尔过滤表达式编译成⼀个能够被过滤引擎所解释的低层的字节码。
有关布尔过滤表达式的语法可以参见这⼀节的内容。
将⼀个过滤器与内核捕获会话向关联。
当被调⽤时,这个过滤器将被应⽤到来⾃⽹络的所有数据包,并且,所有的符合要求的数据包 (即那些经过过滤器以后,布尔表达式为真的包) ,将会⽴即复制给应⽤程序。
现在,我们可以捕捉并过滤⽹络流量了,那就让我们学以致⽤,来做⼀个简单使⽤的程序吧。
在本讲中,我们将会利⽤上⼀讲的⼀些代码,来建⽴⼀个更实⽤的程序。
本程序的主要⽬标是展⽰如何解析所捕获的数据包的协议⾸部。
这个程序可以称为UDPdump,打印⼀些⽹络上传输的UDP数据的信息。
我们选择分析和现实UDP协议⽽不是TCP等其它协议,是因为它⽐其它的协议更简单,作为⼀个⼊门程序范例,是很不错的选择。
让我们看看代码:[cpp]01. #include "pcap.h"02.03. /* 4字节的IP地址 */04. typedef struct ip_address{05. u_char byte1;06. u_char byte2;07. u_char byte3;08. u_char byte4;09. }ip_address;10.11. /* IPv4 ⾸部 */12. typedef struct ip_header{13. u_char ver_ihl; // 版本 (4 bits) + ⾸部长度 (4 bits)14. u_char tos; // 服务类型(Type of service)15. u_short tlen; // 总长(Total length)16. u_short identification; // 标识(Identification)17. u_short flags_fo; // 标志位(Flags) (3 bits) + 段偏移量(Fragment offset) (13 bits)18. u_char ttl; // 存活时间(Time to live)19. u_char proto; // 协议(Protocol)20. u_short crc; // ⾸部校验和(Header checksum)21. ip_address saddr; // 源地址(Source address)22. ip_address daddr; // ⽬的地址(Destination address)23. u_int op_pad; // 选项与填充(Option + Padding)24. }ip_header;25.26. /* UDP ⾸部*/27. typedef struct udp_header{28. u_short sport; // 源端⼝(Source port)29. u_short dport; // ⽬的端⼝(Destination port)30. u_short len; // UDP数据包长度(Datagram length)31. u_short crc; // 校验和(Checksum)32. }udp_header;33.34. /* 回调函数原型 */35. void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);36.37.38. int main()39. {40. pcap_if_t *alldevs;41. pcap_if_t *d;42. int inum;43. int i=0;44. pcap_t *adhandle;45. char errbuf[PCAP_ERRBUF_SIZE];46. u_int netmask;47. char packet_filter[] = "ip and udp";48. struct bpf_program fcode;49.50. /* 获得设备列表 */51. if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)52. {53. fprintf(stderr,"Error in pcap_findalldevs: %s/n", errbuf);54. exit(1);55. }55. }56.57. /* 打印列表 */58. for(d=alldevs; d; d=d->next)59. {60. printf("%d. %s", ++i, d->name);61. if (d->description)62. printf(" (%s)/n", d->description);63. else64. printf(" (No description available)/n");65. }66.67. if(i==0)68. {69. printf("/nNo interfaces found! Make sure WinPcap is installed./n");70. return -1;71. }72.73. printf("Enter the interface number (1-%d):",i);74. scanf("%d", &inum);75.76. if(inum < 1 || inum > i)77. {78. printf("/nInterface number out of range./n");79. /* 释放设备列表 */80. pcap_freealldevs(alldevs);81. return -1;82. }83.84. /* 跳转到已选设备 */85. for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);86.87. /* 打开适配器 */88. if ( (adhandle= pcap_open(d->name, // 设备名89. 65536, // 要捕捉的数据包的部分90. // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容91. PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式92. 1000, // 读取超时时间93. NULL, // 远程机器验证94. errbuf // 错误缓冲池95. ) ) == NULL)96. {97. fprintf(stderr,"/nUnable to open the adapter. %s is not supported by WinPcap/n");98. /* 释放设备列表 */99. pcap_freealldevs(alldevs);100. return -1;101. }102.103. /* 检查数据链路层,为了简单,我们只考虑以太⽹ */104. if(pcap_datalink(adhandle) != DLT_EN10MB)105. {106. fprintf(stderr,"/nThis program works only on Ethernet networks./n");107. /* 释放设备列表 */108. pcap_freealldevs(alldevs);109. return -1;110. }111.112. if(d->addresses != NULL)113. /* 获得接⼝第⼀个地址的掩码 */114. netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr; 115. else116. /* 如果接⼝没有地址,那么我们假设⼀个C类的掩码 */117. netmask=0xffffff;118.119.120. //编译过滤器121. if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) <0 )122. {123. fprintf(stderr,"/nUnable to compile the packet filter. Check the syntax./n");124. /* 释放设备列表 */125. pcap_freealldevs(alldevs);126. return -1;127. }128.129. //设置过滤器130. if (pcap_setfilter(adhandle, &fcode)<0)131. {132. fprintf(stderr,"/nError setting the filter./n");133. /* 释放设备列表 */134. pcap_freealldevs(alldevs);135. return -1;136. }137.138. printf("/nlistening on %s.../n", d->description);139.140. /* 释放设备列表 */141. pcap_freealldevs(alldevs);142.143. /* 开始捕捉 */144. pcap_loop(adhandle, 0, packet_handler, NULL);145.146. return 0;147. }148.149. /* 回调函数,当收到每⼀个数据包时会被libpcap所调⽤ */150. void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) 151. {152. struct tm *ltime;153. char timestr[16];154. ip_header *ih;155. udp_header *uh;156. u_int ip_len;157. u_short sport,dport;158. time_t local_tv_sec;159.160. /* 将时间戳转换成可识别的格式 */161. local_tv_sec = header->_sec;162. ltime=localtime(&local_tv_sec);163. strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);164.165. /* 打印数据包的时间戳和长度 */166. printf("%s.%.6d len:%d ", timestr, header->_usec, header->len);167.168. /* 获得IP数据包头部的位置 */169. ih = (ip_header *) (pkt_data +170. 14); //以太⽹头部长度171.172. /* 获得UDP⾸部的位置 */173. ip_len = (ih->ver_ihl & 0xf) * 4;174. uh = (udp_header *) ((u_char*)ih + ip_len);175.176. /* 将⽹络字节序列转换成主机字节序列 */177. sport = ntohs( uh->sport );178. dport = ntohs( uh->dport );179.180. /* 打印IP地址和UDP端⼝ */181. printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d/n",182. ih->saddr.byte1,183. ih->saddr.byte2,184. ih->saddr.byte3,185. ih->saddr.byte4,186. sport,187. ih->daddr.byte1,188. ih->daddr.byte2,189. ih->daddr.byte3,190. ih->daddr.byte4,191. dport);192. }。
WINPCAP编程环境设置
因为项目需要,而且以前从没用过Winpcap,所以不得不从头学起。
以前虽然看过winsocket,但是,Winpcap的第一个程序,我花了很长时间才编译通过。
对于初学者来说,不太好做的可能是编译程序之前应该做什么事。
我就大体说一下我的过程。
首先先大体介绍下Winpcap。
winpcap(windows packet capture)windows平台下一个免费,公共的网络访问系统。
开发winpcap这个项目的目的在于为win32应用程序提供访问网络底层的能力。
它提供了以下的各项功能:1> 捕获原始数据包,包括在共享网络上各主机发送/接收的以及相互之间交换的数据包;2> 在数据包发往应用程序之前,按照自定义的规则将某些特殊的数据包过滤掉;3> 在网络上发送原始的数据包;4> 收集网络通信过程中的统计信息。
具体介绍参见/view/696423.htm这里有Winpcap的详细介绍。
下面说一下你在编译Winpcap之前要做的事情。
1 下载Winpcap安装包,地址/install/default.htm。
2 然后到/devel.htm下载WinPcap developer's pack包,解压,里面有配置好的例子和include library。
3 在VC6.0菜单中,点Tolls->Options->Directories中的include files 和library files中添加包里面的include和library。
然后我们就来编写一个最简单的Winpcap程序——获取已连接的网络适配器列表。
首先新建一个工程,选择Win32 Console Application,工程名我们设为winpcap.然后这这个工程中新建一个C++源文件,名字winpcap。
在里面填写如下代码:#include <pcap.h>main( )pcap_if_t *alldevs;pcap_if_t *d;int i=0;char errbuf[PCAP_ERRBUF_SIZE];if (pcap_findalldevs(&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);elseprintf(" (No description available)\n");}if (i == 0){printf("\nNo interfaces found! Make sure WinPcap is installed.\n");return -1;}pcap_freealldevs(alldevs);return 0;}运行之前我们要手动给它添加一个动态链接库wpcap.lib,方法是在菜单Project中点Settings,然后在选项中选Link,在library modules 后面填上wpcap.lib,注意和前面的要有空格隔开。
winpcap编程设置过滤器之指定获取某个网站的数据
winpcap编程设置过滤器之指定获取某个⽹站的数据下⾯,我将以乱世隋唐页游为例,通过编码获取这⾥⾯的数据。
游戏图:我是乱世隋唐的⽹址是:这个是官⽹⽹址的服务器地址。
42.62.0.14我玩的游戏服是84区。
⽹址是:我所在区的服务器地址是: 42.62.0.7winpcap⾥有⼀个过滤器字符串。
凡是发送给这个服务器的内容,我都要获取到。
我们需要设置它为:dst host 42.62.0.7 表⽰⽬标主机地址是42.62.0.7如果我要获取从这个服务器发来的数据,需要设置过滤器字符串:src host 42.62.0.7关于字符串过滤器的语法,winpcap官⽹有,我这⾥不想讲。
现在开始编程实现获取这个游戏的数据:#include "pcap.h"int main(){pcap_if_t *alldevs;pcap_if_t *d;int inum;int i=0;pcap_t *adhandle;int res;char errbuf[PCAP_ERRBUF_SIZE];struct tm *ltime;char timestr[16];struct pcap_pkthdr *header;const u_char *pkt_data;time_t local_tv_sec;u_int netmask;char packet_filter[] = "dst host 42.62.0.7";struct bpf_program fcode;/* 获取本机设备列表 */if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1){fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);exit(1);}/* 打印列表 */for(d=alldevs; d; d=d->next){printf("%d. %s", ++i, d->name);if (d->description)printf(" (%s)\n", d->description);elseprintf(" (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);if(inum < 1 || inum > i){printf("\nInterface number out of range.\n");/* 释放设备列表 */pcap_freealldevs(alldevs);return -1;}/* 跳转到已选中的适配器 */for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);/* 打开设备 */if ( (adhandle= pcap_open(d->name, // 设备名65536, // 要捕捉的数据包的部分// 65535保证能捕获到不同数据链路层上的每个数据包的全部内容 PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式1000, // 读取超时时间NULL, // 远程机器验证errbuf // 错误缓冲池) ) == NULL){fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);/* 释放设列表 */pcap_freealldevs(alldevs);return -1;}printf("\nlistening on %s...\n", d->description);/* 设置过滤器 */if (d->addresses != NULL)/* 获取接⼝第⼀个地址的掩码 */netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;else/* 如果这个接⼝没有地址,那么我们假设这个接⼝在C类⽹络中 */netmask=0xffffff;if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask)>=0){//设置过滤器if (pcap_setfilter(adhandle, &fcode)<0){fprintf(stderr,"\nError setting the filter.\n");/* 释放设备列表 */pcap_freealldevs(alldevs);return -1;}}else{fprintf(stderr,"\nError setting the filter.\n");/* 释放设备列表 */pcap_freealldevs(alldevs);return -1;}/* 释放设备列表 */pcap_freealldevs(alldevs);/* 获取数据包 */while((res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0){if(res == 0)/* 超时时间到 */continue;/* 将时间戳转换成可识别的格式 */local_tv_sec = header->_sec;ltime=localtime(&local_tv_sec);strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);printf("%s,%.6d len:%d\n", timestr, header->_usec, header->len);}if(res == -1){printf("Error reading the packets: %s\n", pcap_geterr(adhandle));return -1;}return0;程序运⾏截图:我这⾥获取到四个本地⽹络适配器。
实验1_基于WinPcap的简单网络编程
通信软件基础实验指导书实验一:基于WinPcap的简单网络编程一、实验目的1、学习和掌握基于WinPcap编程的基本方法。
2、通过监控IP包流量,了解IP协议的工作原理和IP数据包的基本结构。
二、实验内容使用WinPcap编写一个控制台程序监控IP数据包流量,要求:①以命令行形式运行:MonitorTraffic time 其中MonitorTraffic为程序名、time为设定的监控时间(单位为分钟);②输出内容:按源地址统计该时间段内发送的IP 包的个数。
三、实验步骤及实验结果1)利用参考代码在VS2008开发工具编中写一个控制台程序2)添加...\WpdPack\Include3)打开cmd窗口,以命令行形式运行debug4)运行四、实验结果分析(自己完成)五、实验心得体会网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到通信的目的!中间最主要的就是数据包的组装,数据包的过滤,数据包的捕获,数据包的分析,当然最后再做一些处理!六、思考题:实验提示:程序中要用到WinPcap(目前的最新版本是4.1.3),可参考下列算法:1)取得当前网络设备列表(在标准输出上显示,以让用户进行选择);2)将用户选择的Ethernet网卡以混杂模式打开,以接收到所有的数据包;3)设置过滤器,此处的过滤器为“IP”;4)捕获IP包并按包的源地址进行统计(用链表结构进行实现)。
程序流程图如下图所示:开始获取网卡列表选取Ethernet网卡打开网卡(混杂模式)编译设置过滤器捕获IP包将IP包源地址加入链表N是否超时Y输出链表内容结束。
WinPcap编程
WinPcap编程WinPcap是一个开源的、运行于Win32平台下的体系结构,它的主要功能是进行数据包捕获和网络分析。
它允许应用程序通过协议栈捕获和传输网络数据包,也包括内核级别的数据包过滤、网络静态引擎和支持远程数据包捕获等有用的功能。
WinPcap由两部分组成:1. 驱动程序: 扩展操作系统功能提供低层次的网络访问2. 动态链接库:运行在Win32平台上的应用程序可以非常方便地访问网络低层次的数据。
Ethereal是大名鼎鼎的捕获数据包专业软件,它的运行是在WinPcap的支持之下的,如果没有安装WinPcap,Ethereal也无法正常捕获数据包。
在正式WinPcap编程之前,要配置运行环境。
Win32 平台下WinPcap应用程序需要以下四个动态链接库才能正常运行:wpcap.dllPacket.dllWanPacket.dllpthreadVC.dll这四个动态链接库在WinPcap驱动程序里。
如果应用程序出现一下提示,那就是没有安装驱动程序的原因了。
被过滤广告也可以不安装WinPcap驱动程序。
但是需要把上面提到的四个动态链接库文件拷贝到系统分区/WINDOWS/system32目录下或者接下来配置编程环境。
如果一个源文件使用了WinPcap提供的库函数,那么就需要在该文件开始的位置添加pcap.h包含文件(或者在引用的文件中),即#include “pcap.h”也许会出现下面的错误:fatal error C1083: 无法打开包括文件:“pcap.h”: No such file or directory这个错误表明找不到pcap.h文件这个头文件在驱动程序安装完成后也是没有的,它是开发包里面的一个头文件所以,如果要运行程序还需要到官方网站上去下载WinPcap SDK―WpdPackWinPcap SDk里面包含库文件,头文件,文档文件和一些例子。
解压缩后把Include目录添加到IDE的包含文件中(VC6.0 Tools->Option->Directory; VS 2003/2005 工具->选项->项目和解决方案/项目->VC++目录)error LNK2019: 无法解析的外部符号_pcap_findalldevs_ex,该符号在函数XXX 中被引用如果发生上面的错误就表明缺少库文件,需要添加wpcap.lib到工程中(VC6.0 Project->Settings->Link->Object/library modules; VS 2003/2005 项目->添加现有项->所有文件)error C2065: “PCAP_SRC_IF_STRING”: 未声明的标识符error C3861: “pcap_findalldevs_ex”: 找不到标识符error C2065: “PCAP_OPENFLAG_PROMISCUOUS”: 未声明的标识符error C3861: “pcap_open”: 找不到标识符新的版本里WinPcap支持远程数据包获取,发生上面的错误很有可能是新的版本导致不兼容的问题,所以还应当添加一个头文件remote-ext.h ,即#include "remote-ext.h"如果还有问题,可以到WinPcaP官方网站上找FAQ。
Winpcap编程
接口
3.1 WinPcap组成--Packet.dll
packet.dll(Packet Driver
API) 提供了一个底层的API访问接 口,可以直接访问网卡,为win32 平台提供了一个公共的接口。
3.1 WinPcap组成
NPF功能: 数据捕获 流量监测 数据发送 dump to disk
1.什么是WinPcap
2.WinPcap的结构
3.WinPcap编程环境配置
环境配置
VC6.0 环境下的配置
1. 到/devel.htm 下载安装 包 和 Developer's Pack. 2.安装驱动。 3.开发时,解压Developer's Pack,分别找到LIB 和 Include 目录。打开VC++,首先在 Tools=>Options=>Directories,分别配置 lib 和 Include 目录。当中Show Directories for 可以指定相应 的文件目录 4.VC++环境配置。 Project=>Settings=>Link=>Object/Library Modules 里面添加需要的LIB. (Packet.lib wpcap.lib ws2_32.lib)
在同一下拉框中找到“库文件”,然后对应到开发包的lib目录;
设置编译条件;在项目属性页中:
配置属性->C/C++->预处理器->预处理器定义,增加 ;WPCAP;HAVE_REMOTE;每 一个预定义符用";"隔开; 在项目属性页中:配置属性->链接器->命令行->附加选项对应的文本 框中增加:“wpcap.lib ws2_32.lib”;
编译与使用WinPcap
1.1. 源代码目录结构WinPcap的所有源代码都可从网站获取,此处采用的源代码包为WpcapSrc_4_1_beta5.zip,源代码目录结构如图5-1所示。
其中:Common目录下为几个共用的头文件。
dox 目录下为一些说明文档。
Examples-pcap与Examples目录下为一些示例代码,两个目录的区别在于前者是采用libpcap库接口的示例程序,后者为采用wpcap库接口的示例程序。
Packet9x目录下为Windows 9x平台的驱动程序NPF的源代码与Packet.dll库的源代码,分别放置在VXD与DLL目录下。
PacketNtx目录下为Windows NTx平台的驱动程序NPF的源代码与Packet.dll库的源代码,分别放置在driver与DLL目录下。
wpcap目录下为wpcap.dll库的源代码。
图5-1 WinPcap源代码目录结构可从网站获取开发包WpdPack_4_1_beta5.zip,便于WinPcap的软件开发,该软件包的目录结构如图5-2所示,其中:docs目录下为详细的用户使用手册。
Examples-pcap与Examples-remote目录下为一些示例代码,两个目录的区别在于前者是采用libpcap库接口的示例程序,后者为采用wpcap库接口的示例程序。
Include目录下为在WinPcap库上开发所需的头文件。
Lib目录下为在WinPcap库上开发所需的库文件。
图5-2 WpdPack 开发包目录结构1.2. 构建驱动程序NPF在开始编译之前,我们需要注意NPF是依赖于平台的。
所以强烈建议编译驱动程序的操作系统与将要使用NPF的操作系统一致。
此处我们以Windows XP(x86架构)平台下驱动程序NPF的构建为例,来说明构建的过程。
此处使用WDK 6001.18002[2]编译WinPcap 4.1 beta5。
WinPcap 4.1 beta5的文档要求采用Microsoft Windows Driver Kit (WDK) 6000 or 6001进行编译。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Packet.dll应用步骤
2) 打开指定的网卡 lpAdapter = PacketOpenAdapter(AdapterList [0 ]) ; if ( ! lpAdapter | | (lpAdapter - > hFile = = INVALID_HANDLE_VALUE) ) { dwErrorCode = GetLastError() ; sprintf ( szErr ,″Unable to open the adapter ,error code : %lx″, dwErrorCode) ; AfxMessageBox(szErr) ; return FALSE; }
1> LPPACKET PacketAllocatePacket(void) 如果运行成功,返回一个_PACKET结构的指针, 否则返回NULL。成功返回的结果将会传送到 PacketReceivePacket()函数,接收来自驱动的网络 数据报。 2> VOID PacketFreePacket(LPPACKET lpPacket) 释放参数提供的_PACKET结构。 3> VOID PacketCloseAdapter(LPADAPTER lpAdapter) 关闭参数中提供的网络适配器,释放相关的 ADAPTER结构。
WinPcap
WinPcap包括三个部分 第一个模块:内核级的包过滤驱动程序
NPF(Netgroup Packet Filter),是一个虚拟设备驱动程序文件, 是架构的核心(在Win95/98 中是一个VXD文件,在NT/2000 中是 一个SYS 文件) ,它的主要功能是过滤数据包,在包上附加时间戳、 数据包长度等信息。
第二个模块:低级动态链接库packet.dll,在Win32 平台 上提供了与NPF 的一个通用接口。 packet.dll数据包驱 动程序库是与libpcap 相兼容的一组用户级的函数库。 第三个模块:用户级的Wpcap.dll。通过调用packet.dll 提供的函数生成,它包括了过滤器生成等一系列可以被 用户级调用的高级函数,另外还有诸如数据包统计及发 送功能。
Packet.dll相关函数
7> BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s) 返回几个关于当前捕获报告的统计信息。 其中bpf_stat结构包含: bs_recv, bs_drop,ps_ifdrop,bs_capt bs_recv: 从网络适配器开始捕获数据报 开始所接收到的所有数据报的数目,包括丢失 的数据报; bs_drop: 丢失的数据报数目。 8> PCHAR PacketGetVersion() 返回关于dll的版本信息。
Packet.dll相关函数
14> BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter) 为接收到的数据报设置硬件过滤规则。
以下为一些典型的过滤规则: NDIS_PACKET_TYPE_PROMISCUOUS: 设置为混 杂模式,接收所有流过的数据报; NDIS_PACKET_TYPE_DIRECTED: 只有目的地为 本地主机网络适配器的数据报才会被接收; NDIS_PACKET_TYPE_BROADCAST: 只有广播数 据报才会被接收; NDIS_PACKET_TYPE_MULTICAST: 只有与本地 主机网络适配器相对应的多播数据报才会被接收; NDIS_PACKET_TYPE_ALL_MULTICAST: 所有多 播数据报均被接收; NDIS_PACKET_TYPE_ALL_LOCAL: 所有本地数 据报均被接收。
WinPcap体系结构来自NPFPacket.dll相关的数据结构
typedef struct _ADAPTER *LPADAPTER 描述一个网络适配器。 它包含了两个域: HANDLE hFile TCHAR SymbolicLink hFile是一个指向驱动器句柄的指针。通过该句柄, 我们可以直接与驱动器进行通信,如接收或发送 数据包。SymbolicLink是一个字符串,它包含了 当前打开的网络适配器的名称。
Packet.dll相关函数
15> BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites) 设置调用PacketSendPacket()函数发送一个数 据报副本的最大重发次数。 16> BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout) 设置读操作等待时间 。
Packet.dll相关的数据结构
struct bpf_hdr 数据报头部。 它包含以下几个域: struct timeval bh_tstamp UNIT bh_caplen UNIT bh_datalen USHORT bh_hdrlen bh_tstamp是一个时间戳,它包含两个域: tv_sec和tv_usec,用来表示报文的捕获时间。 bh_caplen是封装报文后的报文长度。bh_datalen是 原始报文长度。bh_hdrlen是封装报文的报头长度。
Packet.dll相关函数
12> BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket, BOOLEAN Sync) 发送一个或多个数据报的副本。 13> BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim) 设置捕获数据报的内核级缓冲区大小。
以上介绍的包含了packet.dll里的大部分函数。如果想更 深层的了解winpcap,请访问相关网站,主页地址: http://winpcap.polito.it
Packet.dll监听流程图
PacketGetAdapterName() 选择网卡 PacketOpenAdapter() PacketSetHwFilter() 打开网络适配器 设置接收模式(一般设置为混杂模式) 编辑设置过滤规则 设置核心缓冲区大小
Packet.dll相关的数据结构
typedef struct NetType NetType 描述网络类型的数据结构。
typedef struct npf_if_addr npf_if_addr 描述一个网络适配器的ip地址。 Struct bpf_stat 当前捕获数据报的统计信息
Packet.dll相关函数
Packet.dll应用步骤
3) 设置过滤器,将网卡设置为混杂模式,这样可以监听流过本机的数据包 if ( PacketSetHwFilter ( lpAdapter ,NDIS_PACKET_TYPE_PROMISCUOUS) = = FALSE) { return FALSE; } 4) 设置缓冲区大小 if (PacketSetBuff (lpAdapter ,512000) = = FALSE) { return FALSE; } 5) 设置接收一个数据包的超时时间 PacketSetReadTimeout ( lpAdapter , 1000) / / set a 1 second read timeout
Packet.dll相关函数
9> VOID PacketInitPacket(LPPACKET lpPacket, PVOID Buffer, UINT Length) 初始化一个_PACKET结构。 10> LPADAPTER PacketOpenAdapter(LPTSTR AdapterName) 打开一个网络适配器。 11> BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync) 从NPF驱动程序读取网络数据报及统计信息。 数据报编码结构: |bpf_hdr|data|Padding|bpf_hdr|data|Padding|
Windows平台下的抓包技术
虽然Unix 平台上的BSD 包截获系统提供了一组供 应用程序直接调用的网络数据包截获函数,允许应 用程序与网卡间直接进行交互, 但在Win32 平台上, 目前主要使用WinPcap 体系结构。 WinPcap 是基于Win32 平台的网络包截获和分析 的系统,它具有丰富的网络数据包处理函数,其功能 比BSD 包截获系统更强,如“包监视”和“包发送” 等功能函数在早先的Unix 平台上是不具备的。 WinPcap是一个重要的抓包工具,它是libpcap的 Windows版本
Packet.dll相关的数据结构
typedef struct _PACKET *LPPACKET 描述一组网络数据包的结构。 它包含了以下几个域: OVERLAPPED OverLapped PVOID Buffer UINT Length PVOID ulBytesReceived BOOLEAN bIoComplete OverLapped是用来处理对驱动器的异步调用。Buffer是用 来指向缓存的指针,该缓存包含了数据包的数据。Length是 该缓存区的大小。而ulBytesReceived表明了该缓存中包含的 有效数据的大小。BIoComplete是在异步调用中用来表示该 Packet是否包含有效的数据。
Packet.dll相关函数
4> BOOLEAN PacketGetAdapterNames(LPSTR pStr,PULONG BufferSize) 返回可以得到的网络适配器列表及描述。 5> BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterNames,npf_ip_addr *buff, PLONG NEntries) 返回某个网络适配器的全面地址信息。 其中npf_ip_addr结构包含: IPAddress: ip地址 SubnetMask: 子网掩码 Broadcast: 广播地址