其他
Windows驱动编程之NetFilter SDK
看雪论坛作者ID:一半人生
官网:https://netfiltersdk.com
官网帮助:https://netfiltersdk.com/help/nfsdk2/
如果对Windows网络驱动没有概念,请先看:https://bbs.pediy.com/thread-268468.htm
1
源码分析
R3/Nfapi:
if (!ReadFile(g_hDevice, &rr, sizeof(rr), NULL, &ol))
{
if (GetLastError() != ERROR_IO_PENDING)
goto finish;
}
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函数(因为该事件只会调用一次虚函数)。
除了EventHandler类具体的操作,应用层主要初始化r3所需List_Buffer和Work事件处理线程,和驱动交互通过NfApi来Write_Irp控制驱动。
Driver:
devctrl_ioThread主要用来处理驱动内部的事件处理,如数据包拷贝返回应用层等工作,devctrl_injectThread主要负责不同层数据包重新注入,r3修改完成数据包重新发送Send则会进入到该线程注入:
2、框架注册Callout层梳理如下,注册了那么多子层为了满足传输层-网络层不通需求的数据拦截,通过应用层规则和标志位来使用驱动层数据即可:
recvSubLayer:
FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4 IPPROTO_TCP
FWPM_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_TCP
pConnectRedirectSubLayer:
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
2
Create socket Connect server Send & Recv
// 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);
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关联的回调函数
void devctrl_ioThread(IN PVOID StartContext)
{
UNREFERENCED_PARAMETER(StartContext);
KdPrint((DPREFIX"devctrl_ioThread\n"));
for(;;)
{
KeWaitForSingleObject(
&g_ioThreadEvent,
Executive,
KernelMode,
FALSE,
NULL
);
if (devctrl_isShutdown())
{
break;
}
devctrl_serviceReads();
}
PsTerminateSystemThread(STATUS_SUCCESS);
}
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将数据包发送至驱动:
3
总结
看雪ID:一半人生
https://bbs.pediy.com/user-home-819685.htm
*本文由看雪论坛 一半人生 原创,转载请注明来自看雪社区
# 往期推荐
3. 【分析记录】疑似Confucius组织组件CuoliVXaRAT分析
6. 新的漏洞分析体验:CVE-2010-3333 RTF栈缓冲区溢出漏洞
球分享
球点赞
球在看
点击“阅读原文”,了解更多!