防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

  • A+
所属分类:安全闲碎

      安全防护软件、软件防火墙等网络防御软件能阻挡大量的网络入侵,让已知的网络攻击无处遁形,并且对未知的网络攻击缓解甚至阻断。本文中针对Windows 网络防火墙驱动开发以及WFP网络过滤框架介绍。阅读本文需要驱动开发基础。


WFP(Windows Filtering Platform)是Windows 中过滤网络数据的一个框架,代替了曾经的TDI网络过滤,是目前主流的网络过滤框架并同时拥有用户层与内核层的过滤功能。 内核模式用fwpmk.h用户模式用fwpmu.h

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

[WFP 精简原理图]

WFP 框架中包含几大概念:

1. 垫片

2. 呼出端口

3. 分层

4. 子层

5. 过滤器


垫片 

WFP 在网络设备栈中有多个垫片,分别截取不同网络层不同时机下的数据包。随后通过驱动自定义的Callout回调到驱动的回调中,驱动可以对截获的请求做任何事。可以理解垫片就是Hook的实现部分,用来截获函数调用的部分,只不过这里面向的是网络。这部分WFP开发者不需要为其做任何事,这些都由WFP框架完成。

 

呼出端口(Callout)

呼出端口是引擎截获到了相应垫片传来的网络请求和数据时,通过指定的规则分发到驱动声明的回调函数中,这些回调函数的定义在WFP中叫做呼出端口。并且每一个呼出端口创建时由开发者指定一个GUID来标识这个呼出回调。其中classifyFn代表着截获数据后的回调,notifyFn则是添加过滤器时的回调(一般使用STATUS_SUCCESS作为返回值即可),flowDeleteFn用于对绑定数据流的上下文释放。我们不绑定因此用空函数的函数指针。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

[WFPCALLOUT的定义]

