基于NDIS Filter 抓包

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驱动就没那么麻烦,直接一步搞定。我也不会怎么写理论的文章直接看图吧!

如下图所示:
2222
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。定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
	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的指点大概写了一段代码了读取数据包。读出数据包的地址和长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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);
	}
}


小弟水平很菜,写出来的文章也很戳,欢迎拍砖!热爱丢脸!学习… … 再贴个图,凑篇幅
2

随机日志


    5 Responses to “基于NDIS Filter 抓包”

    1. daisy 说:

      谢谢博主,通俗易懂,很适合像我一样的初学者,谢谢啦~

      [回复]

    2. archangel 说:

      容易是容易,怎么编译安装得,说一下啊。wdk

      [回复]

    3. daisy 说:

      博主,谢谢你给的小例子,在filter sample里边加入你的代码运行成功后让我长了不少自信。之前一直研究如何通过filter drive修改NET_BUFFER_LIST,对NetBufferList的架构一直难以理解,看你例子的简单读取NetBuffer的数据,比看那一大堆文档明了很多。现在想请教博主一个问题,博士是否了解一些filter driver如何修改NetBuffer的相关技术,msdn里边说只有其创建者才可修改其内容,我试着用NdisAllocateCloneNetBufferList()等函数去复制原NetBufferList,然后修改都不成功。如果博主有了解相关方便的知识,麻烦你可以从百忙中抽出一点时间,给我一些指点或者提示,我的email:hellodaisy@139.com,先谢了~

      [回复]

    4. gz1x 说:

      我以前有个项目是LWF的,等有时间写篇文章抛抛砖。

      [回复]

    Post a Comment