Windows驱动编程之NetFilterSDK

admin 2021年12月15日03:44:07评论1,516 views字数 5958阅读19分51秒阅读模式
Windows驱动编程之NetFilterSDK
本文为看雪论坛优秀文章
看雪论坛作者ID:一半人生

Nfsdk源码网友口碑一直不错,梳理笔记分享。NetFilter SDK团队维护了多平台源码,本篇只介绍Windows平台。

官网:https://netfiltersdk.com

官网帮助:https://netfiltersdk.com/help/nfsdk2/

如果对Windows网络驱动没有概念,请先看:https://bbs.pediy.com/thread-268468.htm


1


源码分析


Netfilter sdk 2.0f主要分析三个模块,驱动,Dll和应用层。

编译环境:Wdk 2008/ wdk7600,win7/win10 x32x64

源码:泄露版v1.5.5.6(文章不提供,网上一堆)的socketRedirect示例。

R3/Nfapi:


1、 SocksRedirector.cpp.main入口分析:

For循环部分参数解析,eh则是EventHandler类负责规则和数据处理,Add_rule()函数负责添加规则。
Windows驱动编程之NetFilterSDK
2、Eh.Init函数负责Proxy的初始化:
Windows驱动编程之NetFilterSDK
 3、Nf_init驱动初始化,数据初始化包括hash_tab链表和启动Work线程:
Windows驱动编程之NetFilterSDK
4、Work线程负责Event事件处理,并且阻塞在Read I/O数据,等待驱动返回数据,如下所示:
if (!ReadFile(g_hDevice, &rr, sizeof(rr), NULL, &ol)){    if (GetLastError() != ERROR_IO_PENDING)        goto finish;}
Windows驱动编程之NetFilterSDK
5 HandleEvent负责处理来自内核捕获的传输层,网络层数据流,TCP/UDP-IP规则处理都可以在该类中,然后通过Nfapi.cpp接口将修改后的数据Write_IRP到驱动(注入):
Windows驱动编程之NetFilterSDK
6、规则添加部分,这部分请具体参考官方说明,下面是bypass本地和UDP/TCP重定向规则添加:
    memset(&rule, 0, sizeof(rule));    rule.filteringFlag = NF_ALLOW;    rule.ip_family = AF_INET;    *((unsigned long*)rule.remoteIpAddress) = inet_addr("127.0.0.1");    *((unsigned long*)rule.remoteIpAddressMask) = inet_addr("255.0.0.0");    nf_addRule(&rule, FALSE);     // Filter UDP packets    memset(&rule, 0, sizeof(rule));    rule.ip_family = AF_INET;        //    rule.protocol = IPPROTO_UDP;    // UDP协议    rule.filteringFlag = NF_FILTER;    nf_addRule(&rule, FALSE);     // Filter TCP connect requests    memset(&rule, 0, sizeof(rule));//    rule.ip_family = AF_INET;    rule.protocol = IPPROTO_TCP;   // TCP协议    rule.direction = NF_D_OUT;//    rule.remotePort = htons(443);    rule.filteringFlag = NF_INDICATE_CONNECT_REQUESTS;    nf_addRule(&rule, FALSE);

7、 规则中的Direction字段,NF_FILTER模式EventHandler类将负责处理过滤的数据包,NF_INDICATE_CONNECT_REQUESTS只会触发EventHandler类中的tcpConnectRequest函数(因为该事件只会调用一次虚函数)。

Windows驱动编程之NetFilterSDK
8、Add_rule通过Nfapi发送NF_REQ_ADD_HEAD_RULE /NF_REQ_ADD_TAIL_RULE来实现规则添加:
Windows驱动编程之NetFilterSDK
9、 可以看到通过nf_postData和驱动进行数据传输,通过Write I/O将数据传入到驱动:
Windows驱动编程之NetFilterSDK

除了EventHandler类具体的操作,应用层主要初始化r3所需List_Buffer和Work事件处理线程,和驱动交互通过NfApi来Write_Irp控制驱动。

Driver:


1、DriverEntry首先初始化数据链表,dirver_init初始化devctrl_ioThread和devctrl_injectThread两个线程。

devctrl_ioThread主要用来处理驱动内部的事件处理,如数据包拷贝返回应用层等工作,devctrl_injectThread主要负责不同层数据包重新注入,r3修改完成数据包重新发送Send则会进入到该线程注入:
Windows驱动编程之NetFilterSDK
Devctrl_serviceReads函数中devctrl_fillBuffer如下:

