防火墙的数据包拦截方式小结
网络防火墙都是基于数据包的拦截技术之上的。在 Windows 下,数据包的拦截方式有很多种,
其原理和实现方式也千差万别。总的来说,可分为用户级内核级数据包拦截两大类。
用户级下的数据包拦截方式有:
* Winsock Layered Service Provider (LSP)
* Win2K 包过滤接口 (Win2K Packet Filtering Interface)
* 替换 Winsock 动态链接库 (Winsock Replacement DLL)
内核级下的数据包拦截方式有:
* TDI过滤驱动程序 (TDI-Filter Driver)
* NDIS中间层驱动程序 (NDIS Intermediate Driver)
* Win2K Filter-Hook Driver
* Win2K Firewall-Hook Driver
* NDIS-Hook Driver
在这么多种方式面前,我们该如何决定采用哪一种作为自己项目的实现技术?这需要对每一种
方式都有一个大致的了解,并清楚它们各自的优缺点。技术方案的盲目选用往往会带来一些技术
风险。以自己为例,我需要在截包的同时得到当前进程文件名,也就是说,需向用户报告当前是
哪个应用程序要访问网络。在选用 Win2K Filter-Hook Driver 这一方案之后(很多小型开源项
目都采用这一方案),便开始编码。但之后发现 Win2K Filter-Hook Driver 的截包上下文处于内
核进程中,即 IRQL >= DISPATCH_LEVEL,根本无法知道当前应用程序的名字。相比之下,
TDI-Filter Driver NDIS-Hook Driver 则可以得知这些信息。其中 TDI-Filter Driver
NDIS-Hook Driver 更能准确地获知当前应用程序文件名,后者的接收数据包和少数发送数据
包的场景仍然处于内核进程中。
下面列出了各种截包方式的特点:
* Winsock Layered Service Provider (LSP)
  该方式也称为 SPI (Service Provider Interface) 截包技术。SPI是由 Winsock2 提供的一个
  接口,它需要用户机上安装有 Winsock 2.0Winsock2 SPI 工作在 API 之下的 Driver 之上,
  可以截获所有基于 Socket 的网络数据包。
  优点:
  * DLL形式存在,编程方便,调试简单。
  * 数据封包比较完整,未做切片,便于做内容过滤。
  缺点:
  * 拦截不够严密,对于不用 Socket 的网络通讯则无法拦截 ( ICMP),木马病毒很容易绕过。
* Win2K Packet Filtering Interface
  这是 Win2K 中一组 API 提供的功能 (PfCreateInterface, PfAddFiltersToInterface, ...)
  优点:
  * 接口简单,实现起来没什么难度。
  缺点:
  * 功能过于简单,只能提供IP和端口的过滤,可能无法满足防火墙的复杂需求。
  * 处于 API 层,木马病毒容易绕过。
  * 只能在 Win2K 以上()系统中使用。
* Winsock Replacement DLL
  这种方法通过替换系统 Winsock 库的部分导出函数,实现数据报的监听和拦截。
  缺点:
  * 由于工作在 Winsock 层,所以木马病毒容易绕过。
* TDI-Filter Driver
  TDI 的全称是 Transport Driver Interface。传输层过滤驱动程序通过创建一个或多个设备对象
  直接挂接到一个现有的驱动程序之上。当有应用程序或其它驱动程序调用这个设备对象时,会首
  先映射到过滤驱动程序上,然后由过滤驱动程序再传递给原来的设备对象。
  优点:
  * 能获取到当前进程的详细信息,这对开发防火墙尤其有用。
  缺点:
  * 该驱动位于 tcpip.sys 之上,所以没有机会得到那些由 tcpip.sys 直接处理的包,比如ICMP
  * TDI驱动需要重启系统方能生效。
* NDIS Intermediate Driver
  也称之为 IM Driver。它位于协议层驱动和小端口驱动之间,它主要是在网络层和链路层之间对
  所有的数据包进行检查,因而具有强大的过滤功能。它能截获所有的数据包。
  可参考DDK中附带的例子 Passthru
  优点:
  * 功能非常强大,应用面广泛,不仅仅是防火墙,还可以用来实现VPNNAT VLan 等。
  缺点:
  * 编程复杂,难度较大。
  * 中间层驱动的概念是在 WinNT SP4 之后才有的,因此 Win9X 无法使用。
  * 不容易安装,自动化安装太困难。
