网络包捕获技术WinDivert介绍-实现网络包篡改

一、windivert 介绍及环境搭建

   我在准备开发协议测试工具的时候,在网上搜索了很多资料,偶然发现了这个强大的库,简单方便的API使得一切都变得容易,简单介绍一下它。

   步骤一、下载windivert的代码库,官方网站 百度搜WinDivert

    步骤二、解压下载的代码包,然后拷贝里面的include和对应平台的lib到自己的工程

    步骤三、在你的VS工程中包含对应目录头文件目录和库目录文件,最后别忘了把.dll.sys拷贝到生成目录。

 

 

二、快速上手

    先看下面的一段代码,大致介绍了整个网络包从捕获、接收、修改到发送的过程。

 1 // 打开过滤对象
 2 mHandle = WinDivertOpen("tcp.DstPort == 80", //过滤规则
 3                         WINDIVERT_LAYER_NETWORK, //过滤的层
 4                         0, 0);
 5 if (mHandle == INVALID_HANDLE_VALUE) //开启过滤对象,可以通过错误码识别错误
 6 {
 7     return ;  //error
 8 }
 9 // 接收过滤到的网络包内容
10 if (!WinDivertRecv(mHandle,  // windivert对象
11           packet, packetLen,  //char* packet和buff长度
12           &recvSize,   // int 实际读取的数据长度
13           &addr)) //WINDIVERT_ADDRESS
14  {
15     // error
16  }
17  //  网络包头部解析
18 if (!WinDivertHelperParsePacket(packet, recvSize, 
19             &iphdr, NULL, NULL, NULL, NULL, 
20             &tcphdr, &udphdr, NULL, NULL, NULL, NULL))
21   {
22        // error
23   }  
24   // -----修改网络数据包内容
25   // 计算校验和
26  WinDivertHelperCalcChecksums(packet, packetLen, &addr, 0);
27   // 把修改后的包发送出去
28  if (!WinDivertSend(handle, packet, packetLen, &addr, NULL))
29  {
30        // send error
31  }

    从上面的代码看,是不是非常简单?我刚开始也是被这简单的操作步骤给迷住了,但在真正开发的过程中还是有一些问题需要解决。

    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说明文
posted @ 2021-11-21 16:44  爆走de萝卜  阅读(3968)  评论(0编辑  收藏  举报