如何在 Windows 上使用 LWF driver 将数据包注入接收 (Rx) 路径?
How to inject packets into Receive (Rx) path using LWF driver on Windows?
我正在开发一个基于 WinPcap 的 NDIS 6 Light-weight 过滤器 (LWF) driver。我们可以想象网络适配器有两条路径:Tx
和 Rx
.
Tx
为发送方式
Rx
为接收方式
我们知道 WinPcap 能够向网络发送数据包(所以这是 Tx
方式)。我想知道是否可以将数据包发送到 Rx
,所以这意味着 将数据包注入适配器并假装该数据包是来自网络的到达数据包 .
首先我不知道这是否可行?如果是,那么继续阅读:
我已经编写了代码,使用NdisFIndicateReceiveNetBufferLists
调用将我制作的数据包指示给上层,然后在FilterReturnNetBufferLists
处理程序中释放数据包。所以包括Windows OS在内的上层模块会知道有一个新的数据包从网络传来(实际上不是事实)。
但是,我的方法行不通。我使用 Nping
(来自 Nmap)来 ping 我的网关,nping window 冻结,甚至任务管理器也无法终止它。所以它一定是driver停止。
我注意到这种方式应该可行 基于:
Jeffery 对 post 的回答:Is FilterSendNetBufferLists handler a must for an NDIS filter to use NdisFSendNetBufferLists?
来自微软的解释:https://msdn.microsoft.com/en-us/library/windows/hardware/ff570452(v=vs.85).aspx
OSR提供的例子:https://www.osronline.com/showthread.cfm?link=242847
然后我分析了driver打印的日志。似乎我的 NdisFIndicateReceiveNetBufferLists
调用(用于发送到 Rx
)只调用了一次,然后 driver 用于其他工作,而环 3 nping
已死。我重用了来自 NPF_SendCompleteEx
的现有 well-running 代码中的大部分代码(这是将完成发送到正常 Tx
的处理程序)。所以我觉得这部分不会有bug吧?
整个代码库托管在 GitHub 上:https://github.com/nmap/npcap
它不包含此 post 中的错误代码,因为我尚未提交它,但如果您需要,它会提供一些背景知识:)
我的注入代码:
NTSTATUS
NPF_Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
POPEN_INSTANCE Open;
POPEN_INSTANCE GroupOpen;
POPEN_INSTANCE TempOpen;
PIO_STACK_LOCATION IrpSp;
ULONG SendFlags = 0;
PNET_BUFFER_LIST pNetBufferList;
NDIS_STATUS Status;
ULONG NumSends;
ULONG numSentPackets;
TRACE_ENTER();
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open = IrpSp->FileObject->FsContext;
if (NPF_StartUsingOpenInstance(Open) == FALSE)
{
//
// an IRP_MJ_CLEANUP was received, just fail the request
//
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_CANCELLED;
}
NumSends = Open->Nwrites;
//
// validate the send parameters set by the IOCTL
//
if (NumSends == 0)
{
NPF_StopUsingOpenInstance(Open);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_SUCCESS;
}
//
// Validate input parameters:
// 1. The packet size should be greater than 0,
// 2. less-equal than max frame size for the link layer and
// 3. the maximum frame size of the link layer should not be zero.
//
if (IrpSp->Parameters.Write.Length == 0 || // Check that the buffer provided by the user is not empty
Open->MaxFrameSize == 0 || // Check that the MaxFrameSize is correctly initialized
Irp->MdlAddress == NULL ||
IrpSp->Parameters.Write.Length > Open->MaxFrameSize) // Check that the fame size is smaller that the MTU
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Frame size out of range, or maxFrameSize = 0. Send aborted");
NPF_StopUsingOpenInstance(Open);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_UNSUCCESSFUL;
}
//
// Increment the ref counter of the binding handle, if possible
//
if (NPF_StartUsingBinding(Open) == FALSE)
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Adapter is probably unbinding, cannot send packets");
NPF_StopUsingOpenInstance(Open);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_INVALID_DEVICE_REQUEST;
}
NdisAcquireSpinLock(&Open->WriteLock);
if (Open->WriteInProgress)
{
// Another write operation is currently in progress
NdisReleaseSpinLock(&Open->WriteLock);
NPF_StopUsingBinding(Open);
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Another Send operation is in progress, aborting.");
NPF_StopUsingOpenInstance(Open);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_UNSUCCESSFUL;
}
else
{
Open->WriteInProgress = TRUE;
NdisResetEvent(&Open->NdisWriteCompleteEvent);
}
NdisReleaseSpinLock(&Open->WriteLock);
TRACE_MESSAGE2(PACKET_DEBUG_LOUD,
"Max frame size = %u, packet size = %u",
Open->MaxFrameSize,
IrpSp->Parameters.Write.Length);
//
// reset the number of packets pending the SendComplete
//
Open->TransmitPendingPackets = 0;
NdisResetEvent(&Open->WriteEvent);
numSentPackets = 0;
while (numSentPackets < NumSends)
{
pNetBufferList = NdisAllocateNetBufferAndNetBufferList(Open->PacketPool,
0,
0,
Irp->MdlAddress,
0,
Irp->MdlAddress->ByteCount);
if (pNetBufferList != NULL)
{
//
// packet is available, prepare it and send it with NdisSend.
//
//
// If asked, set the flags for this packet.
// Currently, the only situation in which we set the flags is to disable the reception of loopback
// packets, i.e. of the packets sent by us.
//
//if (Open->SkipSentPackets)
//{
// NPFSetNBLFlags(pNetBufferList, g_SendPacketFlags);
//}
// The packet hasn't a buffer that needs not to be freed after every single write
RESERVED(pNetBufferList)->FreeBufAfterWrite = FALSE;
// Save the IRP associated with the packet
// RESERVED(pPacket)->Irp=Irp;
// Attach the writes buffer to the packet
InterlockedIncrement(&Open->TransmitPendingPackets);
NdisResetEvent(&Open->NdisWriteCompleteEvent);
//receive the packets before sending them
ASSERT(Open->GroupHead != NULL);
if (Open->GroupHead != NULL)
{
GroupOpen = Open->GroupHead->GroupNext;
}
else
{
//this is impossible
GroupOpen = Open->GroupNext;
}
#ifdef HAVE_WFP_LOOPBACK_SUPPORT
// Do not capture the send traffic we send, if this is our loopback adapter.
if (Open->Loopback == FALSE)
{
#endif
while (GroupOpen != NULL)
{
TempOpen = GroupOpen;
if (TempOpen->AdapterBindingStatus == ADAPTER_BOUND && TempOpen->SkipSentPackets == FALSE)
{
NPF_TapExForEachOpen(TempOpen, pNetBufferList);
}
GroupOpen = TempOpen->GroupNext;
}
#ifdef HAVE_WFP_LOOPBACK_SUPPORT
}
#endif
pNetBufferList->SourceHandle = Open->AdapterHandle;
NPFSetNBLChildOpen(pNetBufferList, Open); //save the child open object in the packets
//SendFlags |= NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK;
// Recognize IEEE802.1Q tagged packet, as no many adapters support VLAN tag packet sending, no much use for end users,
// and this code examines the data which lacks efficiency, so I left it commented, the sending part is also unfinished.
// This code refers to Win10Pcap at https://github.com/SoftEtherVPN/Win10Pcap.
// if (Open->Loopback == FALSE)
// {
// PUCHAR pHeaderBuffer;
// UINT iFres;
//
// BOOLEAN withVlanTag = FALSE;
// UINT VlanID = 0;
// UINT VlanUserPriority = 0;
// UINT VlanCanFormatID = 0;
//
// NdisQueryMdl(
// Irp->MdlAddress,
// &pHeaderBuffer,
// &iFres,
// NormalPagePriority);
//
// // Determine if the packet is IEEE802.1Q tagged packet.
// if (iFres >= 18)
// {
// if (pHeaderBuffer[12] == 0x81 && pHeaderBuffer[13] == 0x00)
// {
// USHORT pTmpVlanTag = 0;
//
// ((UCHAR *)(&pTmpVlanTag))[0] = pHeaderBuffer[15];
// ((UCHAR *)(&pTmpVlanTag))[1] = pHeaderBuffer[14];
//
// VlanID = pTmpVlanTag & 0x0FFF;
// VlanUserPriority = (pTmpVlanTag >> 13) & 0x07;
// VlanCanFormatID = (pTmpVlanTag >> 12) & 0x01;
//
// if (VlanID != 0)
// {
// withVlanTag = TRUE;
// }
// }
// }
// }
//
// Call the MAC
//
#ifdef HAVE_WFP_LOOPBACK_SUPPORT
if (Open->Loopback == TRUE)
{
NPF_LoopbackSendNetBufferLists(Open->GroupHead,
pNetBufferList);
}
else
#endif
#ifdef HAVE_SEND_TO_RECEIVE_PATH_SUPPORT
if (Open->SendToRxPath == TRUE)
{
IF_LOUD(DbgPrint("hahahahahahahahahahahaha:: SendToRxPath, Open->AdapterHandle=%p, pNetBufferList=%u\n", Open->AdapterHandle, pNetBufferList);)
// pretend to receive these packets from network and indicate them to upper layers
NdisFIndicateReceiveNetBufferLists(
Open->AdapterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
1,
0);
}
else
#endif
{
NdisFSendNetBufferLists(Open->AdapterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
SendFlags);
}
numSentPackets ++;
}
else
{
//
// no packets are available in the Transmit pool, wait some time. The
// event gets signalled when at least half of the TX packet pool packets
// are available
//
NdisWaitEvent(&Open->WriteEvent, 1);
}
}
//
// when we reach this point, all the packets have been enqueued to NdisSend,
// we just need to wait for all the packets to be completed by the SendComplete
// (if any of the NdisSend requests returned STATUS_PENDING)
//
NdisWaitEvent(&Open->NdisWriteCompleteEvent, 0);
//
// all the packets have been transmitted, release the use of the adapter binding
//
NPF_StopUsingBinding(Open);
//
// no more writes are in progress
//
NdisAcquireSpinLock(&Open->WriteLock);
Open->WriteInProgress = FALSE;
NdisReleaseSpinLock(&Open->WriteLock);
NPF_StopUsingOpenInstance(Open);
//
// Complete the Irp and return success
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = IrpSp->Parameters.Write.Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_SUCCESS;
}
我的 FilterReturnNetBufferLists 处理程序:
_Use_decl_annotations_
VOID
NPF_ReturnEx(
NDIS_HANDLE FilterModuleContext,
PNET_BUFFER_LIST NetBufferLists,
ULONG ReturnFlags
)
/*++
Routine Description:
FilterReturnNetBufferLists handler.
FilterReturnNetBufferLists is an optional function. If provided, NDIS calls
FilterReturnNetBufferLists to return the ownership of one or more NetBufferLists
and their embedded NetBuffers to the filter driver. If this handler is NULL, NDIS
will skip calling this filter when returning NetBufferLists to the underlying
miniport and will call the next lower driver in the stack. A filter that doesn't
provide a FilterReturnNetBufferLists handler cannot originate a receive indication
on its own.
Arguments:
FilterInstanceContext - our filter context area
NetBufferLists - a linked list of NetBufferLists that this
filter driver indicated in a previous call to
NdisFIndicateReceiveNetBufferLists
ReturnFlags - flags specifying if the caller is at DISPATCH_LEVEL
--*/
{
POPEN_INSTANCE ChildOpen;
POPEN_INSTANCE GroupOpen;
POPEN_INSTANCE TempOpen;
BOOLEAN FreeBufAfterWrite;
PNET_BUFFER_LIST pNetBufList;
PNET_BUFFER_LIST pNextNetBufList;
PNET_BUFFER Currbuff;
PMDL pMdl;
POPEN_INSTANCE Open = (POPEN_INSTANCE) FilterModuleContext;
TRACE_ENTER();
#ifdef HAVE_SEND_TO_RECEIVE_PATH_SUPPORT
pNetBufList = NetBufferLists;
while (pNetBufList != NULL)
{
pNextNetBufList = NET_BUFFER_LIST_NEXT_NBL(pNetBufList);
NET_BUFFER_LIST_NEXT_NBL(pNetBufList) = NULL;
if (pNetBufList->SourceHandle == Open->AdapterHandle) //this is our self-sent packets
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "hahahaha This is my own send to Rx packets");
ChildOpen = NPFGetNBLChildOpen(pNetBufList); //get the child open object that sends these packets
FreeBufAfterWrite = RESERVED(pNetBufList)->FreeBufAfterWrite;
if (FreeBufAfterWrite)
{
//
// Packet sent by NPF_BufferedWrite()
//
//Free the NBL allocate by myself
Currbuff = NET_BUFFER_LIST_FIRST_NB(pNetBufList);
while (Currbuff)
{
pMdl = NET_BUFFER_FIRST_MDL(Currbuff);
NdisFreeMdl(pMdl); //Free MDL
Currbuff = NET_BUFFER_NEXT_NB(Currbuff);
}
NdisFreeNetBufferList(pNetBufList); //Free NBL
}
else
{
//
// Packet sent by NPF_Write()
//
//Free the NBL allocate by myself
NdisFreeNetBufferList(pNetBufList); //Free NBL
}
// this if should always be false, as Open is always the GroupHead itself, only GroupHead is known by NDIS and get invoked in NPF_SendCompleteEx() function.
if (Open->GroupHead != NULL)
{
GroupOpen = Open->GroupHead->GroupNext;
}
else
{
GroupOpen = Open->GroupNext;
}
//GroupOpen = Open->GroupNext;
while (GroupOpen != NULL)
{
TempOpen = GroupOpen;
if (ChildOpen == TempOpen) //only indicate the specific child open object
{
NPF_SendCompleteExForEachOpen(TempOpen, FreeBufAfterWrite);
break;
}
GroupOpen = TempOpen->GroupNext;
}
}
else
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "hahahaha This is NOT my own send to Rx packets");
// Return the received NBLs. If you removed any NBLs from the chain, make
// sure the chain isn't empty (i.e., NetBufferLists!=NULL).
NdisFReturnNetBufferLists(Open->AdapterHandle, pNetBufList, ReturnFlags);
}
pNetBufList = pNextNetBufList;
}
#else
// Return the received NBLs. If you removed any NBLs from the chain, make
// sure the chain isn't empty (i.e., NetBufferLists!=NULL).
NdisFReturnNetBufferLists(Open->AdapterHandle, NetBufferLists, ReturnFlags);
#endif
TRACE_EXIT();
}
我的日志:
00010269 58.36443710 MDL 42
00010270 58.36444092 hahahahahahahahahahahaha:: SendToRxPath, Open->AdapterHandle=FFFFFA8003C24010, pNetBufferList=68928096
00010271 58.36450577 --> NPF_ReturnEx
00010272 58.36450577 NPF_ReturnEx: hahahaha This is my own send to Rx packets
00010273 58.36451340 <-- NPF_ReturnEx
00010274 59.04499054 --> NPF_NetworkClassify
00010275 59.04499817 --> NPF_IsPacketSelfSent
00010276 59.04499817 <-- NPF_IsPacketSelfSent
00010277 59.04499817 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010278 59.04500961 <-- NPF_NetworkClassify
00010279 59.04502869 --> NPF_SendEx
00010280 59.04503632 --> NPF_SendCompleteEx
00010281 59.04504395 <-- NPF_SendCompleteEx
00010282 59.04504395 <-- NPF_SendEx
00010283 59.04520798 --> NPF_NetworkClassify
00010284 59.04520798 --> NPF_IsPacketSelfSent
00010285 59.04521561 <-- NPF_IsPacketSelfSent
00010286 59.04521561 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010287 59.04522324 <-- NPF_NetworkClassify
00010288 59.04529953 --> NPF_SendEx
00010289 59.04529953 --> NPF_SendCompleteEx
00010290 59.04530716 <-- NPF_SendCompleteEx
00010291 59.04530716 <-- NPF_SendEx
00010292 59.04531097 --> NPF_NetworkClassify
00010293 59.04531097 --> NPF_IsPacketSelfSent
00010294 59.04531097 <-- NPF_IsPacketSelfSent
00010295 59.04531860 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010296 59.04531860 <-- NPF_NetworkClassify
00010297 59.04541397 --> NPF_NetworkClassify
00010298 59.04541397 --> NPF_IsPacketSelfSent
00010299 59.04541397 <-- NPF_IsPacketSelfSent
00010300 59.04542160 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010301 59.04542160 <-- NPF_NetworkClassify
00010302 59.04543304 --> NPF_SendEx
00010303 59.04543304 Received on CPU 0 3
00010304 59.04544067 Received on CPU 0 2
00010305 59.04544067 MDL 62
00010306 59.04544067 next MDL 24 and added
00010307 59.04544830 --> NPF_SendCompleteEx
00010308 59.04547882 <-- NPF_SendCompleteEx
00010309 59.04548645 <-- NPF_SendEx
00010310 59.04558563 --> NPF_NetworkClassify
00010311 59.04558563 --> NPF_IsPacketSelfSent
00010312 59.04558563 <-- NPF_IsPacketSelfSent
00010313 59.04559326 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010314 59.04560089 <-- NPF_NetworkClassify
00010315 59.04560471 --> NPF_SendEx
00010316 59.04561234 Received on CPU 0 4
00010317 59.04561234 Received on CPU 0 3
00010318 59.04561234 MDL 42
00010319 59.04561996 next MDL 24 and added
00010320 59.04561996 --> NPF_SendCompleteEx
00010321 59.04562378 <-- NPF_SendCompleteEx
00010322 59.04562378 <-- NPF_SendEx
00010323 59.15098953 --> NPF_NetworkClassify
00010324 59.15098953 --> NPF_IsPacketSelfSent
00010325 59.15099335 <-- NPF_IsPacketSelfSent
00010326 59.15099335 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010327 59.15103912 <-- NPF_NetworkClassify
00010328 59.15105820 --> NPF_SendEx
00010329 59.15106583 --> NPF_SendCompleteEx
00010330 59.15106583 <-- NPF_SendCompleteEx
00010331 59.15106583 <-- NPF_SendEx
00010332 59.15113449 --> NPF_NetworkClassify
00010333 59.15113449 --> NPF_IsPacketSelfSent
00010334 59.15114212 <-- NPF_IsPacketSelfSent
00010335 59.15114212 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010336 59.15114975 <-- NPF_NetworkClassify
00010337 59.15118027 --> NPF_SendEx
00010338 59.15118027 --> NPF_SendCompleteEx
00010339 59.15118790 <-- NPF_SendCompleteEx
00010340 59.15118790 <-- NPF_SendEx
00010341 59.15118790 --> NPF_NetworkClassify
00010342 59.15119171 --> NPF_IsPacketSelfSent
00010343 59.15119171 <-- NPF_IsPacketSelfSent
00010344 59.15119171 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010345 59.15119934 <-- NPF_NetworkClassify
00010346 59.15123367 --> NPF_NetworkClassify
00010347 59.15123749 --> NPF_IsPacketSelfSent
00010348 59.15123749 <-- NPF_IsPacketSelfSent
00010349 59.15123749 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010350 59.15124512 <-- NPF_NetworkClassify
00010351 59.15125275 --> NPF_SendEx
00010352 59.15125275 Received on CPU 1 1
00010353 59.15125656 Received on CPU 1 1
00010354 59.15132904 MDL 62
00010355 59.15133286 next MDL 24 and added
00010356 59.15134048 --> NPF_SendCompleteEx
00010357 59.15134811 <-- NPF_SendCompleteEx
00010358 59.15134811 <-- NPF_SendEx
00010359 59.15138626 --> NPF_NetworkClassify
00010360 59.15138626 --> NPF_IsPacketSelfSent
00010361 59.15138626 <-- NPF_IsPacketSelfSent
00010362 59.15139389 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010363 59.15139771 <-- NPF_NetworkClassify
00010364 59.15140533 --> NPF_SendEx
00010365 59.15140533 Received on CPU 1 2
00010366 59.15140533 Received on CPU 1 2
00010367 59.15141296 MDL 42
00010368 59.15141296 next MDL 24 and added
00010369 59.15141296 --> NPF_SendCompleteEx
00010370 59.15141678 <-- NPF_SendCompleteEx
00010371 59.15141678 <-- NPF_SendEx
00010372 59.19804001 --> NPF_SendEx
00010373 59.19805527 --> NPF_SendCompleteEx
00010374 59.19805527 <-- NPF_SendCompleteEx
00010375 59.19805527 <-- NPF_SendEx
00010376 59.35518646 --> NPF_NetworkClassify
00010377 59.35519409 --> NPF_IsPacketSelfSent
00010378 59.35519409 <-- NPF_IsPacketSelfSent
00010379 59.35519409 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010380 59.35520554 <-- NPF_NetworkClassify
00010381 59.35526276 --> NPF_SendEx
00010382 59.35527039 --> NPF_SendCompleteEx
00010383 59.35527802 <-- NPF_SendCompleteEx
00010384 59.35527802 <-- NPF_SendEx
00010385 59.35528183 --> NPF_NetworkClassify
00010386 59.35528183 --> NPF_IsPacketSelfSent
00010387 59.35528183 <-- NPF_IsPacketSelfSent
00010388 59.35528946 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010389 59.35528946 <-- NPF_NetworkClassify
00010390 59.35543823 --> NPF_NetworkClassify
00010391 59.35543823 --> NPF_IsPacketSelfSent
00010392 59.35543823 <-- NPF_IsPacketSelfSent
00010393 59.35544205 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010394 59.35544968 <-- NPF_NetworkClassify
00010395 59.35546112 --> NPF_SendEx
00010396 59.35546875 Received on CPU 0 5
00010397 59.35546875 Received on CPU 0 4
00010398 59.35547638 MDL 42
00010399 59.35547638 next MDL 50 and added
00010400 59.35548019 --> NPF_SendCompleteEx
00010401 59.35548019 <-- NPF_SendCompleteEx
00010402 59.35548782 <-- NPF_SendEx
00010403 59.47556305 --> NPF_TapEx
00010404 59.47557068 --> NPF_ReturnEx
00010405 59.47557068 NPF_ReturnEx: hahahaha This is NOT my own send to Rx packets
00010406 59.47557068 <-- NPF_ReturnEx
00010407 59.47557831 <-- NPF_TapEx
00010408 59.58328247 --> NPF_TapEx
00010409 59.58329773 --> NPF_ReturnEx
00010410 59.58329773 NPF_ReturnEx: hahahaha This is NOT my own send to Rx packets
00010411 59.58329773 <-- NPF_ReturnEx
00010412 59.58329773 <-- NPF_TapEx
00010413 59.58549881 --> NPF_TapEx
00010414 59.58550262 --> NPF_ReturnEx
00010415 59.58551025 NPF_ReturnEx: hahahaha This is NOT my own send to Rx packets
00010416 59.58551025 <-- NPF_ReturnEx
00010417 59.58551025 <-- NPF_TapEx
00010418 60.11791992 --> NPF_NetworkClassify
00010419 60.11791992 --> NPF_IsPacketSelfSent
00010420 60.11792755 <-- NPF_IsPacketSelfSent
00010421 60.11792755 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010422 60.11793900 <-- NPF_NetworkClassify
00010423 60.11795807 --> NPF_SendEx
00010424 60.11796570 Received on CPU 0 6
00010425 60.11796570 Received on CPU 0 5
00010426 60.11796951 MDL 42
00010427 60.11796951 next MDL 50 and added
正确的做法是根据 MSDN 使用 NdisFIndicateReceiveNetBufferLists:https://msdn.microsoft.com/en-us/library/windows/hardware/ff570448(v=vs.85).aspx
我正在开发一个基于 WinPcap 的 NDIS 6 Light-weight 过滤器 (LWF) driver。我们可以想象网络适配器有两条路径:Tx
和 Rx
.
Tx
为发送方式
Rx
为接收方式
我们知道 WinPcap 能够向网络发送数据包(所以这是 Tx
方式)。我想知道是否可以将数据包发送到 Rx
,所以这意味着 将数据包注入适配器并假装该数据包是来自网络的到达数据包 .
首先我不知道这是否可行?如果是,那么继续阅读:
我已经编写了代码,使用NdisFIndicateReceiveNetBufferLists
调用将我制作的数据包指示给上层,然后在FilterReturnNetBufferLists
处理程序中释放数据包。所以包括Windows OS在内的上层模块会知道有一个新的数据包从网络传来(实际上不是事实)。
但是,我的方法行不通。我使用 Nping
(来自 Nmap)来 ping 我的网关,nping window 冻结,甚至任务管理器也无法终止它。所以它一定是driver停止。
我注意到这种方式应该可行 基于:
Jeffery 对 post 的回答:Is FilterSendNetBufferLists handler a must for an NDIS filter to use NdisFSendNetBufferLists?
来自微软的解释:https://msdn.microsoft.com/en-us/library/windows/hardware/ff570452(v=vs.85).aspx
OSR提供的例子:https://www.osronline.com/showthread.cfm?link=242847
然后我分析了driver打印的日志。似乎我的 NdisFIndicateReceiveNetBufferLists
调用(用于发送到 Rx
)只调用了一次,然后 driver 用于其他工作,而环 3 nping
已死。我重用了来自 NPF_SendCompleteEx
的现有 well-running 代码中的大部分代码(这是将完成发送到正常 Tx
的处理程序)。所以我觉得这部分不会有bug吧?
整个代码库托管在 GitHub 上:https://github.com/nmap/npcap
它不包含此 post 中的错误代码,因为我尚未提交它,但如果您需要,它会提供一些背景知识:)
我的注入代码:
NTSTATUS
NPF_Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
POPEN_INSTANCE Open;
POPEN_INSTANCE GroupOpen;
POPEN_INSTANCE TempOpen;
PIO_STACK_LOCATION IrpSp;
ULONG SendFlags = 0;
PNET_BUFFER_LIST pNetBufferList;
NDIS_STATUS Status;
ULONG NumSends;
ULONG numSentPackets;
TRACE_ENTER();
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open = IrpSp->FileObject->FsContext;
if (NPF_StartUsingOpenInstance(Open) == FALSE)
{
//
// an IRP_MJ_CLEANUP was received, just fail the request
//
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_CANCELLED;
}
NumSends = Open->Nwrites;
//
// validate the send parameters set by the IOCTL
//
if (NumSends == 0)
{
NPF_StopUsingOpenInstance(Open);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_SUCCESS;
}
//
// Validate input parameters:
// 1. The packet size should be greater than 0,
// 2. less-equal than max frame size for the link layer and
// 3. the maximum frame size of the link layer should not be zero.
//
if (IrpSp->Parameters.Write.Length == 0 || // Check that the buffer provided by the user is not empty
Open->MaxFrameSize == 0 || // Check that the MaxFrameSize is correctly initialized
Irp->MdlAddress == NULL ||
IrpSp->Parameters.Write.Length > Open->MaxFrameSize) // Check that the fame size is smaller that the MTU
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Frame size out of range, or maxFrameSize = 0. Send aborted");
NPF_StopUsingOpenInstance(Open);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_UNSUCCESSFUL;
}
//
// Increment the ref counter of the binding handle, if possible
//
if (NPF_StartUsingBinding(Open) == FALSE)
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Adapter is probably unbinding, cannot send packets");
NPF_StopUsingOpenInstance(Open);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_INVALID_DEVICE_REQUEST;
}
NdisAcquireSpinLock(&Open->WriteLock);
if (Open->WriteInProgress)
{
// Another write operation is currently in progress
NdisReleaseSpinLock(&Open->WriteLock);
NPF_StopUsingBinding(Open);
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Another Send operation is in progress, aborting.");
NPF_StopUsingOpenInstance(Open);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_UNSUCCESSFUL;
}
else
{
Open->WriteInProgress = TRUE;
NdisResetEvent(&Open->NdisWriteCompleteEvent);
}
NdisReleaseSpinLock(&Open->WriteLock);
TRACE_MESSAGE2(PACKET_DEBUG_LOUD,
"Max frame size = %u, packet size = %u",
Open->MaxFrameSize,
IrpSp->Parameters.Write.Length);
//
// reset the number of packets pending the SendComplete
//
Open->TransmitPendingPackets = 0;
NdisResetEvent(&Open->WriteEvent);
numSentPackets = 0;
while (numSentPackets < NumSends)
{
pNetBufferList = NdisAllocateNetBufferAndNetBufferList(Open->PacketPool,
0,
0,
Irp->MdlAddress,
0,
Irp->MdlAddress->ByteCount);
if (pNetBufferList != NULL)
{
//
// packet is available, prepare it and send it with NdisSend.
//
//
// If asked, set the flags for this packet.
// Currently, the only situation in which we set the flags is to disable the reception of loopback
// packets, i.e. of the packets sent by us.
//
//if (Open->SkipSentPackets)
//{
// NPFSetNBLFlags(pNetBufferList, g_SendPacketFlags);
//}
// The packet hasn't a buffer that needs not to be freed after every single write
RESERVED(pNetBufferList)->FreeBufAfterWrite = FALSE;
// Save the IRP associated with the packet
// RESERVED(pPacket)->Irp=Irp;
// Attach the writes buffer to the packet
InterlockedIncrement(&Open->TransmitPendingPackets);
NdisResetEvent(&Open->NdisWriteCompleteEvent);
//receive the packets before sending them
ASSERT(Open->GroupHead != NULL);
if (Open->GroupHead != NULL)
{
GroupOpen = Open->GroupHead->GroupNext;
}
else
{
//this is impossible
GroupOpen = Open->GroupNext;
}
#ifdef HAVE_WFP_LOOPBACK_SUPPORT
// Do not capture the send traffic we send, if this is our loopback adapter.
if (Open->Loopback == FALSE)
{
#endif
while (GroupOpen != NULL)
{
TempOpen = GroupOpen;
if (TempOpen->AdapterBindingStatus == ADAPTER_BOUND && TempOpen->SkipSentPackets == FALSE)
{
NPF_TapExForEachOpen(TempOpen, pNetBufferList);
}
GroupOpen = TempOpen->GroupNext;
}
#ifdef HAVE_WFP_LOOPBACK_SUPPORT
}
#endif
pNetBufferList->SourceHandle = Open->AdapterHandle;
NPFSetNBLChildOpen(pNetBufferList, Open); //save the child open object in the packets
//SendFlags |= NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK;
// Recognize IEEE802.1Q tagged packet, as no many adapters support VLAN tag packet sending, no much use for end users,
// and this code examines the data which lacks efficiency, so I left it commented, the sending part is also unfinished.
// This code refers to Win10Pcap at https://github.com/SoftEtherVPN/Win10Pcap.
// if (Open->Loopback == FALSE)
// {
// PUCHAR pHeaderBuffer;
// UINT iFres;
//
// BOOLEAN withVlanTag = FALSE;
// UINT VlanID = 0;
// UINT VlanUserPriority = 0;
// UINT VlanCanFormatID = 0;
//
// NdisQueryMdl(
// Irp->MdlAddress,
// &pHeaderBuffer,
// &iFres,
// NormalPagePriority);
//
// // Determine if the packet is IEEE802.1Q tagged packet.
// if (iFres >= 18)
// {
// if (pHeaderBuffer[12] == 0x81 && pHeaderBuffer[13] == 0x00)
// {
// USHORT pTmpVlanTag = 0;
//
// ((UCHAR *)(&pTmpVlanTag))[0] = pHeaderBuffer[15];
// ((UCHAR *)(&pTmpVlanTag))[1] = pHeaderBuffer[14];
//
// VlanID = pTmpVlanTag & 0x0FFF;
// VlanUserPriority = (pTmpVlanTag >> 13) & 0x07;
// VlanCanFormatID = (pTmpVlanTag >> 12) & 0x01;
//
// if (VlanID != 0)
// {
// withVlanTag = TRUE;
// }
// }
// }
// }
//
// Call the MAC
//
#ifdef HAVE_WFP_LOOPBACK_SUPPORT
if (Open->Loopback == TRUE)
{
NPF_LoopbackSendNetBufferLists(Open->GroupHead,
pNetBufferList);
}
else
#endif
#ifdef HAVE_SEND_TO_RECEIVE_PATH_SUPPORT
if (Open->SendToRxPath == TRUE)
{
IF_LOUD(DbgPrint("hahahahahahahahahahahaha:: SendToRxPath, Open->AdapterHandle=%p, pNetBufferList=%u\n", Open->AdapterHandle, pNetBufferList);)
// pretend to receive these packets from network and indicate them to upper layers
NdisFIndicateReceiveNetBufferLists(
Open->AdapterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
1,
0);
}
else
#endif
{
NdisFSendNetBufferLists(Open->AdapterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
SendFlags);
}
numSentPackets ++;
}
else
{
//
// no packets are available in the Transmit pool, wait some time. The
// event gets signalled when at least half of the TX packet pool packets
// are available
//
NdisWaitEvent(&Open->WriteEvent, 1);
}
}
//
// when we reach this point, all the packets have been enqueued to NdisSend,
// we just need to wait for all the packets to be completed by the SendComplete
// (if any of the NdisSend requests returned STATUS_PENDING)
//
NdisWaitEvent(&Open->NdisWriteCompleteEvent, 0);
//
// all the packets have been transmitted, release the use of the adapter binding
//
NPF_StopUsingBinding(Open);
//
// no more writes are in progress
//
NdisAcquireSpinLock(&Open->WriteLock);
Open->WriteInProgress = FALSE;
NdisReleaseSpinLock(&Open->WriteLock);
NPF_StopUsingOpenInstance(Open);
//
// Complete the Irp and return success
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = IrpSp->Parameters.Write.Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
TRACE_EXIT();
return STATUS_SUCCESS;
}
我的 FilterReturnNetBufferLists 处理程序:
_Use_decl_annotations_
VOID
NPF_ReturnEx(
NDIS_HANDLE FilterModuleContext,
PNET_BUFFER_LIST NetBufferLists,
ULONG ReturnFlags
)
/*++
Routine Description:
FilterReturnNetBufferLists handler.
FilterReturnNetBufferLists is an optional function. If provided, NDIS calls
FilterReturnNetBufferLists to return the ownership of one or more NetBufferLists
and their embedded NetBuffers to the filter driver. If this handler is NULL, NDIS
will skip calling this filter when returning NetBufferLists to the underlying
miniport and will call the next lower driver in the stack. A filter that doesn't
provide a FilterReturnNetBufferLists handler cannot originate a receive indication
on its own.
Arguments:
FilterInstanceContext - our filter context area
NetBufferLists - a linked list of NetBufferLists that this
filter driver indicated in a previous call to
NdisFIndicateReceiveNetBufferLists
ReturnFlags - flags specifying if the caller is at DISPATCH_LEVEL
--*/
{
POPEN_INSTANCE ChildOpen;
POPEN_INSTANCE GroupOpen;
POPEN_INSTANCE TempOpen;
BOOLEAN FreeBufAfterWrite;
PNET_BUFFER_LIST pNetBufList;
PNET_BUFFER_LIST pNextNetBufList;
PNET_BUFFER Currbuff;
PMDL pMdl;
POPEN_INSTANCE Open = (POPEN_INSTANCE) FilterModuleContext;
TRACE_ENTER();
#ifdef HAVE_SEND_TO_RECEIVE_PATH_SUPPORT
pNetBufList = NetBufferLists;
while (pNetBufList != NULL)
{
pNextNetBufList = NET_BUFFER_LIST_NEXT_NBL(pNetBufList);
NET_BUFFER_LIST_NEXT_NBL(pNetBufList) = NULL;
if (pNetBufList->SourceHandle == Open->AdapterHandle) //this is our self-sent packets
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "hahahaha This is my own send to Rx packets");
ChildOpen = NPFGetNBLChildOpen(pNetBufList); //get the child open object that sends these packets
FreeBufAfterWrite = RESERVED(pNetBufList)->FreeBufAfterWrite;
if (FreeBufAfterWrite)
{
//
// Packet sent by NPF_BufferedWrite()
//
//Free the NBL allocate by myself
Currbuff = NET_BUFFER_LIST_FIRST_NB(pNetBufList);
while (Currbuff)
{
pMdl = NET_BUFFER_FIRST_MDL(Currbuff);
NdisFreeMdl(pMdl); //Free MDL
Currbuff = NET_BUFFER_NEXT_NB(Currbuff);
}
NdisFreeNetBufferList(pNetBufList); //Free NBL
}
else
{
//
// Packet sent by NPF_Write()
//
//Free the NBL allocate by myself
NdisFreeNetBufferList(pNetBufList); //Free NBL
}
// this if should always be false, as Open is always the GroupHead itself, only GroupHead is known by NDIS and get invoked in NPF_SendCompleteEx() function.
if (Open->GroupHead != NULL)
{
GroupOpen = Open->GroupHead->GroupNext;
}
else
{
GroupOpen = Open->GroupNext;
}
//GroupOpen = Open->GroupNext;
while (GroupOpen != NULL)
{
TempOpen = GroupOpen;
if (ChildOpen == TempOpen) //only indicate the specific child open object
{
NPF_SendCompleteExForEachOpen(TempOpen, FreeBufAfterWrite);
break;
}
GroupOpen = TempOpen->GroupNext;
}
}
else
{
TRACE_MESSAGE(PACKET_DEBUG_LOUD, "hahahaha This is NOT my own send to Rx packets");
// Return the received NBLs. If you removed any NBLs from the chain, make
// sure the chain isn't empty (i.e., NetBufferLists!=NULL).
NdisFReturnNetBufferLists(Open->AdapterHandle, pNetBufList, ReturnFlags);
}
pNetBufList = pNextNetBufList;
}
#else
// Return the received NBLs. If you removed any NBLs from the chain, make
// sure the chain isn't empty (i.e., NetBufferLists!=NULL).
NdisFReturnNetBufferLists(Open->AdapterHandle, NetBufferLists, ReturnFlags);
#endif
TRACE_EXIT();
}
我的日志:
00010269 58.36443710 MDL 42
00010270 58.36444092 hahahahahahahahahahahaha:: SendToRxPath, Open->AdapterHandle=FFFFFA8003C24010, pNetBufferList=68928096
00010271 58.36450577 --> NPF_ReturnEx
00010272 58.36450577 NPF_ReturnEx: hahahaha This is my own send to Rx packets
00010273 58.36451340 <-- NPF_ReturnEx
00010274 59.04499054 --> NPF_NetworkClassify
00010275 59.04499817 --> NPF_IsPacketSelfSent
00010276 59.04499817 <-- NPF_IsPacketSelfSent
00010277 59.04499817 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010278 59.04500961 <-- NPF_NetworkClassify
00010279 59.04502869 --> NPF_SendEx
00010280 59.04503632 --> NPF_SendCompleteEx
00010281 59.04504395 <-- NPF_SendCompleteEx
00010282 59.04504395 <-- NPF_SendEx
00010283 59.04520798 --> NPF_NetworkClassify
00010284 59.04520798 --> NPF_IsPacketSelfSent
00010285 59.04521561 <-- NPF_IsPacketSelfSent
00010286 59.04521561 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010287 59.04522324 <-- NPF_NetworkClassify
00010288 59.04529953 --> NPF_SendEx
00010289 59.04529953 --> NPF_SendCompleteEx
00010290 59.04530716 <-- NPF_SendCompleteEx
00010291 59.04530716 <-- NPF_SendEx
00010292 59.04531097 --> NPF_NetworkClassify
00010293 59.04531097 --> NPF_IsPacketSelfSent
00010294 59.04531097 <-- NPF_IsPacketSelfSent
00010295 59.04531860 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010296 59.04531860 <-- NPF_NetworkClassify
00010297 59.04541397 --> NPF_NetworkClassify
00010298 59.04541397 --> NPF_IsPacketSelfSent
00010299 59.04541397 <-- NPF_IsPacketSelfSent
00010300 59.04542160 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010301 59.04542160 <-- NPF_NetworkClassify
00010302 59.04543304 --> NPF_SendEx
00010303 59.04543304 Received on CPU 0 3
00010304 59.04544067 Received on CPU 0 2
00010305 59.04544067 MDL 62
00010306 59.04544067 next MDL 24 and added
00010307 59.04544830 --> NPF_SendCompleteEx
00010308 59.04547882 <-- NPF_SendCompleteEx
00010309 59.04548645 <-- NPF_SendEx
00010310 59.04558563 --> NPF_NetworkClassify
00010311 59.04558563 --> NPF_IsPacketSelfSent
00010312 59.04558563 <-- NPF_IsPacketSelfSent
00010313 59.04559326 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010314 59.04560089 <-- NPF_NetworkClassify
00010315 59.04560471 --> NPF_SendEx
00010316 59.04561234 Received on CPU 0 4
00010317 59.04561234 Received on CPU 0 3
00010318 59.04561234 MDL 42
00010319 59.04561996 next MDL 24 and added
00010320 59.04561996 --> NPF_SendCompleteEx
00010321 59.04562378 <-- NPF_SendCompleteEx
00010322 59.04562378 <-- NPF_SendEx
00010323 59.15098953 --> NPF_NetworkClassify
00010324 59.15098953 --> NPF_IsPacketSelfSent
00010325 59.15099335 <-- NPF_IsPacketSelfSent
00010326 59.15099335 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010327 59.15103912 <-- NPF_NetworkClassify
00010328 59.15105820 --> NPF_SendEx
00010329 59.15106583 --> NPF_SendCompleteEx
00010330 59.15106583 <-- NPF_SendCompleteEx
00010331 59.15106583 <-- NPF_SendEx
00010332 59.15113449 --> NPF_NetworkClassify
00010333 59.15113449 --> NPF_IsPacketSelfSent
00010334 59.15114212 <-- NPF_IsPacketSelfSent
00010335 59.15114212 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010336 59.15114975 <-- NPF_NetworkClassify
00010337 59.15118027 --> NPF_SendEx
00010338 59.15118027 --> NPF_SendCompleteEx
00010339 59.15118790 <-- NPF_SendCompleteEx
00010340 59.15118790 <-- NPF_SendEx
00010341 59.15118790 --> NPF_NetworkClassify
00010342 59.15119171 --> NPF_IsPacketSelfSent
00010343 59.15119171 <-- NPF_IsPacketSelfSent
00010344 59.15119171 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010345 59.15119934 <-- NPF_NetworkClassify
00010346 59.15123367 --> NPF_NetworkClassify
00010347 59.15123749 --> NPF_IsPacketSelfSent
00010348 59.15123749 <-- NPF_IsPacketSelfSent
00010349 59.15123749 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010350 59.15124512 <-- NPF_NetworkClassify
00010351 59.15125275 --> NPF_SendEx
00010352 59.15125275 Received on CPU 1 1
00010353 59.15125656 Received on CPU 1 1
00010354 59.15132904 MDL 62
00010355 59.15133286 next MDL 24 and added
00010356 59.15134048 --> NPF_SendCompleteEx
00010357 59.15134811 <-- NPF_SendCompleteEx
00010358 59.15134811 <-- NPF_SendEx
00010359 59.15138626 --> NPF_NetworkClassify
00010360 59.15138626 --> NPF_IsPacketSelfSent
00010361 59.15138626 <-- NPF_IsPacketSelfSent
00010362 59.15139389 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010363 59.15139771 <-- NPF_NetworkClassify
00010364 59.15140533 --> NPF_SendEx
00010365 59.15140533 Received on CPU 1 2
00010366 59.15140533 Received on CPU 1 2
00010367 59.15141296 MDL 42
00010368 59.15141296 next MDL 24 and added
00010369 59.15141296 --> NPF_SendCompleteEx
00010370 59.15141678 <-- NPF_SendCompleteEx
00010371 59.15141678 <-- NPF_SendEx
00010372 59.19804001 --> NPF_SendEx
00010373 59.19805527 --> NPF_SendCompleteEx
00010374 59.19805527 <-- NPF_SendCompleteEx
00010375 59.19805527 <-- NPF_SendEx
00010376 59.35518646 --> NPF_NetworkClassify
00010377 59.35519409 --> NPF_IsPacketSelfSent
00010378 59.35519409 <-- NPF_IsPacketSelfSent
00010379 59.35519409 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010380 59.35520554 <-- NPF_NetworkClassify
00010381 59.35526276 --> NPF_SendEx
00010382 59.35527039 --> NPF_SendCompleteEx
00010383 59.35527802 <-- NPF_SendCompleteEx
00010384 59.35527802 <-- NPF_SendEx
00010385 59.35528183 --> NPF_NetworkClassify
00010386 59.35528183 --> NPF_IsPacketSelfSent
00010387 59.35528183 <-- NPF_IsPacketSelfSent
00010388 59.35528946 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010389 59.35528946 <-- NPF_NetworkClassify
00010390 59.35543823 --> NPF_NetworkClassify
00010391 59.35543823 --> NPF_IsPacketSelfSent
00010392 59.35543823 <-- NPF_IsPacketSelfSent
00010393 59.35544205 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010394 59.35544968 <-- NPF_NetworkClassify
00010395 59.35546112 --> NPF_SendEx
00010396 59.35546875 Received on CPU 0 5
00010397 59.35546875 Received on CPU 0 4
00010398 59.35547638 MDL 42
00010399 59.35547638 next MDL 50 and added
00010400 59.35548019 --> NPF_SendCompleteEx
00010401 59.35548019 <-- NPF_SendCompleteEx
00010402 59.35548782 <-- NPF_SendEx
00010403 59.47556305 --> NPF_TapEx
00010404 59.47557068 --> NPF_ReturnEx
00010405 59.47557068 NPF_ReturnEx: hahahaha This is NOT my own send to Rx packets
00010406 59.47557068 <-- NPF_ReturnEx
00010407 59.47557831 <-- NPF_TapEx
00010408 59.58328247 --> NPF_TapEx
00010409 59.58329773 --> NPF_ReturnEx
00010410 59.58329773 NPF_ReturnEx: hahahaha This is NOT my own send to Rx packets
00010411 59.58329773 <-- NPF_ReturnEx
00010412 59.58329773 <-- NPF_TapEx
00010413 59.58549881 --> NPF_TapEx
00010414 59.58550262 --> NPF_ReturnEx
00010415 59.58551025 NPF_ReturnEx: hahahaha This is NOT my own send to Rx packets
00010416 59.58551025 <-- NPF_ReturnEx
00010417 59.58551025 <-- NPF_TapEx
00010418 60.11791992 --> NPF_NetworkClassify
00010419 60.11791992 --> NPF_IsPacketSelfSent
00010420 60.11792755 <-- NPF_IsPacketSelfSent
00010421 60.11792755 NPF_NetworkClassify: NPF_NetworkClassify: NPF_IsPacketSelfSent() [bSelfSent: 0]
00010422 60.11793900 <-- NPF_NetworkClassify
00010423 60.11795807 --> NPF_SendEx
00010424 60.11796570 Received on CPU 0 6
00010425 60.11796570 Received on CPU 0 5
00010426 60.11796951 MDL 42
00010427 60.11796951 next MDL 50 and added
正确的做法是根据 MSDN 使用 NdisFIndicateReceiveNetBufferLists:https://msdn.microsoft.com/en-us/library/windows/hardware/ff570448(v=vs.85).aspx