我想从传入连接中提取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);
我试过:
- 更换过滤器
- 更改注解
我也在谷歌上找过类似的问题,但都是过时或不相似的。
1条答案
按热度按时间lymnna711#
在层中基于where the offset is set执行adjust the offset。在您的特定情况下,在INBOUND_TRANSPORT层,偏移量指向传输数据的开头。要获取传输头,您需要后退传输头的大小(
inMetaValues->transportHeaderSize
),访问数据,然后前进相同的大小,然后从回调返回。