Windows驱动编程之NetFilterSDK

如果是NF_TCP_REINJECT类型会调用devctrl_pushTcpInject,激活devctrl_injectThread事件处理。

2、框架注册Callout层梳理如下,注册了那么多子层为了满足传输层-网络层不通需求的数据拦截,通过应用层规则和标志位来使用驱动层数据即可:
recvSubLayer:    FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4    IPPROTO_TCPFWPM_LAYER_ALE_FLOW_ESTABLISHED_V6    IPPROTO_TCP    FWPM_LAYER_STREAM_V4   FWPM_LAYER_STREAM_V6    FWPM_LAYER_OUTBOUND_TRANSPORT_V4   FWPM_LAYER_INBOUND_TRANSPORT_V6    FWPM_LAYER_ALE_ENDPOINT_CLOSURE_V4    IPPROTO_TCP     FWPM_LAYER_ALE_ENDPOINT_CLOSURE_V6    IPPROTO_TCPpConnectRedirectSubLayer:    FWPM_LAYER_ALE_CONNECT_REDIRECT_V4    IPPROTO_TCP     FWPM_LAYER_ALE_CONNECT_REDIRECT_V6    IPPROTO_TCP  recvPortSubLayer:    FWPM_LAYER_STREAM_V4    FWPM_LAYER_STREAM_V6 subLayer:    FWPM_LAYER_STREAM_V4    FWPM_LAYER_STREAM_V6    FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4    IPPROTO_UDP     FWPM_LAYER_ALE_FLOW_ESTABLISHED_V6    IPPROTO_UDP     FWPM_LAYER_OUTBOUND_TRANSPORT_V4     FWPM_LAYER_INBOUND_TRANSPORT_V6     FWPM_LAYER_ALE_ENDPOINT_CLOSURE_V4      IPPROTO_UDP     FWPM_LAYER_ALE_ENDPOINT_CLOSURE_V6    IPPROTO_UDP     FWPM_LAYER_OUTBOUND_IPPACKET_V4     FWPM_LAYER_INBOUND_IPPACKET_V4     FWPM_LAYER_OUTBOUND_IPPACKET_V6     FWPM_LAYER_INBOUND_IPPACKET_V6 pUdpSubLayer:    FWPM_LAYER_DATAGRAM_DATA_V4        IPPROTO_UDP        FWPM_LAYER_DATAGRAM_DATA_V6        IPPROTO_UDP  pUdpConnectRedirectSubLayer:     FWPM_LAYER_ALE_CONNECT_REDIRECT_V4    IPPROTO_UDP     FWPM_LAYER_ALE_CONNECT_REDIRECT_V6    IPPROTO_UDP

其他更多层注册请参考MSDN;
https://docs.microsoft.com/zh-cn/windows-hardware/drivers/network/management-filtering-layer-identifiers
 
3、通过NfApi发送Write_Irp处理devctrl_dispatch派遣函数,控制码IRP_MJ_WRITE调用devctrl_write.devctrl_processRequest函数处理请求数据:
Windows驱动编程之NetFilterSDK
4、应用层Add_rule驱动中将规则解析加入全局g_lRules链表中,如下所示:

Windows驱动编程之NetFilterSDK



2


重定向


TCP重定向方法和TCP数据修改,客户端连接Server必要的几个步骤:
  • Create socket
  • Connect server
  • Send & Recv
  
WFP每个阶段都提供了对应的筛选器对应GUID,这个过程有很多重定向办法,比如Connect连接直接将目标IP进行重定向,也可以在stearm或者garmdata层(udp)做拦截block,重新注入层(改包)。
 
1、 应用层Main添加了TCP重定向规则才会生效:
// Filter TCP connect requests    memset(&rule, 0, sizeof(rule));//  rule.ip_family = AF_INET;    rule.protocol = IPPROTO_TCP;    rule.direction = NF_D_OUT;//    rule.remotePort = htons(443);    rule.filteringFlag = NF_INDICATE_CONNECT_REQUESTS;    nf_addRule(&rule, FALSE);

2、驱动初始化的时候,会注册callout和过滤器(Driver中的第二步),相关代码如下:
Dirver.callout.c:        status = callouts_addFlowEstablishedFilter(            &g_calloutGuids[CG_ALE_CONNECT_REDIRECT_V4],            &FWPM_LAYER_ALE_CONNECT_REDIRECT_V4,            pConnectRedirectSubLayer);        if (!NT_SUCCESS(status))        {            break;        }CG_ALE_CONNECT_REDIRECT_V4关联的回调函数

