NDIS-Hook技术的工作机制是挂接网络驱动NDIS. SYS的函数库中的导出函数,在发向NDIS的请求之前就会被挂接并经过自己函数的处理。在W indows实现NDIS-Hook时有两种不同的思路可以利用。

①对内核驱动NDIS. SYS的Export table进行Hook 在Windows 下,可执行文件(包括DLL以及SYS)都是遵从PE(Portable Exe-cutable)[2]格式的。NDIS. SYS向其它操作系统组件提供接口,故NDIS. SYS有Export table,因此只要实现对关键NDISAPI的挂接。由于协议驱动程序在系统启动的时候会调用NdisRegisterProtocol来向系统进行协议注册,因此这种方法关键在于修改NDIS. SYS所提供的NdisRegisterProtocol、Ndis-DeRegisterProtocol、NdisOpenAdapter、NdisSend等函数的起始地址。NDIS. SYS位于系统的核心内存区,通过内核态的驱动程序来实现。

②向系统注册假协议(fake protocol) 在W in-dows内核中,所有已注册的协议通过一个单向的协议链表来维护。这个单向链表保存了所有已注册协议NDIS_PROTOCOL_BLOCK结构的地址,在这个结构中保存了协议驱动所指定的相应派发函数的地址如RECEIVE_HANDLER等。并且,每个协议驱动还对应一个NDIS_OPEN_BLOCK的单向链表来维护其所绑定的网卡信息[3]。当协议驱动调用NdisRegisterProtocol之后,NDIS总是会把新注册的协议放在协议链表的表头并返回这张表,所以只要注册一个新的协议通过新协议注册返回的链表头就可以轻而易举的遍历系统中所有协议表。但是,如果要成功地挂接派发函数,还需要对协议所对应的NDIS_OPEN_BLOCK结构里的派发函数进行挂接,因为NDIS并不是直接调用协议驱动在NDIS_PROTOCOL_CHARACTERISTICS所注册的派发函数地址,而是调用NDIS_OPEN_BLOCK里的派发函数。在Windows DDK中,并没有该结构的详细定义,也就是说该结构在Windows下是非公开的,因此要采用逆向工程利用各种调试工具来发掘该结构的详细定义[具体实现方法可以参考www.lunwenroom.com/jisuanjilei/127.html]。

上面的第2种思路对平台的依赖性比较大,需要在程序中判断不同的操作系统版本并使用不同的结构定义。本文采用第1种方法对NDIS. SYS的导出函数进行挂接。另外Windows提供了系统内存保护机制,因此在修改NDIS. SYS前还需要禁用Win-dows的内存保护,使只读内存区可写。编程采用嵌入汇编来实现对内存属性的操作,在NDIS. SYS加载后对其相应的输出函数进行挂接,就可以在自己的函数中实现对网络数据的分析控制。