| « | November 2025 | » | | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | | | | | | |
| 登录 |
|
| 联系我 email: binaryluo(at)gmail.com
|
Blog信息 |
|
blog名称:二进制-虚心使人进步,骄傲使人落后。 日志总数:42 评论数量:370 留言数量:88 访问次数:643706 建立时间:2005年2月19日 |

| |
|
[网络编程技术]关于Winpcap和NDIS数据包的问题 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
binaryluo 发表于 2006/3/30 17:41:26 |
|
问题一:Winpcap捕获到的数据包是什么?
pcap_open()函数的第二个参数snaplen表示的是需要保存的数据包的长度,对于被过滤器接收到的每一个数据包,仅仅只有开始的‘snaplen’个字节被保存到缓冲区然后被传递给用户应用程序。例如,snaple等于100意味着仅仅保存每一个数据包开始的100个字节。在某些操作系统中(例如xBSD和Win32),数据包驱动程序可以被配置了只捕获数据包的首部:这样可以减少要拷贝的数据量从而提高抓包的效率。如果想要获得完整的数据包,可以把snaplen赋值为65535,因为65535远远大于我们所遇到的最大的MTU。下图(截自《TCP/IP详解卷一:协议》)列出了最常见的MTU:
500)this.width=500'>pcap_dispatch()和pcap_loop()都是捕获数据包的函数。它们的功能非常相似,只是返回的时机不同,pcap_ dispatch()。
pcap_handler()中的第二个参数struct pcap_pkthdr *pkt_header是与抓包驱动程序相关的一些头部信息,但它不是协议头。第三个参数const u_char *pkt_data是指向数据包的指针,包括协议头。如下图(截自winpcap文档)所示:
500)this.width=500'>
因此表明winpcap捕获到的数据包就是一些字节流,该字节流以一个MTU的实际大小作为一个数据包,所以前面如果在pcap_open()里设置了snaplen是65535就可以保证以65535字节为一个数据包的大小,如果MTU小于65535,多出来的字节将添0(这里我已经用winpcap抓获数据包分析过)。
总结:
先回顾下winpcap的内部结构图(截自winpcap文档):
500)this.width=500'>
Winpcap提供了两个不同的库:packet.dll和wpcap.dll前者提供了一个底层API,伴随着一个独立于Microsoft操作系统的编程接口,这些API可以直接用来访问驱动的函数;后者导出了一组更强大的与libpcap一致的高层抓包函数库(capture primitives),这些函数使得数据包的捕获以一种与网络硬件和操作系统无关的方式进行 。Packet.dll是一个相对于NPF驱动的用户应用程序,就是来使用NPF提供的功能的;wpcap.dll的接口跟libpcap是一样的。
Winpcap的NPF捕获到的数据包是什么还是依赖于NDIS的库函数。不过根据NPF发送的数据格式可以判断它捕获到的数据包应该也是字节流,因为NPF允许发送的数据包可以没有按照任何的协议进行封装,因为封装的工作是在应用程序里完成的,也就是说NPF根本不关心上层传下来的是什么,只要传下来就发送;按照发送数据包的思路推想接收数据包也应该是这样的,NPF不关心接收到的是什么东西,反正它以你规定的snaplen为单位读取数据交给上层应用程序,由应用程序来判断该数据到底是怎么封装的,也就是Packet.dll或更上层应用程序。
问题二:Ndis库函数从网卡拷贝过来的数据包是什么?
NDIS数据包被协议驱动分配的,填以数据,并且为了将这些数据发送出去而传递给更低层的NDIS驱动。通常,协议驱动分配一个数据包并且把它传递给一个NIC驱动,然后NIC驱动把接收到的数据拷贝到协议驱动所提供的数据包中。NDIS提供了分配和操作包装数据包结构体的函数。下图(截自DDK)阐明了一个数据包的结构:
500)this.width=500'>下面就讨论NDIS是如何用NDIS_PACKET表示网络上的数据包(Packet)。下面是一个简单的ICMP“ping”数据包的16进制表示:000000: 00 A0 CC 63 08 1B 00 40 : 95 49 03 5F 08 00 45 00 ...c...@.I._..E.000010: 00 3C 82 47 00 00 20 01 : 94 C9 C0 A8 01 20 C0 A8 .<.G.. ...... ..000020: 01 40 08 00 48 5C 01 00 : 04 00 61 62 63 64 65 66 .@..H\....abcdef000030: 67 68 69 6A 6B 6C 6D 6E : 6F 70 71 72 73 74 75 76 ghijklmnopqrstuv000040: 77 61 62 63 64 65 66 67 : 68 69 wabcdefghi......
这个ping是由下面的命令来初始化的:
C:> ping 192.168.1.64
并发送伴随着默认的32字节数据的ICMP响应请求。Ping数据包的总长度是74字节。下图(截自http://www.ndis.com/papers/ndispacket/ndispacket1.htm)阐明了一个NDIS_PACKET用来表示被封装好的数据包数据的简单方式:
500)this.width=500'>在这个简单的例子中,数据包数据的74个字节全都是在一片连续的空间内。用一句话对这个NDIS_PACKET可描述为:
NDIS_PACKET有一个NDIS_BUFFER链,NDIS_BUFFER描述了包含完整数据包数据的74字节大小的虚拟存储空间。
下面这个图比上面那个图稍微复杂一点,它阐明了NDIS_PACKET表示封装好的数据包数据的另一种方式:
500)this.width=500'>在这个例子中数据包数据被存放在两个不连续的虚拟存储空间中。用一句话总结如下:
这个NDIS_PACKET有两个链在一起的NDIS_BUFFER,第一个NDIS_BUFFER表示了包含以太帧头部的14字节虚拟存储空间,第二个NDIS_BUFFER表示以太帧的有效负载(数据)的60字节虚拟存储空间。
尽管上面两个图有助于理解如何使用一个NDIS_PACKET,但是还必须注意一点这些结构体是透明的。我们不能直接访问结构体的这些域,只能通过NDIS库提供的函数来访问它们。NDIS提供的用来检查NDIS_PACKET和NDIS_BUFFER的函数很少,下面列举几个(详细信息看DDK):NdisQueryPacket,NdisQueryBuffer,NidsGetNextBuffer,NdisQueryBufferSafe。
总结:网线上传输的是电信号,NIC的功能就是将这些电信号转化成计算机能够理解的二进制位串,而网卡驱动就是将这些连续的二进制位串进行整理,把它整理成NDIS_PACKET这样的结构体,所以从网卡读数据包的时候读到的就是NDIS_PAKCET这种结构体。然后NDIS提供了相应的函数来处理NDIS_PACKET结构体,一个NDIS_PACKET中的NDIS_BUFFER组成的链表所指示的虚拟存储空间连接起来就是一个完整的数据帧。
|
|
回复:关于Winpcap和NDIS数据包的问题 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
hjbcn(游客)发表评论于2007/6/27 10:50:30 |
|
因为防火墙的原因,PCAP抓不到数据包。有没有一个好的解决办法?以下为blog主人的回复: 这个应该没办法了,因为用WinPcap捕获数据包利用广播的特点进行的,如果是防火墙组织了广播的话,用WinPcap就没意义了。
|
|
回复:关于Winpcap和NDIS数据包的问题 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
rr(游客)发表评论于2006/5/18 15:14:26 |
|
我用winpcap发包,发现速度比NDIS差多了,不知道是我程序的问题,还是WinPcap本身的问题?盼LZ赐教以下为blog主人的回复: 有可能,虽然WinPcap基于NDIS,但因为WinPcap为了做得通用,所以相对来说比较臃肿,如果能针对自己的需要自己开发一个抓包库而不必考虑太多通用性的话这样效率应该会高得多。
|
|
回复:关于Winpcap和NDIS数据包的问题 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
binaryluo发表评论于2006/4/1 0:59:13 |
|
以下引用everester(游客)在2006-3-31 11:18:27的评论:怎样把截获的数据包进行拼装和还原呢,还请Binary能够帮忙指出,比如说如何将一封基于SMTP的的邮件的不同包组合起来并还原呢.谢谢.
我认为需要组合数据包的地方有两处:一是在IP层需要组合IP分片;另外就是在TCP层需要组合数据段。组装数据包都依赖于这两层协议头中的某些关键字段,所以正确解读出包头信息是必须的,然后再根据相关关键字段来组合数据包。
关于SMTP数据包组合好以后,可能还要用base64解码。
|
|
回复:关于Winpcap和NDIS数据包的问题 原创空间, 随笔, 读书笔记, 心得体会, 软件技术, 电脑与网络
everester(游客)发表评论于2006/3/31 11:18:27 |
|
怎样把截获的数据包进行拼装和还原呢,还请Binary能够帮忙指出,比如说如何将一封基于SMTP的的邮件的不同包组合起来并还原呢.谢谢.
|
» 1 »
|