You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

内核驱动发送TCP数据包:WFP/NDIS使用求助(C语言开发)

内核态发送TCP数据包的实现方案(针对WFP/NDIS使用困惑)

核心定位澄清

WFP并非专为主动发送数据包设计,它的核心能力是流量过滤、修改与注入;NDIS则是更底层的网络驱动接口,可直接构造并发送完整网络帧。根据你的需求,分两种场景给出实现思路:


方案1:WFP出站注入(适合已有TCP连接或依托现有连接发送数据)

如果目标IP:端口已有活跃TCP连接,或可通过用户态先建立连接再由内核注入数据,WFP是更简便的选择:

步骤拆解

  1. 初始化WFP引擎
    调用FwpmEngineOpen0打开WFP过滤引擎,可选开启事务批量配置规则。
  2. 创建注入句柄
    通过FwpsInjectionHandleCreate0创建注入句柄,指定注入模式(同步/异步)。
  3. 注册过滤规则
    注册针对FWPM_LAYER_OUTBOUND_TRANSPORT_V4层的过滤规则,精确匹配目标地址192.168.1.105:32500,在过滤回调中触发注入逻辑。
  4. 构造并注入数据包
    填充FWPS_TRANSPORT_SEND_PARAMS0结构体指定源/目标地址、端口,分配内核缓冲区存储待发送数据,调用FwpsInjectTransportSendAsync0完成注入。

简化代码示例

NTSTATUS InjectKernelTcpPacket(FWPS_INJECTION_HANDLE injectionHandle)
{
    NTSTATUS status = STATUS_SUCCESS;
    FWPS_TRANSPORT_SEND_PARAMS0 sendParams = {0};
    const CHAR sendData[] = "Kernel-sent TCP data";
    const SIZE_T dataLen = sizeof(sendData);
    
    // 设置目标地址与端口(转换为网络字节序)
    sendParams.remoteAddressV4 = (IPV4_ADDRESS){.Byte = {192, 168, 1, 105}};
    sendParams.remotePort = RtlUshortByteSwap(32500);
    sendParams.localPort = RtlUshortByteSwap(12345); // 自定义本地端口

    // 分配非分页内存(内核态必须用此类内存分配函数)
    PVOID dataBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, dataLen, 'TCPK');
    if (!dataBuffer)
        return STATUS_INSUFFICIENT_RESOURCES;
    RtlCopyMemory(dataBuffer, sendData, dataLen);

    // 执行注入
    status = FwpsInjectTransportSendAsync0(
        injectionHandle,
        NULL, NULL, 0, AF_INET,
        &sendParams, NULL,
        dataBuffer, &dataLen,
        NULL // 同步模式下可忽略完成回调
    );

    ExFreePoolWithTag(dataBuffer, 'TCPK');
    return status;
}
  1. 资源清理
    注入完成后,调用FwpsInjectionHandleDestroy0销毁句柄,FwpmEngineClose0关闭WFP引擎。

方案2:NDIS直接构造发送TCP帧(适合自定义完整TCP包,含握手)

如果需要主动发起TCP连接(构造SYN/SYN-ACK/ACK握手包)或完全自定义网络帧,需使用NDIS:

步骤拆解

  1. 枚举并打开目标网络适配器
    枚举系统中能访问192.168.1.0/24段的网络适配器,调用NdisOpenAdapterEx打开适配器句柄。
  2. 构造完整网络帧
    依次构造以太网帧头、IP头、TCP头与数据段:
    • 以太网帧:指定目的MAC(网关MAC)、源MAC(适配器MAC)、帧类型0x0800(IP协议)
    • IP头:设置版本4、协议6(TCP)、源/目标IP、计算IP校验和(用NdisComputeIpChecksum)
    • TCP头:设置源/目标端口、序列号、标志位(如SYN用于握手)、计算TCP校验和(用NdisComputeTcpChecksum)
  3. 发送数据包
    将构造好的帧封装为NET_BUFFER_LIST,调用NdisSendNetBufferLists发送。

关键注意事项

  • 驱动签名:Windows内核驱动必须签名,测试阶段可启用测试签名模式。
  • 内存管理:内核态必须使用ExAllocatePoolWithTag/ExFreePoolWithTag分配释放内存,优先选择NonPagedPoolNx避免执行漏洞。
  • 字节序转换:所有端口、IP地址等多字节字段需转换为网络字节序(大端),使用RtlUshortByteSwap/RtlUlongByteSwap。
  • TCP握手:若需主动建立连接,需自行实现TCP三次握手逻辑,WFP无法直接完成此过程。

内容的提问来源于stack exchange,提问作者trapstar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 07:20:29