【问题标题】:Blue screen when rewriting packets at DATAGRAM_DATA layer in WFP在 WFP 中的 DATAGRAM_DATA 层重写数据包时出现蓝屏
【发布时间】:2020-08-01 22:50:35
【问题描述】:

我一直在尝试通过 WFP 中的DATAGRAM_DATA 层修改传出的 DNS 数据包,但是在重写传出数据包中的目标 ip 时出现蓝屏错误。我做错了什么?

我承认我发现 FwpsInjectTransportSendAsync 的参数有点令人困惑,并且不确定究竟应该为 sendParams arg 输入什么 - 尽管我认为我所拥有的看起来是正确的。

RtlIpv4StringToAddressExW(
L"1.1.1.1", // hard-coding the new (rewritten) dns server for now
FALSE,
&sin4.sin_addr,
&sin4.sin_port);

RtlIpv4StringToAddressExW(
    L"8.8.8.8",        // hard-coding the original dns server for now
    FALSE,
    &origSin4.sin_addr,
    &origSin4.sin_port);
if ((Direction == FWP_DIRECTION_OUTBOUND) && (PacketInjectionState == FWPS_PACKET_NOT_INJECTED) && (RemotePort == 53) && (RemoteAddress == origSin4.sin_addr.S_un.S_addr))
{

    UINT32 IpHeaderSize = inMetaValues->ipHeaderSize;
    UINT32 TransportHeaderSize = inMetaValues->transportHeaderSize;
    UINT64 endpointHandle = inMetaValues->transportEndpointHandle;

    PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB((PNET_BUFFER_LIST)layerData);
    NdisRetreatNetBufferDataStart(NetBuffer, IpHeaderSize + TransportHeaderSize, 0, NULL);

    PNET_BUFFER_LIST NetBufferList = NULL;
    NTSTATUS Status = FwpsAllocateCloneNetBufferList(layerData, NULL, NULL, 0, &NetBufferList);
    if (!NT_SUCCESS(Status))
    {
        return;
    }

    NdisAdvanceNetBufferDataStart(NetBuffer, IpHeaderSize + TransportHeaderSize, FALSE, NULL);

    if (!NetBufferList)
    {
        return;
    }

    NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);

    PIPV4_HEADER IpHeader = NdisGetDataBuffer(NetBuffer, sizeof(IPV4_HEADER), NULL, 1, 0);

    // Rewriting the dest ip
    IpHeader->DestinationAddress = sin4.sin_addr.S_un.S_addr;

    // Updating the IP checksum
    UpdateIpv4HeaderChecksum(IpHeader, sizeof(IPV4_HEADER));

    // not 100% sure the sendParams argument is setup correctly, the docs are slightly unclear
    FWPS_TRANSPORT_SEND_PARAMS sendParams = {
        .remoteAddress = (UCHAR*)IpHeader->DestinationAddress,
        .remoteScopeId = inMetaValues->remoteScopeId,
        .controlData = inMetaValues->controlData,
        .controlDataLength = inMetaValues->controlDataLength,
        .headerIncludeHeader = inMetaValues->headerIncludeHeader,
        .headerIncludeHeaderLength = inMetaValues->headerIncludeHeaderLength
    };

    Status = FwpsInjectTransportSendAsync(g_InjectionHandle, NULL, endpointHandle, 0, &sendParams, AF_INET, inMetaValues->compartmentId, NetBufferList, DriverDatagramDataInjectComplete, NULL);
    if (!NT_SUCCESS(Status))
    {
        FwpsFreeCloneNetBufferList(NetBufferList, 0);
    }

    classifyOut->actionType = FWP_ACTION_BLOCK;
    classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
    classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
}

【问题讨论】:

  • 首先你需要做的 - 查看memory.dmp。什么是错误代码,在哪里,调用堆栈。可能是您只是查看代码中导致错误的指令。在任意上下文中可能是(比如 pool(heap) 损坏)错误。错误稳定且可重复(总是在同一个地方)或随机地点/时间。这种需求有问题,但不仅仅是蓝屏
  • @RbMm 哦,这是如此简单/小代码,我认为这个问题对于有 WFP 经验的人来说可能很明显。我如何找到并查看 memory.dmp ?
  • 不,Kernel memory dump 总是有用的,并且使任务更简单。此外 - 在系统重新启动之前 - 位于 pagefile.sys 内的转储 - 如果您在虚拟机上崩溃 - 您可以简单地在 windbg中打开 pagefile.sys > 崩溃后重启前

标签: windows winapi windows-firewall wfp


【解决方案1】:

sendParams 中有两件事对我来说很突出。

首先,remoteAddress 不正确。它需要一个指向地址的指针,所以应该是(UCHAR*)&IpHeader->DestinationAddress

其次,FwpsInjectTransportSendAsync() 是异步的,因此您传递给它的任何参数都需要保持有效,直到它完成,这可能是在您的调用函数返回之后。通常,您分配一些上下文结构,其中包含sendParams 和相关成员的深层副本(remoteAddresscontrolData)。你把它作为上下文传递给你释放它的完成例程。

【讨论】:

  • 谢谢,这是很好的信息。出于兴趣,哪些层支持数据流?我正在尝试在 CONNECT_REDIRECT 层中关联流上下文并在 DATAGRAM_DATA 层中访问它,但我似乎无法在 CONNECT_REDIRECT 层中获得流句柄...
  • CONNECT_REDIRECT 的问题是它在创建流之前被调用。您必须将您的上下文与 AUTH_CONNECT 或 AUTH_FLOW_ESTABLISHED 中的流相关联。
  • 非常感谢!请问你是怎么知道这一切的?我在文档中根本找不到这个信息,你有其他可以链接到的资源吗?
  • 文档、示例代码、论坛帖子和经验的组合。很多这样的东西实际上都在文档中,但要么组织得不好,要么不够明确。
  • 不,我是全职工作,在过去一年左右的时间里才开始从事 WFP 驱动程序的工作。如果我知道答案,我可以回答任何 SO 问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-24
  • 2017-04-03
  • 2011-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多