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

NdisGetDataBuffer处理入站TCP包返回NULL问题求助

入站TCP数据包拦截时NdisGetDataBuffer返回NULL问题

开发了一款用于拦截入站连接并分析数据包结构的驱动程序,目前遇到异常:处理入站数据包时,NdisGetDataBuffer始终返回NULL,origTcpHeader的值始终为0x0;但处理出站数据包时一切正常,可通过NdisGetDataBuffer成功获取数据包结构。

过滤器与标注点初始化代码

static NTSTATUS InitializeCallout(PDEVICE_OBJECT deviceObject)
{
    FWPM_SUBLAYER subLayer = {};
    subLayer.displayData.name = const_cast<wchar_t*>(L"TcpInterception Sub-Layer");
    subLayer.subLayerKey = TCP_INTERCEPTION_SUBLAYER;

    NTSTATUS status = FwpmSubLayerAdd(g_engineHandle, &subLayer, nullptr);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    FWPS_CALLOUT0 sCallout =
    {
        TCP_INTERCEPTION_INBOUND_TRANSPORT_V4,
        0,
        CalloutConnectClassifyFn,
        CalloutNotifyFn,
        nullptr
    };

    status = FwpsCalloutRegister0(deviceObject, &sCallout, &g_id);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    FWPM_CALLOUT mCallout = {};
    mCallout.calloutKey = TCP_INTERCEPTION_INBOUND_TRANSPORT_V4;
    // INBOUND
    mCallout.applicableLayer = FWPM_LAYER_INBOUND_TRANSPORT_V4;
    mCallout.displayData.name = const_cast<wchar_t*>(g_displayName);

    status = FwpmCalloutAdd(g_engineHandle, &mCallout, nullptr, nullptr);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    FWPM_FILTER_CONDITION filterCondition = {};
    filterCondition.fieldKey = FWPM_CONDITION_IP_PROTOCOL;
    filterCondition.matchType = FWP_MATCH_EQUAL;
    filterCondition.conditionValue.type = FWP_UINT8;
    filterCondition.conditionValue.uint16 = IPPROTO_TCP;

    FWPM_FILTER filter = {};
    // INBOUND
    filter.layerKey = FWPM_LAYER_INBOUND_TRANSPORT_V4;
    filter.displayData.name = const_cast<wchar_t*>(g_displayName);;
    filter.displayData.description = filter.displayData.name;

    filter.action.type = FWP_ACTION_CALLOUT_INSPECTION;
    filter.action.calloutKey = TCP_INTERCEPTION_INBOUND_TRANSPORT_V4;
    filter.filterCondition = &filterCondition;
    filter.numFilterConditions = 1;
    filter.subLayerKey = FWPM_SUBLAYER_INSPECTION;
    filter.weight.type = FWP_EMPTY;

    status = FwpmFilterAdd(g_engineHandle, &filter, NULL, NULL);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    status = FwpsInjectionHandleCreate(AF_UNSPEC, 0, &g_injectionHandle);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    return status;
}

NTSTATUS InitializeFilter(PDEVICE_OBJECT deviceObject)
{
    FWPM_SESSION session = {};
    session.flags = FWPM_SESSION_FLAG_DYNAMIC;

    NTSTATUS status = FwpmEngineOpen(nullptr, RPC_C_AUTHN_WINNT, nullptr, &session, &g_engineHandle);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    NET_BUFFER_LIST_POOL_PARAMETERS netBufferListParameters = {};
    netBufferListParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
    netBufferListParameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
    netBufferListParameters.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
    netBufferListParameters.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
    netBufferListParameters.PoolTag = 'IpcT';
    netBufferListParameters.DataSize = 0;
    netBufferListParameters.fAllocateNetBuffer = TRUE;

    g_netBufferListHandle = NdisAllocateNetBufferListPool(nullptr, &netBufferListParameters);
    if (!g_netBufferListHandle)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    status = FwpmTransactionBegin(g_engineHandle, 0);
    if (!NT_SUCCESS(status))
    {
        return status;
    }

    status = InitializeCallout(deviceObject);
    if (NT_SUCCESS(status))
    {
        FwpmTransactionCommit(g_engineHandle);
    }
    else
    {
        FwpmTransactionAbort(g_engineHandle);
    }

    return status;
}

