【网络编程】网络包捕获技术WinDivert介绍
一、windivert 介绍及环境搭建
我在准备开发协议测试工具的时候,在网上搜索了很多资料,偶然发现了这个强大的库,简单方便的API使得一切都变得容易,今天就来简单介绍一下它。
步骤一、下载windivert的代码库,官方网站 百度搜WinDivert
步骤二、解压下载的代码包,然后拷贝里面的include和对应平台的lib到自己的工程
步骤三、在你的VS工程中包含对应目录头文件目录和库目录文件,最后别忘了把.dll和.sys拷贝到生成目录。
二、快速上手
先看下面的一段代码,大致介绍了整个网络包从捕获、接收、修改到发送的过程。
// 打开过滤对象 mHandle = WinDivertOpen("tcp.DstPort == 80", //过滤规则 WINDIVERT_LAYER_NETWORK, //过滤的层 0, 0); if (mHandle == INVALID_HANDLE_VALUE) //开启过滤对象,可以通过错误码识别错误 { return ; //error } // 接收过滤到的网络包内容 if (!WinDivertRecv(mHandle, // windivert对象 packet, packetLen, //char* packet和buff长度 &recvSize, // int 实际读取的数据长度 &addr)) //WINDIVERT_ADDRESS { // error } // 网络包头部解析 if (!WinDivertHelperParsePacket(packet, recvSize, &iphdr, NULL, NULL, NULL, NULL, &tcphdr, &udphdr, NULL, NULL, NULL, NULL)) { // error } // -----修改网络数据包内容 // 计算校验和 WinDivertHelperCalcChecksums(packet, packetLen, &addr, 0); // 把修改后的包发送出去 if (!WinDivertSend(handle, packet, packetLen, &addr, NULL)) { // send error }
从上面的代码看,是不是非常简单?我刚开始也是被这简单的操作步骤给迷住了,但在真正开发的过程中还是有一些问题需要解决。
1. 篡改UDP,通过WinDivertHelperParsePacket方法中参数udphdr不为空即可判断当前捕获的包是UDP包,然后严格按照UDP头进行读取,首先需要先读取IP头内容,然后再读取UDP头格式。具体的格式可以参考维基百科中的介绍。篡改难度不大,这主要是因为UDP本身就是不可靠的。
2. 篡改TCP,同上只需要判断tcphdr不为空即表示是TCP包,解析的时候首先也是先读取IP头内容,然后才是TCP的内容。我们知道TCP是面向连接的可靠的网络传输协议,因此篡改起来就要麻烦一些,解决思路是这样的,首先需要将这条链接的通讯两端的网络包全部捕获下来,并解析出里面的ACK和SEQ,当进行篡改后就需要人为的对后续的每个包的ACK和SEQ进行修正,以保证接收的双方能够正常识别,否则就会被重置和断开连接。
三、总结
如果仅仅只需要监控网络包,开发起来还是比较的方便快捷。如果需要篡改其中的内容,就需要针对性的额外开发代码,感兴趣的读者可以新手写一下。
参考资料:
https://reqrypt.org/windivert-doc.html
windivert官方API说明文档
欢迎微信搜索"游戏测试开发"关注一起沟通交流。