Callouts_connectRedirectCallout,如何处理连接操作如下:

首先参数检测,调用callouts_createFlowContext将句柄和五要素等数据,包括判断当前规则状态:

Windows驱动编程之NetFilterSDK


如果NF_INDICATE_CONNECT规则,push:NF_TCP_CONNECT_REQUEST标志:

Windows驱动编程之NetFilterSDK

devctrl_pushTcpData函数负责将保存的数据插入链表,激活g_ioThreadEvent事件如下:

Windows驱动编程之NetFilterSDK

Devctrl_ioThread()负责处理g_ioThreadEvent激活事件,如下:
void devctrl_ioThread(IN PVOID StartContext){  UNREFERENCED_PARAMETER(StartContext);   KdPrint((DPREFIX"devctrl_ioThreadn"));   for(;;)  {      KeWaitForSingleObject(          &g_ioThreadEvent,           Executive,           KernelMode,           FALSE,           NULL       );       if (devctrl_isShutdown())      {          break;      }       devctrl_serviceReads();  }   PsTerminateSystemThread(STATUS_SUCCESS);}

IRP_pakcet完成返回:
pResult->length = devctrl_fillBuffer();irp->IoStatus.Status = STATUS_SUCCESS;irp->IoStatus.Information = sizeof(NF_READ_RESULT);IoCompleteRequest(irp, IO_NO_INCREMENT);

应用层接收到驱动传递来的数据以后,其实激活了处理的事件:
  

通过事件调用EventHandler类的tcpCpnnectRequest函数,然后在应用层函数修改数据,通过nf_postData将数据包发送至驱动:
Windows驱动编程之NetFilterSDK

IRP_MJ_WRITE就会被触发,执行devctrl_processRequest来分发进程的IRP,根据NF标志调用devctrl_processTcpConnect,如下:

Windows驱动编程之NetFilterSDK

基于Connect_Redirect这种方式重定位无法拦截具体的包数据,驱动需要注册Stearm&Established层出入栈条件,将包数据回传到应用层,在Send和Recv时候对数据Buffer进行操作。

Nfsdk框架初始化时候已经注册完成,提供了过滤标志,tcpSend其他的函数生效只需要在tcpConnectRequest函数修改重定向数据后,标志位pConnInfo->filteringFlag标志开启NF_FILTER即可,如下所示:

Windows驱动编程之NetFilterSDK


3


总结
  
驱动负责网络数据捕获,将数据抛到应用层,应用层根据规则过滤、改包。应用层通过接口将修改Packet发送至驱动,注入到对应的层从而闭环,应用层处理数据也会减少了一些风险,健壮性会好一些。
  
NetFilter SDK2.0源码对应用层开发友好,接口文档和示例就可以基于TDI/WFP开发网络防火墙和代理,驱动是透明的。邮件反馈回复及时,有问题他们会给予帮助。

这套代码思路也可以应用到其他方向如MiniFilter,也会有比较好的效果。觉着如果事件这种触发方式换成ALPC通信,r0~r3数据传输会更高效一些。



Windows驱动编程之NetFilterSDK 


看雪ID:一半人生

https://bbs.pediy.com/user-home-819685.htm

*本文由看雪论坛 一半人生 原创,转载请注明来自看雪社区


Windows驱动编程之NetFilterSDK

Windows驱动编程之NetFilterSDK


# 往期推荐

1. CVE-2010-2553 堆溢出漏洞分析

2. MTCTF-PSA-Writeup

3. 【分析记录】疑似Confucius组织组件CuoliVXaRAT分析

4. WOW怀旧服 明文发包获取和HOOK

5. X86内核笔记_2_驱动开发

6. 新的漏洞分析体验:CVE-2010-3333 RTF栈缓冲区溢出漏洞



Windows驱动编程之NetFilterSDK
公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]



Windows驱动编程之NetFilterSDK

球分享

Windows驱动编程之NetFilterSDK

球点赞

Windows驱动编程之NetFilterSDK

球在看



Windows驱动编程之NetFilterSDK

点击“阅读原文”,了解更多!

本文始发于微信公众号(看雪学院):Windows驱动编程之NetFilter SDK

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月15日03:44:07
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Windows驱动编程之NetFilterSDKhttp://cn-sec.com/archives/443149.html

发表评论

匿名网友 填写信息