论文部分内容阅读
摘要:NDIS中间层驱动程序(Intermediate Drivers)位于网卡驱动程序和协议驱动程序之间。对于上层驱动程序而言,它是小端口驱动程序。对于底层的驱动程序,它是协议驱动程序。在NDIS中间层驱动程序中,我们可以实现对数据包的过滤、加密、压缩等操作。据此提出了利用中间层驱动程序进行重新组报发报的解决方案,基于此种方案可以实现网络的封包截获、修改等。
关键词:中间层驱动程序;NDIS;组报;发报
NDIS中间层驱动程序对数据的发送和接收都是通过操作包描述符(Packet Descriptor)完成的。包描述符是一个NDIS_PACKET结构体,驱动程序通过NdisAllocatePacketPoolEx和NdisAllocatePacket两个函数完成包描述符的分配,当包描述符分配成功后,其关联着NDIS_PACKET_OOB_DATA和NDIS_PACKET_EXTENSION两个结构体,它们包含有每个包描述符的out-of-band信息,如发送时间、接收时间、指定的媒体信息、指定NIC是否对数据包进行检验和操作等。中间层驱动程序必须通过NDIS层提供的宏复制上层驱动程序包描述符的out-of-band信息到自己分配的包描述符中,通过NdisSend函数将包描述符传递给底层驱动程序,完成数据包的发送。
NDIS中间层驱动程序发包过程描述如下:
1.Protocol driver调用NdisSend向下层发送数据报文。
2.中间层驱动的MPSend/MPSendPacket例程根据上层传下来的数据报文分配MyPacket,调用NdisSend发送到下层。如果返回pending,就在PtSendComplete中释放我们的MyPacket;否则就在本函数中紧接着释放MyPacket。
3.当下层miniport driver发送完成MyPacket以后,会调用NdisMSendComplete。
4.NDIS接着调用中间层的PtSendComplete,在这个函数里边,我们应该释放MyPacket,并且通知上层protocol driver去释放它们的packet。
方案:修改主机原有发包的数据内容实现对我们数据包的发送。
在NDIS中间层驱动程序中,我们可以通过NDIS层提供的相关函数获取包描述符链接的数据Buffer的虚拟地址,通过该虚拟地址可以得到数据包的内容,也可以通过该虚拟地址修改数据包的内容。具体步骤如图1所示:
1.协议层驱动程序调用NdisSend函数使得中间层驱动程序调用注册的MiniportSendPackets例程。
2.中间层驱动程序复制上层驱动传递的包描述符信息到自己的包描述符中,获取包描述符信息后通过NdisQueryPacket、NdisQueryBufferSafe、NdisGetNextBuffer三个函数得到上层驱动传递的包描述符链接的各个Buffer的虚拟地址。得到Buffer的虚拟地址后修改原始数据包的内容为我们的数据,如果原始数据包的长度小于我们的数据长度,应通过NdisAllocateMemoryWithTag函数分配一个剩余大小的虚拟内存填写剩余的数据。再通过NdisAllocateBuffer函数将虚拟内存转变为Buffer,最后调用NdisChainBufferAtBack将该Buffer链接到包描述符上。数据修改完成后调用NdisSend函数,使得小端口驱动程序调用注册的MiniportSendPackets例程。
3.小端口驱动程序成功发送数据包后,调用完成函数NdisMSendComplete通知中间层驱动程序数据包发送成功。
4.如果中间层驱动在ProtocolSendComplete例程中检测到完成的是我们的数据包,若该包描述符链接过我们分配的Buffer,应调用NdisUnChainBufferAtBack函数去掉链接的Buffer并释放该Buffer。完后释放自己分配的包描述符,调用NdisMSendComplete通知协议驱动程序数据包发送成功。最后设置我们的发送数据包结束事件,通知可以写入新的数据进行发送。
![](https://www.soolun.com/img/pic.php?url=http://img.resource.qikan.cn/qkimages/jxlx/jxlx201007/jxlx201007150-1-l.jpg)
该方案的优点是根据中间层可以修改数据包内容的机制实行对我们数据包的发送,因为不改变中间层的发包机制,程序运行稳定。缺点是改变了主机原有的发包,会影响主机的正常通信。
关键词:中间层驱动程序;NDIS;组报;发报
NDIS中间层驱动程序对数据的发送和接收都是通过操作包描述符(Packet Descriptor)完成的。包描述符是一个NDIS_PACKET结构体,驱动程序通过NdisAllocatePacketPoolEx和NdisAllocatePacket两个函数完成包描述符的分配,当包描述符分配成功后,其关联着NDIS_PACKET_OOB_DATA和NDIS_PACKET_EXTENSION两个结构体,它们包含有每个包描述符的out-of-band信息,如发送时间、接收时间、指定的媒体信息、指定NIC是否对数据包进行检验和操作等。中间层驱动程序必须通过NDIS层提供的宏复制上层驱动程序包描述符的out-of-band信息到自己分配的包描述符中,通过NdisSend函数将包描述符传递给底层驱动程序,完成数据包的发送。
NDIS中间层驱动程序发包过程描述如下:
1.Protocol driver调用NdisSend向下层发送数据报文。
2.中间层驱动的MPSend/MPSendPacket例程根据上层传下来的数据报文分配MyPacket,调用NdisSend发送到下层。如果返回pending,就在PtSendComplete中释放我们的MyPacket;否则就在本函数中紧接着释放MyPacket。
3.当下层miniport driver发送完成MyPacket以后,会调用NdisMSendComplete。
4.NDIS接着调用中间层的PtSendComplete,在这个函数里边,我们应该释放MyPacket,并且通知上层protocol driver去释放它们的packet。
方案:修改主机原有发包的数据内容实现对我们数据包的发送。
在NDIS中间层驱动程序中,我们可以通过NDIS层提供的相关函数获取包描述符链接的数据Buffer的虚拟地址,通过该虚拟地址可以得到数据包的内容,也可以通过该虚拟地址修改数据包的内容。具体步骤如图1所示:
1.协议层驱动程序调用NdisSend函数使得中间层驱动程序调用注册的MiniportSendPackets例程。
2.中间层驱动程序复制上层驱动传递的包描述符信息到自己的包描述符中,获取包描述符信息后通过NdisQueryPacket、NdisQueryBufferSafe、NdisGetNextBuffer三个函数得到上层驱动传递的包描述符链接的各个Buffer的虚拟地址。得到Buffer的虚拟地址后修改原始数据包的内容为我们的数据,如果原始数据包的长度小于我们的数据长度,应通过NdisAllocateMemoryWithTag函数分配一个剩余大小的虚拟内存填写剩余的数据。再通过NdisAllocateBuffer函数将虚拟内存转变为Buffer,最后调用NdisChainBufferAtBack将该Buffer链接到包描述符上。数据修改完成后调用NdisSend函数,使得小端口驱动程序调用注册的MiniportSendPackets例程。
3.小端口驱动程序成功发送数据包后,调用完成函数NdisMSendComplete通知中间层驱动程序数据包发送成功。
4.如果中间层驱动在ProtocolSendComplete例程中检测到完成的是我们的数据包,若该包描述符链接过我们分配的Buffer,应调用NdisUnChainBufferAtBack函数去掉链接的Buffer并释放该Buffer。完后释放自己分配的包描述符,调用NdisMSendComplete通知协议驱动程序数据包发送成功。最后设置我们的发送数据包结束事件,通知可以写入新的数据进行发送。
![](https://www.soolun.com/img/pic.php?url=http://img.resource.qikan.cn/qkimages/jxlx/jxlx201007/jxlx201007150-1-l.jpg)
该方案的优点是根据中间层可以修改数据包内容的机制实行对我们数据包的发送,因为不改变中间层的发包机制,程序运行稳定。缺点是改变了主机原有的发包,会影响主机的正常通信。