NDIS 6.0中有了一个新框架,号称比NDIS IMD更牛B。开始关注这个东西是因为卡巴的防火墙取个名字叫Kaspersky Anti-Virus NDIS Filter ,又听说WDK中才有新框架,但是卡巴老早就在用了,就觉得卡巴真牛。(后来看Filter 的时候,自己的Filter驱动既不能在编译到XP平台的,编译VISTA的安装上去也没用,怀疑卡巴就是一个IMD的驱动,取了个名字NDIS Filter 而已,有空F5下。)
说正题,微软建议使用NDIS Filter替代NDIS IMD。Filter Driver比IMD驱动更容易实现,Filter驱动被插入在Miniport驱动和Protocol Driver之间。Filter Driver会 attach到Miniport Driver上,对于Protocol Driver来说,Filter Driver是透明的。Filter Driver与任何设备对象无关。Filter Driver可以动态的安装和卸载。在IMD驱动的里面,你需要注册一个Miniport和Protocol两层驱动。(所以以前的IMD有两个相关联的 INF文件。)Filter驱动就没那么麻烦,直接一步搞定。我也不会怎么写理论的文章直接看图吧!
如下图所示:
Filter Driver 框架介绍
WDK中\src\network\ndis\filter中Filter的主要框架,在MSDN文档里面有对这个框架的详细解释,这里我们只简单说几个 函数。
DriverEntry
// NDIS调用这个函数为一些数据结构分配内存和作初始化工作
// 主要的结构体有:
//NDIS_FILTER_DRIVER_CHARACTERISTICS 指定一些Filter驱动的特性,并把这些参数传给NDIS。
// 主要的函数:
// NdisFRegisterFilterDriver 把Filter驱动注册给NDIS
FilterAttach
// NDIS调用这个函数为一些数据结构分配内存和作初始化工作
// 主要的结构体有:
// NDIS_FILTER_ATTACH_PARAMETERS 初始化参数
// NDIS_FILTER_ATTRIBUTES Filter模块的属性
FilterRegisterDevice
// 填充分派函数,初始化设备属性。并注册。
// 主要的结构体有:
// NDIS_FILTER_ATTACH_PARAMETERS 初始化参数
// NDIS_FILTER_ATTRIBUTES Filter模块的属性
FilterSendNetBufferLists
// 用这个函数去过滤一个NET_BUFFER_LIST的发送
// 主要的结构体有:
// NET_BUFFER_LIST NET_BUFFER的链表
FilterReceiveNetBufferLists
// 用这个函数去过滤一个NET_BUFFER_LIST的接收
// 主要的结构体有:
// NET_BUFFER_LIST NET_BUFFER的链表
如果要读取数据包,那么有两个结构体就相当重要了。它们是NET_BUFFER_LIST和 NET_BUFFER。定义如下:
typedef struct _NET_BUFFER_LIST{ NET_BUFFER_LIST_HEADER NetBufferListHeader; PNET_BUFFER_LIST_CONTEXT Context; PNET_BUFFER_LIST ParentNetBufferList; NDIS_HANDLE NdisPoolHandle; DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)PVOID NdisReserved[2]; DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)PVOID ProtocolReserved[4]; DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)PVOID MiniportReserved[2]; PVOID Scratch; NDIS_HANDLE SourceHandle; ULONG NblFlags; LONG ChildRefCount; ULONG Flags; NDIS_STATUS Status; PVOID NetBufferListInfo[MaxNetBufferListInfo]; }NET_BUFFER_LIST,*PNET_BUFFER_LIST; typedef struct _NET_BUFFER { NET_BUFFER_HEADER NetBufferHeader; USHORT ChecksumBias; USHORT Reserved; NDIS_HANDLE NdisPoolHandle; DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)PVOID NdisReserved[2]; DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)PVOID ProtocolReserved[6]; DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)PVOID MiniportReserved[4]; NDIS_PHYSICAL_ADDRESS DataPhysicalAddress; // was NdisReserved1; } NET_BUFFER, *PNET_BUFFER;
另外,还有一些宏定义。
NET_BUFFER_LIST_FIRST_NB 从NET_BUFFER_LIST结构中获得第一个NDIS_BUFFER
NET_BUFFER_DATA_OFFSET 从NDIS_BUFFER中获得DATA的偏移
NET_BUFFER_FIRST_MDL 从NDIS_BUFFER中获得第一个MDL
NET_BUFFER_DATA_LENGTH 取得DATA的长度
更具体的自己去看MSDN了。 我根据MSDN和GOOGLE的指点大概写了一段代码了读取数据包。读出数据包的地址和长度。
void ReadNetBuffer( PNET_BUFFER_LIST NetBufferLists ) { PUCHAR data,info; ULONG len,i,offset=0; PNET_BUFFER_LIST CurrNbl; PNET_BUFFER Currbuff; PMDL mdl; int DataLen; CurrNbl = NetBufferLists; while (CurrNbl) { Currbuff = NET_BUFFER_LIST_FIRST_NB(CurrNbl); while(Currbuff) { offset = NET_BUFFER_DATA_OFFSET(Currbuff); mdl = NET_BUFFER_FIRST_MDL(Currbuff); DataLen = NET_BUFFER_DATA_LENGTH(Currbuff); if ( mdl && DataLen ) { data = (UCHAR*)MmGetSystemAddressForMdlSafe( mdl,NormalPagePriority ); if(data) { info = data + offset; KdPrint((" PacketData : %p , PacketSize : %d ",info,DataLen)); } } Currbuff = NET_BUFFER_NEXT_NB(Currbuff); } CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl); } }