一、背景
利用NdisAllocateNetBufferAndNetBufferList和NdisCopySendNetBufferListInfo生成和克隆出来的修改过的包,发出去后wireshark没抓到,说明修改后的网络包没有发出去。
二、分析
一开始以为是因为我们改的包头不合规导致包发布出去,但是排查后发现,没发出去的都是内容大于1472的UDP包,一般来说,整个包大于1500的udp包都需要分片,先看看ndislwf中分片是如何表示的
NBL(NetBufferList)结构指向一个NB(NetBuffer)链表,每个NB会关联MDL,MDL所关联的内容就是我们的包的内容,每个NB代表一个分片,调用NdisAllocateFragmentNetBufferList可以将一个包分片,用多个NB结构表示,调试可以看到,filtersend函数接收到的包的确是有多个分片的,但是,克隆NBL的时候,只克隆了NBL的一些属性,克隆出来的包只包含了第一个分片,所以这样子会导致后面的分片丢失,导致包异常发不出去了
三、解决:
查NDIS文档可以看到,NDIS有提供组合的API,NdisAllocateReassembledNetBufferList,可以将多个NB结构组合成一个,把分片的内容连起来,因此我们可以先把filter拦截到的带多个NB的NBL组合成只有一个NB的NBL,然后再克隆这个组合后的NBL,这时候我们得到“克隆的只带一个NB的NBL”,这样就可以用我们原来的逻辑去对这个包进行修改,并重新计算checksum,这时候把这个包用NdisFSendNetBufferLists发送出去,发现还是发不出。后来想filter接收到的是带分片的包,但是我们发出去的是没有分片的包,可能是这个原因导致了NDIS没有将这个包发出去,于是我再用NdisAllocateFragmentNetBufferList把修改好的NBL重新分片,再发,就可以正常发出去了。