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
相关产品推荐
相关产品推荐

