WFP是微软推出来替代TDI HOOK、NDIS HOOK等拦截网络通信的方案,WFP的框架非常庞大,在RING3和RING0各有一套类似的函数,令人兴奋的是,即使在R3使用WFP,也可以做到全局拦截访问网络。由于WFP的范围太广,实在难以一言概括,感兴趣的朋友可以自行到MSDN上查看微软对它的官方概述。本文的目的,是给大家理顺WFP的框架,并利用WFP拦截指定进程访问网络,或拦截对指定IP地址/端口的访问。
一个标准的WFP程序大体是这样子的:首先使用FwpmEngineOpen开启WFP引擎(获得一个WFP的使用句柄),然后用FwpmTransactionBegin设置对网络通信内容的过滤权限(是只读还是允许修改),然后用FwpsCalloutRegister、FwpmCalloutAdd、FwpmFilterAdd选择你要过滤的内容,并添加过滤器对象和回调函数,最后用FwpmTransactionCommit确认刚才的内容,让刚才添加的回调函数开始生效。当你不用WFP的时候,就要用FwpmFilterDeleteById、FwpmCalloutDeleteById、FwpsCalloutUnregisterById把你刚才添加的过滤器对象和回调函数删除掉,然后用FwpmEngineClose关闭WFP引擎(类似于关闭句柄)。
waitforsingleobject函数一个概述已经是这样子了,实现起来就更加麻烦了。为了方便大家学习,我已经把微软的WFP实例进行了最大简化,并把核心的注册回调功能封装成了一个函数。下面一步一步进行分析。在具体分析之前,有一些重要的内容需要先说明,否则后面的内容肯定会让大家一头雾水。一、WFP一次性要注册的回调函数不是1个,而是3个。但只有1个是“事前”回调,另外2个都是“事后”回调(一般只使用“事前”回调,不使用“事
后”回调)。二、WFP能过滤的内容很多,你必须选择一个感兴趣的内容。这个“感兴趣的内容”用官话来说叫做“过滤条件标志”,这货其实是一个常量,由于我们是要过滤进程联网,而且一般都是用IPV4协议,所以“过滤条件标志”为FWPM_LAYER_ALE_AUTH_CONNECT_V4(在这个页面可以查到所有的“过滤条件标志”)。三、你必须为这个“过滤条件标志”指定一个GUID,当然GUID的值随便设置就行,只要在系统范围内不重复。代码中的GUID就是随意设定的,它的名称为:GUID_ALE_AUTH_CONNECT_CALLOUT_V4。
第一步:开启WFP引擎、选择过滤权限(监控还是监视)、注册回调(输入感兴趣的内容、回调函数地址*3、返回过滤器和回调函数的“句柄”)、确认所有内容(让回调函数开始生效)。
第二步:编写回调函数。WFP的回调函数里提供了丰富的信息,这是WFP最大的优点,不用我们为获得各种相关信息而绞尽脑汁。比如在FWPM_LAYER_ALE_AUTH_CONNECT_V4的回调函数里,我们能获得进程ID、进程路径、本地、远程的IP地址/端口号以及协议代码。但最爽的是此回调函数的最后一个参数,能让我们指定一个值,决定是放行还是拦截。