* Win2K Filter-Hook Driver
  这是从 Win2K 开始提供的一种机制,该机制主要利用 ipfiltdrv.sys 所提供的功能来拦截网络
  数据包。Filter-Hook Driver 的结构非常简单,易于实现。但是正因为其结构过于简单,并且
  依赖于 ipfiltdrv.sys,微软并不推荐使用。
  可参考 CodeProject 上的例子:deproject/KB/IP/drvfltip.aspx
  优点:
  * 结构简单,易于实现。
  * 能截获所有的IP(包括ICMP)
  缺点:
  * 工作于内核进程中,无法取得当前应用程序进程的信息。
  * 虽能截获所有IP包,但无法取得数据包的以太帧(Ethernet Frame)
  * 只能在 Win2K 以上()系统中使用。
* Win2K Firewall-Hook Driver
  这是一种和 Win2k Filter-Hook Driver 差不多的机制,所不同的是,Firewall-Hook Driver
  能在 IP Driver 上挂接多个回调函数,所以和前者相比,它引起冲突的可能性更小一些。
  可参考 CodeProject 上的例子:deproject/KB/IP/FwHookDrv.aspx
  这种方式的优缺点和 Win2K Filter-Hook Driver 基本相同。
* NDIS-Hook Driver
  这是一种要重点讲述的截包方式。它是目前大多数网络防火墙所使用的方法。这种方式的做法
  是安装钩子到 ndis.sys 中,替换其中的某些关键函数,从而达到截包的目的。在下一节中我
  们将详细地介绍它的实现方法。
  优点:
  * 安装简单,可即时安装和卸载驱动,无需重启系统。
  * 能截获所有的IP包,同时能取得数据包的以太帧(Ethernet Frame)
  * 安全性高,木马病毒不容易穿透。
  * 在大多数情况下,能获取到当前应用程序的进程信息。
  * 能在 Win98 以上()系统中使用。
  缺点:
  * 接收数据包、或偶尔发送数据包时,驱动工作在内核进程中,无法获得应用程序进程信息。
NDIS-Hook 技术
微软和 3COM 公司在1989年制定了一套开发 Windows 下网络驱动程序的标准,称为 NDIS
NDIS 的全称是 Network Driver Interface SpecificationNDIS为网络驱动的开发提供了一套
标准的接口,使得网络驱动程序的跨平台性更好。
NDIS提供以下几个层次的接口:
1. NDIS 小端口驱动 (NDIS Miniport Driver)
  这也就是我们常说的网卡驱动。
2. NDIS 协议驱动 (NDIS Protocol Driver)
  用来实现某个具体的协议栈,如 TCP/IP 协议栈,并向上层导出 TDI 接口。
3. NDIS 中间层驱动 (NDIS Intermediate Driver)
  这是位于小端口驱动和协议驱动之间的驱动。
NDIS为了给出上述三种接口,提供了一个系统的、完整的 Wrapper。这个 Wrapper ndis.sys
上面提到的 Miniport DriverProtocol DriverIntermediate Driver 均属于插入到这个
Wrapper 中的模块,它们调用 Wrapper 提供的函数,同时也向 Wrapper 注册回调函数。
在简单了解了NDIS的机制之后,不难得知,网络防火墙只需要将自己的函数挂钩(Hook) ndis.sys
中即可截获网络数据包。NDIS-Hook 技术有两种实现方案:
1. 修改 ndis.sys Export Tabletcpip协议缺陷
  Win32 下,可执行文件(EXE/DLL/SYS)都遵从PE格式。所有提供接口的驱动都有 Export Table
  因此只要修改 ndis.sys Export Table,就可实现对关键函数的挂接。在实现步骤中,首先
  需要得到 ndis.sys 的内存基址,再根据PE格式得到DOS头部结构(IMAGE_DOS_HEADER),进一步得
  NT头部结构(IMAGE_NT_HEADER),最后从头部结构中查得 Export Table 的地址。
  由于协议驱动程序(NDIS Protocol Driver)在系统启动时会调用 NdisRegisterProtocol() 来向
  系统注册协议,因此这种方法关键在于修改 ndis.sys 所提供的 NdisRegisterProtocol
  NdisDeRegisterProtocolNdisOpenAdapterNdisCloseAdapterNdisSend 这几个函数的地址。
  对于处于系统核心的 ndis.sys 而言,要修改它的内存区域,只有驱动程序才能做到,所以我们
  必须编写驱动程序来达到这个目的。
  该方案的缺点是加载或卸载驱动后无法立即生效,必须重启系统。且挂钩方法较为复杂。早期凡
  使用 NDIS-Hook 的防火墙都采用这一方法,包括著名的费尔防火墙的早期版本(v2.1)
  直到 2004 年,kit 上一名黑客公布了一种全新的 NDIS-Hook 技术(即下文即将提
  到的第2种方法),诸多防火墙产品才都悄悄对自己的核心技术进行了升级。由于新的挂钩技术更
  好,故本文不打算详述修改 Export Table 这一方法的具体细节。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。