(注意:FWPS_CALLOUT0_  0代表版本,不同的Windows版本中可能会不一致,参数均使用宏代替,例如FWPS_CALLOUT0_ 使用它们时应该使用FWPS_CALLOUT

 

分层(Layer)

分层表示着在哪一个时机执行,WFP预定义了许多层。每一个分层都有个GUID,如TCP三次握手后的分层:

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

分层定义FWPM_LAYER_*

参考MSDN:

[https://docs.microsoft.com/en-us/windows/win32/fwp/management-filtering-layer-identifiers-]

 

子层(SubLayer)

子层是在分层基础上添加的,一个分层中可以由多个子层组成。每个子层它的名字以及GUID,并且还有高度,这里的高度指的是优先级,优先级越高就会在同一分层中被优先调用WFP可以自行创建。WFP也有预定义的几个

参考:

[https://docs.microsoft.com/en-us/windows/win32/fwp/management-filtering-sublayer-identifiers ]

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

[WFPSUBLAYER的定义]

过滤器(Filter)

过滤器用于细化规则,并且将Callout、Layer、SubLayer合并到一起,

FilterKey由开发者定义用于标识Filter,filterCondition用于定义规则,action用于定义行为,行为中包括CalloutKey与行为类型,将行为类型定义为

FWP_ACTION_CALLOUT_TERMINATING则代表着行为由Callout回调的返回结构中定义,定义为FWP_ACTION_PERMIT则是直接放过。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

[WFPFILTER的定义]

Condition的定义:

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

其中fieldKey代表着过滤字段的GUID,WFP定义了一组字段,均为FWPM_CONDITION开头。

如:

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

MATCH_TYPE代表匹配类型,如相等、较小、较大。均为FWP_MATCH_开头

conditionValue则标识具体的值。

MSDN案例:

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

FWPM_CONDITION_IP_PROTOCOL字段表示IP的网络协议

FWP_MATCH_EQUAL 表示相等

FWP_UINT8表示对比的数据类型是UINT8

IPPROTO_TCP 表示TCP

 

随后开始尝试着制作一个拦截对远程80端口访问的请求:

需要使用到的函数:

FwpmEngineOpen//打开引擎

FwpmTransactionBegin//开始事物 (开始修改)

FwpsCalloutRegister//注册呼出端口

FwpmCalloutAdd//实例化呼出端口

FwpmSubLayerAdd//添加子层

FwpmFilterAdd//添加过滤器

FwpmTransactionCommit//提交事物 (应用修改)

FwpmTransactionAbort//终止事物 (取消修改)

由于WFP需要指定设备,所以需要先创建一个设备:

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

首先打开WFP引擎,驱动程序应将第二个参数设置为RPC_C_AUTHN_WINNT或者RPC_C_AUTHN_DEFAULT其他参数一般情况均为空。engineHandle返回引擎句柄。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

随后通过引擎句柄开启事物。FwpmTransactionBegin的第二个参数为只读或读写

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

随后注册Callout以及回调函数,CalloutGuidGUID工具生成,回调函数格式放在文章后部分,可以先创建一个空函数:

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

随后添加实例化Callout,其中applicableLayer就是分层类型GUID,

这里使用applicableLayer= FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4,表示过滤关于IPv4的三次握手

CalloutId是上面注册的返回值。CalloutKey是注册时用户自定义的CalloutKey

flags 0或三个选项,FWPM_CALLOUT_FLAG_PESISTENT表示callout在重新启动后保持不变。

displayData自定义名称。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

随后创建子层,为子层设置优先级为最大,并自定义名称。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

随后添加过滤器,将其组合成一个可用的过滤配置。

LayerKey仍然是实例化Callout时使用的applicableLayer参数,weigth高度的Type设置为FWP_EMPTY表示自动分配。action中表示着匹配成功后的动作。这里在action中的calloutKey设置好callout的回调GUIDaction的类型设置为允许或拒绝或由callout回调决定,这里设置为由callout回调决定:FWP_ACTION_CALLOUT_TERMINATING。同样,给过滤器取一个名称。

filterConditions设置过滤规则,numFilterCondition设置过滤规则项个数。这里均为空。

filterKey可以选择自定义或者用ExUuidCreate生成一个GUIDsubLayerKey用之前创建的SubLayerKey作为参数。随后调用FwpmFilterAdd创建出过滤器,返回一个FilterId

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

一切准备就绪,可以提交修改了。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口 

随后只要有用Ipv4连接的程序均会经过回调classifyFn

我们在classifyFn中只要做到判断端口为80时返回拒绝就可以到达效果。

首先看下classifyFn的结构

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

其中inFixedValues包含着分层中每个字段的值。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

其中有个incomingValue中存放着的亦是我们关注的信息,如IP/端口。

使用以下下标访问亦可取出指定的值,注意我们的分层时用的是ALE_FLOW_ESTABLISHED_V4如果用的是别的那么一样是FWPS_FIELD_<分层>_<字段名称>的组合。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

可以看到有个FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_PORT

通过inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_PORT].value.uint32 == 80

判断远程端口为80

随后回到classifyFn的声明中可以看到classifyOut指针,此值用于返回当前过滤器的过滤结果。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

其中actionType与之前添加Filter中看到的一致。只不过在添加Filter中设置成FWP_ACTION_CALLOUT_TERMINATING用来表示在回调内决定。现在在回调中我们给定一个拒绝

FWP_ACTION_BLOCK对于其他的请求均用FWP_ACTION_PERMIT 表示允许。此处并打印出IP地址与端口

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

其中FILTER_WFP_ADDRESS_IPV4是自定义的结构

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

拦截效果:

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

正常:

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

当驱动卸载时,需要将过滤器、子层、Callout释放,删除操作需要打开事务。以下函数分别释放。

防火墙驱动开发之WFP网络过滤框架--过滤IP/端口


本文始发于微信公众号(锋刃科技):防火墙驱动开发之WFP网络过滤框架--过滤IP/端口

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: