问题描述
我有一个NDIS筛选器驱动程序(请参阅https://pastebin.com/c5r87NNw)和一个用户空间应用程序。
我想使用过滤器驱动程序(在功能 curl --location --request POST 'https://login.microsoftonline.com/{client-id-of-app-registered-in-b2c}/oauth2/v2.0/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: x-ms-gateway-slice=prod; stsservicecookie=ests; fpc=AmqL7OwikMNGgdpvjdkb0OLnguDtAQAAABl14NYOAAAAd_wwNgEAAABCeeDWDgAAAA' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_secret={secret-of-app}' \
--data-urlencode 'client_id={client-id-of-app-registered-in-b2c}' \
--data-urlencode 'scope=https://graph.microsoft.com/.default'
中)发送任意数据包。我在功能SendData
中通过DbgPrint可以看到我已经收到了数据包,但是在 WireShark 中找不到该数据包。
只要来自FilterReceiveNetBufferLists
的代码被调用或直接粘贴到SendData
函数中,它就可以正常工作。但是现在,由于FilterSendNetBufferLists
的执行是由用户空间应用程序触发的,因此它不再起作用。
您有什么可能的猜测吗?
解决方法
Wireshark是一件有趣的事情,因为它不一定告诉您确切的事实。如果可能的话,我建议在另一台PC上运行Wireshark,这将使您对电线上的实际情况有更清晰的了解。 (从最纯粹的角度来看:请禁用另一台PC的硬件卸载,尤其是RSC,因此另一台PC的NIC不会在捕获数据包之前先处理它们。)
较旧版本的Wireshark具有名为NPF的NDIS5协议驱动程序。这个家伙坐在所有过滤器驱动程序的上方,因此他通常不会看到任何Tx流量。但是作为这种情况的特殊让步,NDIS将把Tx路径循环回到Rx路径(设置了NDIS_NBL_FLAGS_IS_LOOPBACK_PACKET
标志),因此像NPF这样的旧驱动程序可以在其Rx路径中看到Tx数据包的副本。
最近,npcap项目将旧的NPF驱动程序转换为名为NPCAP的NDIS6 LWF。由于多种原因,此驱动程序要好得多,但要记住的一件事是,作为过滤器驱动程序,它位于过滤器堆栈中的某个位置。如果它位于您的LWF之上,那么它将看不到您传输(或修改)的任何数据包。
使用!ndiskd.miniport进行检查,以查看计算机上的wireshark是什么样的:它是一个名为NPF的协议,还是一个名为NPCAP的筛选器驱动程序。如果是后者,它是在过滤器驱动程序之上还是之下?
无论如何,这就是说,您不能完全将Wireshark与要测试的驱动程序放在同一盒子上。在单独的机器上进行数据包捕获会更好,更容易。
对于您的代码,请确保您的FilterSendNetBufferListsComplete处理程序正在查找所有NBL,并删除其NET_BUFFER_LIST :: SourceHandle等于您的OriginalNdisFilterHandle
的NBL。那些应该被释放回NdisFreeNetBufferList(或缓存以供以后重用,但是NDIS已经做了不错的缓存工作)。您可能已经有了该代码,但并没有将其添加到pastebin中。
我看不到任何会导致Tx总是失败的东西。您确实需要跟踪过滤器的暂停状态,并在暂停时阻止(或排队)Tx操作。因此,您的SendData函数可以这样编写:
NTSTATUS SendData(MY_FILTER *filter) {
if (!ExAcquireRundownProtection(&filter->PauseRundown)) {
return STATUS_NDIS_PAUSED;
}
. . . allocate and send NBL . . .;
return STATUS_SUCCESS;
}
void FilterSendNetBufferListsComplete(MY_FILTER *filter,NET_BUFFER_LIST *nblChain) {
for (auto nbl = nblChain; nbl; nbl = nbl->Next) {
if (nbl->SourceHandle == filter->NdisHandle) {
. . . detach NBL from chain . . .;
. . . free NBL back to NDIS . . .;
ExReleaseRundownProtection(&filter->PauseRundown);
}
}
}
void FilterPause(MY_FILTER *filter) {
ExWaitForRundownProtectionRelease(&filter->PauseRundown);
}
void FilterRestart(MY_FILTER *filter) {
ExReInitializeRundownProtection(&filter->PauseRundown);
}
如果弄错了,那么有时在发送数据包时NDIS将崩溃。如果您不幸在数据路径暂停的情况下发送它们,则某些数据包也将悄悄地无法发送。 (解决此问题不会神奇地导致数据包始终能够成功传输-这只是意味着它不再安静了:当NIC尚未准备就绪时,尝试发送数据包时会看到STATUS_NDIS_PAUSED。 )
,我成功了:错误出在我的OriginalNdisFilterHandle
中。我在函数FilterAttach
中进行了设置,但并不认为该函数会被多次调用。因此,该变量的值有误。