标注点与数据传输代码

static void ProcessTransportData(const FWPS_INCOMING_VALUES0* inFixedValues,
    const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
    void* layerData,
    FWPS_CLASSIFY_OUT0* classifyOut)
{
    // Test port
    if (inFixedValues->incomingValue[FWPS_FIELD_INBOUND_TRANSPORT_V4_IP_LOCAL_PORT].value.uint16 != 6044)
    {
        return;
    }
    DbgPrint("[!] HIT\n");


    NET_BUFFER_LIST* netBufferList = static_cast<NET_BUFFER_LIST*>(layerData);
    // TCP header always stored in the first NET_BUFFER_LIST
    ASSERT(NET_BUFFER_LIST_NEXT_NBL(netBufferList) == nullptr);

    // For the SYN packet NET_BUFFER_LIST will contain only one net buffer
    NET_BUFFER* netBuffer = reinterpret_cast<PNET_BUFFER>(layerData);

    DbgBreakPoint();

    const auto origTcpHeader = reinterpret_cast<Packet*>(NdisGetDataBuffer(netBuffer, sizeof Packet, nullptr , 1, 0));

    if (!origTcpHeader)
    {
        DbgBreakPoint();
        return;
    }

    for (int i = 0; i < sizeof &origTcpHeader->payload; i++)
        DbgPrint("0x%x ", origTcpHeader->payload[i]);

    DbgBreakPoint();
}

static void CalloutConnectClassifyFn(
    const FWPS_INCOMING_VALUES0* inFixedValues,
    const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
    void* layerData,
    const FWPS_FILTER0* filter,
    UINT64 /*flowContext*/,
    FWPS_CLASSIFY_OUT0* classifyOut)
{
    // Allowing the traffic for another filter to make a final decision.
    if (FlagOn(classifyOut->rights, FWPS_RIGHT_ACTION_WRITE))
    {
        classifyOut->actionType = FWP_ACTION_CONTINUE;
    }

    if (layerData)
    {
        ProcessTransportData(inFixedValues, inMetaValues, layerData, classifyOut);
    }

    // Callout function should clear the FWPS_RIGHT_ACTION_WRITE flag when it returns FWP_ACTION_BLOCK for the suggested action
    // and if FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT flag is set
    if (FWP_ACTION_BLOCK == classifyOut->actionType || FlagOn(filter->flags, FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT))
    {
        ClearFlag(classifyOut->rights, FWPS_RIGHT_ACTION_WRITE);
    }
}

static NTSTATUS CalloutNotifyFn(
    FWPS_CALLOUT_NOTIFY_TYPE /*notifyType*/,
    const GUID* /*filterKey*/,
    FWPS_FILTER0* /*filter*/)
{
    return STATUS_SUCCESS;
}

数据包结构定义

struct TcpHeader
{
    UINT16 source;
    UINT16 dest;
    UINT32 seq;
    UINT32 ackSeq;

    UINT8 ns : 1;
    UINT8 reserved : 3;
    UINT8 offset : 4;

    UINT8 fin : 1;
    UINT8 syn : 1;
    UINT8 rst : 1;
    UINT8 psh : 1;
    UINT8 ack : 1;
    UINT8 urg : 1;
    UINT8 ece : 1;
    UINT8 cwr : 1;

    UINT16 window;
    UINT16 check;
    UINT16 urgPointer;
};

struct Packet
{
    TcpHeader Header;
    UINT8 payload[];
};

GUID定义

DEFINE_GUID(TCP_INTERCEPTION_SUBLAYER, 0xb8f58e09, 0xba43, 0x4837, 0x97, 0x23, 0xad, 0x80, 0x25, 0x8e, 0x8c, 0xa);

DEFINE_GUID(TCP_INTERCEPTION_INBOUND_TRANSPORT_V4, 0x82A99281, 0x0389, 0x4DE2, 0xAE, 0x2D, 0xA4, 0x51, 0x59, 0x16, 0x26, 0x06);

已尝试的操作:

  • 调整过滤器
  • 调整标注点

谷歌搜索过类似问题,但内容要么过时要么与当前情况不匹配,寻求解决方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 02:17:04