c++ NdisGetDataBuffer返回空值

rekjcdws  于 2023-03-20  发布在  其他
关注(0)|答案(1)|浏览(152)

我想从传入连接中提取TCP数据包。我创建了一个驱动程序,该驱动程序应拦截入站连接并分析数据包结构。由于未知原因,数据包到达时,NdisGetDataBuffer总是返回null。此外,当驱动程序处理OUTBOUND数据包并且成功从NdisGetDataBuffer中获取数据包结构时,一切正常。但它不适用于INBOUND数据包。处理INBOUND数据包时,origTcpHeader的值始终等于0x0
过滤器和标注的初始化。

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[];
};

指南

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);

我试过:

  • 更换过滤器
  • 更改注解

我也在谷歌上找过类似的问题,但都是过时或不相似的。

lymnna71

lymnna711#

在层中基于where the offset is set执行adjust the offset。在您的特定情况下,在INBOUND_TRANSPORT层,偏移量指向传输数据的开头。要获取传输头,您需要后退传输头的大小(inMetaValues->transportHeaderSize),访问数据,然后前进相同的大小,然后从回调返回。

相关问题