Windows驱动开发入门-WFP过滤平台 碎碎念 本节讲网络传输层过滤,其中传输层接口TDI接口技术已被淘汰,取代其的新技术称为Windows过滤平台WFP。WFP包含用户态API和内核态API,本节只讲内核态开发。
WFP分为两大层次模块,用户态基础过滤引擎BFE和内核态过滤引擎KMFE。基础过滤引擎对上提供C调用方式的API以及RPC接口,这些接口封装在fwpuclnt.dll中。基础过滤引擎对下和内核态过滤引擎交互,受内核态过滤引擎控制。内核态过滤引擎与系统网络协议栈交互,通过垫片(此垫片非彼垫片)内核模块从网络协议栈Tcpip.sys中获取网络数据,垫片被插入到网络协议栈各个层中。垫片获取到数据后,通过内核态过滤引擎提供的分类API,把数据传到WFP相应分层中。内核态过滤引擎分为若干个分层,每个分层中存在一个或多个子层和过滤器,子层是分层的更小划分。子层被赋予不同权重,同一个子层中,WFP按照权重从大到小把数据交给相应子层。
例如TCP/IP协议栈中从上到下有数据流分层垫片、ALE网络连接管理、传输分层垫片(TCP/UDP)、网络分层垫片(IPv4/IPv6),他们通过分类API,与内核态过滤引擎不同子层交互,后者从上到小有流/报文数据分层、发送.接收ALE分层、发送/接收传输分层、发送/接收IP分层。
WFP架构中存在过滤器数据结构,里面保存网络数据包的拦截规则和处理动作,开发者可向WFP的内核态过滤引擎添加过滤器。
本节代码报fwpsk.h语法错误的话,在DriverEntry
例程文件最开头补上#define NDIS620
,表示NDIS版本6.20,用别的版本的话可以自己查对应的操作系统版本。若链接错误需要在项目属性的链接器中添加:
1 WDMSec.lib;FwpKClnt.lib;Fwpuclnt.lib;NTOSKrnl.lib;NetIO.lib;NDIS.lib;UUID.lib;advapi32.lib;kernel32.lib;
基本对象模型 内核态过滤引擎检查网络数据包是否命中过滤器的规则,对于命中规则的过滤器,内核态过滤引擎执行这些过滤器中指定的动作。动作有放行或拦截网络数据包。一个分层中可能有多个子层和多个过滤器,一次网络事件可能同时命中多个过滤器规则。此时过滤仲裁器模块计算出最终过滤动作并交由内核态过滤引擎,后者将最终过滤结果反馈给垫片。
垫片安插在系统网络协议栈的不同层中,获取网络协议栈的数据。安插在不同协议层的垫片获取到的数据不同。垫片还能把内核态过滤引擎的过滤结果反馈给网络协议栈。
呼出接口Callout由一系列回调函数和一个GUID组成。当网络数据命中某过滤器规则且过滤器指定一个呼出接口时,该呼出接口内的回调函数会被调用。不同呼出接口的回调函数实现不同功能,系统内置了一部分呼出接口,开发者也可向系统注册自己的呼出接口来完成特定逻辑。FWPS_CALLOUT结构描述呼出接口信息:
1 2 3 4 5 6 7 8 9 10 #define FWPS_CALLOUT FWPS_CALLOUT3 typedef struct FWPS_CALLOUT3_ { GUID calloutKey; UINT32 flags; FWPS_CALLOUT_CLASSIFY_FN3 classifyFn; FWPS_CALLOUT_NOTIFY_FN3 notifyFn; FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN0 flowDeleteFn; } FWPS_CALLOUT3;
内核态中,每个分层用64位的LUID标识,称为运行时过滤分层标识。用户态中,每个分层用129位的GUID标识,称为管理过滤分层标识。部分常用管理过滤分层标识如下,分别位接收/发送IPv4/6网络数据包层:
1 2 3 4 FWPM_LAYER_INBOUND_IPPACKET_V4 FWPM_LAYER_INBOUND_IPPACKET_V6 FWPM_LAYER_OUTBOUND_IPPACKET_V4 FWPM_LAYER_OUTBOUND_IPPACKET_V6
子层结构体定义为:
1 2 3 4 5 6 7 8 9 10 11 12 typedef struct FWPM_SUBLAYER0_ { GUID subLayerKey; FWPM_DISPLAY_DATA0 displayData; UINT32 flags; PGUID providerKey; FWP_BYTE_BLOB providerData; UINT16 weight; } FWPM_SUBLAYER0; typedef struct FWPM_DISPLAY_DATA0_ { wchar_t * name; wchar_t * description; } FWPM_DISPLAY_DATA0;
过滤器中的规则称为过滤条件,当一个过滤器中所有过滤条件全部成立时,才认为该过滤器规则被命中。使用过滤器时必需明确过滤器被添加到内核态过滤引擎哪个分层中,同一分层中可存在多个过滤器,不同过滤器被赋予不同权重,同子层内权重互相不能相同。过滤器还可关联呼出接口,当过滤器规则命中时WFP执行该过滤器关联的呼出接口内的回调函数。回调函数返回过滤结果允许或拦截到WFP。过滤器结构如下:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 #define FWPM_FILTER FWPM_FILTER0 typedef struct FWPM_FILTER0_ FWPM_FILTER0;typedef struct FWPM_FILTER0_ { GUID filterKey; FWPM_DISPLAY_DATA0 displayData; UINT32 flags; PGUID providerKey; FWP_BYTE_BLOB providerData; GUID layerKey; GUID subLayerKey; FWP_VALUE0 weight; UINT32 numFilterConditions; FWPM_FILTER_CONDITION0* filterCondition; FWPM_ACTION0 action; union { UINT64 rawContext; GUID providerContextKey; }; PGUID reserved; UINT64 filterId; FWP_VALUE0 effectiveWeight; } FWPM_FILTER0; typedef struct FWP_VALUE0_ { FWP_DATA_TYPE type; union { UINT8 uint8; UINT16 uint16; UINT32 uint32; PUINT64 uint64; INT8 int8; INT16 int16; INT32 int32; PINT64 int64; FLOAT float32; PDOUBLE double64; FWP_BYTE_ARRAY16* byteArray16; FWP_BYTE_BLOB* byteBlob; SID* sid; FWP_BYTE_BLOB* sd; FWP_TOKEN_INFORMATION* tokenInformation; FWP_BYTE_BLOB* tokenAccessInformation; LPWSTR unicodeString; FWP_BYTE_ARRAY6* byteArray6; }; } FWP_VALUE0; typedef enum FWP_DATA_TYPE_ { FWP_EMPTY = 0 , FWP_UINT8 = (FWP_EMPTY + 1 ), FWP_UINT16 = (FWP_UINT8 + 1 ), FWP_UINT32 = (FWP_UINT16 + 1 ), FWP_UINT64 = (FWP_UINT32 + 1 ), FWP_INT8 = (FWP_UINT64 + 1 ), FWP_INT16 = (FWP_INT8 + 1 ), FWP_INT32 = (FWP_INT16 + 1 ), FWP_INT64 = (FWP_INT32 + 1 ), FWP_FLOAT = (FWP_INT64 + 1 ), FWP_DOUBLE = (FWP_FLOAT + 1 ), FWP_BYTE_ARRAY16_TYPE = (FWP_DOUBLE + 1 ), FWP_BYTE_BLOB_TYPE = (FWP_BYTE_ARRAY16_TYPE + 1 ), FWP_SID = (FWP_BYTE_BLOB_TYPE + 1 ), FWP_SECURITY_DESCRIPTOR_TYPE = (FWP_SID + 1 ), FWP_TOKEN_INFORMATION_TYPE = (FWP_SECURITY_DESCRIPTOR_TYPE + 1 ), FWP_TOKEN_ACCESS_INFORMATION_TYPE = (FWP_TOKEN_INFORMATION_TYPE + 1 ), FWP_UNICODE_STRING_TYPE = (FWP_TOKEN_ACCESS_INFORMATION_TYPE + 1 ), FWP_BYTE_ARRAY6_TYPE = (FWP_UNICODE_STRING_TYPE + 1 ), FWP_SINGLE_DATA_TYPE_MAX = 0xff , FWP_V4_ADDR_MASK = (FWP_SINGLE_DATA_TYPE_MAX + 1 ), FWP_V6_ADDR_MASK = (FWP_V4_ADDR_MASK + 1 ), FWP_RANGE_TYPE = (FWP_V6_ADDR_MASK + 1 ), FWP_DATA_TYPE_MAX = (FWP_RANGE_TYPE + 1 ) } FWP_DATA_TYPE; typedef struct FWPM_FILTER_CONDITION0_ { GUID fieldKey; FWP_MATCH_TYPE matchType; FWP_CONDITION_VALUE0 conditionValue; } FWPM_FILTER_CONDITION0; typedef enum FWP_MATCH_TYPE_ { FWP_MATCH_EQUAL = 0 , FWP_MATCH_GREATER = (FWP_MATCH_EQUAL + 1 ), FWP_MATCH_LESS = (FWP_MATCH_GREATER + 1 ), FWP_MATCH_GREATER_OR_EQUAL = (FWP_MATCH_LESS + 1 ), FWP_MATCH_LESS_OR_EQUAL = (FWP_MATCH_GREATER_OR_EQUAL + 1 ), FWP_MATCH_RANGE = (FWP_MATCH_LESS_OR_EQUAL + 1 ), FWP_MATCH_FLAGS_ALL_SET = (FWP_MATCH_RANGE + 1 ), FWP_MATCH_FLAGS_ANY_SET = (FWP_MATCH_FLAGS_ALL_SET + 1 ), FWP_MATCH_FLAGS_NONE_SET = (FWP_MATCH_FLAGS_ANY_SET + 1 ), FWP_MATCH_EQUAL_CASE_INSENSITIVE = (FWP_MATCH_FLAGS_NONE_SET + 1 ), FWP_MATCH_NOT_EQUAL = (FWP_MATCH_EQUAL_CASE_INSENSITIVE + 1 ), FWP_MATCH_PREFIX = (FWP_MATCH_NOT_EQUAL + 1 ), FWP_MATCH_NOT_PREFIX = (FWP_MATCH_PREFIX + 1 ), FWP_MATCH_TYPE_MAX = (FWP_MATCH_NOT_PREFIX + 1 ) } FWP_MATCH_TYPE; typedef struct FWP_CONDITION_VALUE0_ { FWP_DATA_TYPE type; union { UINT8 uint8; UINT16 uint16; UINT32 uint32; PUINT64 uint64; INT8 int8; INT16 int16; INT32 int32; PINT64 int64; FLOAT float32; PDOUBLE double64; FWP_BYTE_ARRAY16* byteArray16; FWP_BYTE_BLOB* byteBlob; SID* sid; FWP_BYTE_BLOB* sd; FWP_TOKEN_INFORMATION* tokenInformation; FWP_BYTE_BLOB* tokenAccessInformation; LPWSTR unicodeString; FWP_BYTE_ARRAY6* byteArray6; FWP_V4_ADDR_AND_MASK* v4AddrMask; FWP_V6_ADDR_AND_MASK* v6AddrMask; FWP_RANGE0* rangeValue; }; } FWP_CONDITION_VALUE0; typedef struct FWPM_ACTION0_ { FWP_ACTION_TYPE type; union { GUID filterType; GUID calloutKey; }; } FWPM_ACTION0;
前文提到notifyFn、classifyFn和flowDeleteFn回调函数。当一个过滤器关联了呼出接口且规则被命中时,过滤引擎hi掉呼出接口的classify函数。开发者可在该回调函数中获取网络数据包相关信息,具体信息取决于过滤器所在分层,还可以设置对网络数据包的允许或拦截操作,原型如下:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 VOID NTAPI classifyFn1 ( _In_ CONST FWPS_INCOMING_VALUES0* inFixedValues, _In_ CONST FWPS_INCOMING_METADATA_VALUES0* inMetaValues, _Inout_opt_ PVOID layerData, _In_opt_ CONST PVOID classifyContext, _In CONST FWPS_FILTER1* filter, _In_opt_ UINT64 flowContext, _Out_ FWPS_CLASSIFY_OUT0* classifyOut ) ;typedef struct FWPS_INCOMING_VALUES0_ { UINT16 layerId; UINT32 valueCount; FWPS_INCOMING_VALUE0* incomingValue; } FWPS_INCOMING_VALUES0; typedef struct FWPS_INCOMING_VALUE0_ { FWP_VALUE0 value; } FWPS_INCOMING_VALUE0; typedef struct FWPS_INCOMING_METADATA_VALUES0_ { UINT32 currentMetadataValues; UINT32 flags; UINT64 reserved; FWPS_DISCARD_METADATA0 discardMetadata; UINT64 flowHandle; UINT32 ipHeaderSize; UINT32 transportHeaderSize; FWP_BYTE_BLOB* processPath; UINT64 token; UINT64 processId; UINT32 sourceInterfaceIndex; UINT32 destinationInterfaceIndex; ULONG compartmentId; FWPS_INBOUND_FRAGMENT_METADATA0 fragmentMetadata; ULONG pathMtu; HANDLE completionHandle; UINT64 transportEndpointHandle; SCOPE_ID remoteScopeId; WSACMSGHDR* controlData; ULONG controlDataLength; FWP_DIRECTION packetDirection; #if (NTDDI_VERSION >= NTDDI_WIN6SP1) PVOID headerIncludeHeader; ULONG headerIncludeHeaderLength; #if (NTDDI_VERSION >= NTDDI_WIN7) IP_ADDRESS_PREFIX destinationPrefix; UINT16 frameLength; UINT64 parentEndpointHandle; UINT32 icmpIdAndSequence; DWORD localRedirectTargetPID; SOCKADDR* originalDestination; #if (NTDDI_VERSION >= NTDDI_WIN8) HANDLE redirectRecords; UINT32 currentL2MetadataValues; UINT32 l2Flags; UINT32 ethernetMacHeaderSize; UINT32 wiFiOperationMode; #if (NDIS_SUPPORT_NDIS630) NDIS_SWITCH_PORT_ID vSwitchSourcePortId; NDIS_SWITCH_NIC_INDEX vSwitchSourceNicIndex; NDIS_SWITCH_PORT_ID vSwitchDestinationPortId; #else UINT32 padding0; USHORT padding1; UINT32 padding2; #endif HANDLE vSwitchPacketContext; #endif #endif #endif #if (NTDDI_VERSION >= NTDDI_WIN8) PVOID subProcessTag; UINT64 reserved1; #endif } FWPS_INCOMING_METADATA_VALUES0; #define FWPS_METADATA_FIELD_DISCARD_REASON 0x00000001 #define FWPS_METADATA_FIELD_FLOW_HANDLE 0x00000002 #define FWPS_METADATA_FIELD_IP_HEADER_SIZE 0x00000004 #define FWPS_METADATA_FIELD_PROCESS_PATH 0x00000008 #define FWPS_METADATA_FIELD_TOKEN 0x00000010 #define FWPS_METADATA_FIELD_PROCESS_ID 0x00000020 #define FWPS_METADATA_FIELD_SYSTEM_FLAGS 0x00000040 #define FWPS_METADATA_FIELD_RESERVED 0x00000080 #define FWPS_METADATA_FIELD_SOURCE_INTERFACE_INDEX 0x00000100 #define FWPS_METADATA_FIELD_DESTINATION_INTERFACE_INDEX 0x00000200 #define FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE 0x00000400 #define FWPS_METADATA_FIELD_COMPARTMENT_ID 0x00000800 #define FWPS_METADATA_FIELD_FRAGMENT_DATA 0x00001000 #define FWPS_METADATA_FIELD_PATH_MTU 0x00002000 #define FWPS_METADATA_FIELD_COMPLETION_HANDLE 0x00004000 #define FWPS_METADATA_FIELD_TRANSPORT_ENDPOINT_HANDLE 0x00008000 #define FWPS_METADATA_FIELD_TRANSPORT_CONTROL_DATA 0x00010000 #define FWPS_METADATA_FIELD_REMOTE_SCOPE_ID 0x00020000 #define FWPS_METADATA_FIELD_PACKET_DIRECTION 0x00040000 #if (NTDDI_VERSION >= NTDDI_WIN6SP1) #define FWPS_METADATA_FIELD_PACKET_SYSTEM_CRITICAL 0x00080000 #define FWPS_METADATA_FIELD_FORWARD_LAYER_OUTBOUND_PASS_THRU 0x00100000 #define FWPS_METADATA_FIELD_FORWARD_LAYER_INBOUND_PASS_THRU 0x00200000 #define FWPS_METADATA_FIELD_ALE_CLASSIFY_REQUIRED 0x00400000 #define FWPS_METADATA_FIELD_TRANSPORT_HEADER_INCLUDE_HEADER 0x00800000 #if (NTDDI_VERSION >= NTDDI_WIN7) #define FWPS_METADATA_FIELD_DESTINATION_PREFIX 0x01000000 #define FWPS_METADATA_FIELD_ETHER_FRAME_LENGTH 0x02000000 #define FWPS_METADATA_FIELD_PARENT_ENDPOINT_HANDLE 0x04000000 #define FWPS_METADATA_FIELD_ICMP_ID_AND_SEQUENCE 0x08000000 #define FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID 0x10000000 #define FWPS_METADATA_FIELD_ORIGINAL_DESTINATION 0x20000000 #if (NTDDI_VERSION >= NTDDI_WIN8) #define FWPS_METADATA_FIELD_REDIRECT_RECORD_HANDLE 0x40000000 #define FWPS_METADATA_FIELD_SUB_PROCESS_TAG 0x80000000 #define FWPS_IS_METADATA_FIELD_PRESENT(metadataValues, metadataField) (((metadataValues)->currentMetadataValues & (metadataField)) == (metadataField)) typedef struct FWPS_CLASSIFY_OUT0_ { FWP_ACTION_TYPE actionType; UINT64 outContext; UINT64 filterId; UINT32 rights; UINT32 flags; UINT32 reserved; } FWPS_CLASSIFY_OUT0;
当过滤器被添加到过滤引擎中或从过滤引擎中移除时,WFP调用该过滤器对应呼出接口的notifyFn1函数。开发者可通过该函数得知呼出接口关联的过滤器的操作情况,原型如下。
1 2 3 4 5 6 7 8 9 NTSTATUS NTAPI notifyFn1 ( _In_ FWPS_CALLOUT_NOTIFY_TYPE notifyType, _In_ CONST PGUID filterKey, _In_ CONST FWPS_FILTER1* filter ) ;
当一个网络数据流将要被终止,且该数据流被关联了上下文时,flowDeleteFn被回调,可在该回调函数中清理关联的上下文:
1 2 3 4 5 VOID NTAPI flowDeleteFn ( _In_ UINT16 layerId, _In_ UINT32 calloutId, _In_ UINT64 flowContext ) ;
WFP操作 开发者在内核态用WFP提供的API实现网络数据包过滤,分为步骤如下:定义一个或多个呼出接口,向过滤引擎注册呼出接口;添加呼出接口到过滤引擎;设计一个或多个子层,将子层添加到分层中;设计过滤器,把呼出接口、子层、分层和过滤器关联起来。
注册呼出接口时可用FwpsCalloutRegister2
,定义如下。
1 2 3 4 5 NTSTATUS NTAPI FwpsCalloutRegister2 ( _Inout_ PVOID deviceObject, _In_ CONST FWPS_CALLOUT2* callout, _Out_opt_ PUINT32 calloutId ) ;
卸载呼出接口用FwpsCalloutUnregisterById
或FwpsCalloutUnregisterByKey
。前者通过指定呼出接口的运行时标识来对呼出接口进行卸载,后者通过指定呼出接口的GUID来对呼出接口进行卸载。
注册呼出接口后,需要把呼出接口添加到过滤引擎中,在此之前得先用FwpmEngineOpen0
打开过滤引擎。
1 2 3 4 5 6 7 NTSTATUS NTAPI FwpmEngineOpen0 ( _In_opt_ CONST wchar_t * serverName, _In_ UINT32 authnService, _In_opt_ SEC_WINNT_AUTH_IDENTIFY_W* authIdentify, _In_opt_ CONST FWPM_SESSION0* session, _Out_ HANDLE* engineHandle ) ;
用FwpmCalloutAdd0
将呼出接口添加到过滤引擎中。
1 2 3 4 5 6 DWORD WINAPI FwpmCalloutAdd0 ( _In_ HANDLE engineHandle, _In_ CONST FWPM_CALLOUT0* callout, _In_opt_ PSECURITY_DESCRIPTOR sd, _out_opt_ PUINT32 id ) ;
用FwpmCalloutDeleteById0
或FwpmCalloutDeleteByKey0
可移除添加到过滤引擎中的呼出接口。
用FwpmSubLayerAdd0
添加子层:
1 2 3 4 5 DWORD WINAPI FwpmSubLayerAdd0 ( _In_ HANDLE engineHandle, _In_ CONST FWPM_SUBLAYER0* subLayer, _In_opt_ PSECURITY_DESCRIPTOR sd ) ;
用FwpmFilterAdd0
添加过滤器:
1 2 3 4 5 6 DWORD WINAPI FwpmFilterAdd0 ( _In_ HANDLE engineHandle, _In_ CONST FWPM_FILTER0* filter, _In_opt_ PSECURITY_DESCRIPTOR sd, _Out_opt_ PUINT64 id ) ;
移除过滤器用FwpmFilterDeleteById0
或FwpmFilterDeleteByKey0
。
WFP例子 拦截TCP协议对外连接80端口。驱动入口函数实现:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 NTSTATUS DriverEntry (__in struct _DRIVER_OBJECT* DriverObject, __in PUNICODE_STRING RegistryPath) { NTSTATUS nStatus = STATUS_UNSUCCESSFUL; UNREFERENCED_PARAMETER (RegistryPath); do { if (DriverObject == NULL ) break ; DriverObject->MajorFunction[IRP_MJ_CREATE] = WfpSampleIRPDispatch; DriverObject->MajorFunction[IRP_MJ_CLOSE] = WfpSampleIRPDispatch; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WfpSampleIRPDispatch; if (FALSE == InitRuleInfo ()) break ; g_pDeviceObj = CreateDevice (DriverObject); if (g_pDeviceObj == NULL ) break ; if (InitWfp () != STATUS_SUCCESS) break ; DriverObject->DriverUnload = DriverUnload; nStatus = STATUS_SUCCESS; } while (FALSE); if (nStatus != STATUS_SUCCESS) { UninitWfp (); DeleteDevice (); UninitRuleInfo (); }; return nStatus; }; NTSTATUS InitWfp (VOID) { NTSTATUS nStatus = STATUS_UNSUCCESSFUL; do { g_hEngine = OpenEngine (); if (g_hEngine == NULL ) break ; if (STATUS_SUCCESS != WfpRegisterCallouts (g_pDeviceObj)) break ; if (STATUS_SUCCESS != WfpAddCallouts ()) break ; if (STATUS_SUCCESS != WfpAddSubLayer ()) break ; if (STATUS_SUCCESS != WfpAddFilters ()) break ; nStatus = STATUS_SUCCESS; } while (FALSE); return nStatus; }; HANDLE OpenEngine (VOID) { FWPM_SESSION0 Session = { 0 }; HANDLE hEngine = NULL ; FwpmEngineOpen (NULL , RPC_C_AUTHN_WINNT, NULL , &Session, &hEngine); return hEngine; }; DEFINE_GUID (WFP_SAMPLE_ESTABLISHED_CALLOUT_V4_GUID, 0xd969fc67 , 0x6fb2 , 0x4504 , 0x91 , 0xce , 0xa9 , 0x7c , 0x3c , 0x32 , 0xad , 0x36 ); NTSTATUS WfpRegisterCallouts (IN OUT PVOID deviceObject) { NTSTATUS status = STATUS_UNSUCCESSFUL; do { if (deviceObject == NULL ) break ; status = WfpRegisterCalloutImple (deviceObject, Wfp_Sample_Established_ClassifyFn_V4, Wfp_Sample_Established_NotifyFn_V4, Wfp_Sample_Established_FlowDeleteFn_V4, &WFP_SAMPLE_ESTABLISHED_CALLOUT_V4_GUID, 0 , &g_uFwpsEstablishedCallOutId); if (status != STATUS_SUCCESS) break ; status = STATUS_SUCCESS; } while (FALSE); return status; }; NTSTATUS WfpRegisterCalloutImple ( IN OUT void * deviceObject, IN FWPS_CALLOUT_CLASSIFY_FN ClassifyFunction, IN FWPS_CALLOUT_NOTIFY_FN NotifyFunction, IN FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN FlowDeleteFunction, IN GUID const * calloutKey, IN UINT32 flags, OUT UINT32* calloutId) { FWPS_CALLOUT sCallout; NTSTATUS status = STATUS_SUCCESS; memset (&sCallout, 0 , sizeof (FWPS_CALLOUT)); sCallout.calloutKey = *calloutKey; sCallout.flags = flags; sCallout.classifyFn = ClassifyFunction; sCallout.notifyFn = NotifyFunction; sCallout.flowDeleteFn = FlowDeleteFunction; status = FwpsCalloutRegister (deviceObject, &sCallout, calloutId); return status; }; DEFINE_GUID (WFP_SAMPLE_SUBLAYER_GUID,0xed6a516a , 0x36d1 , 0x4881 , 0xbc , 0xf0 , 0xac , 0xeb , 0x4c , 0x4 , 0xc2 , 0x1c ); NTSTATUS WfpAddCallouts (VOID) { NTSTATUS status = STATUS_SUCCESS; FWPM_CALLOUT fwpmCallout = { 0 }; fwpmCallout.flags = 0 ; do { if (g_hEngine == NULL ) break ; fwpmCallout.displayData.name = (wchar_t *)WFP_SAMPLE_ESTABLISHED_CALLOUT_DISPLAY_NAME; fwpmCallout.displayData.description = (wchar_t *)WFP_SAMPLE_ESTABLISHED_CALLOUT_DISPLAY_NAME; fwpmCallout.calloutKey = WFP_SAMPLE_ESTABLISHED_CALLOUT_V4_GUID; fwpmCallout.applicableLayer = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; status = FwpmCalloutAdd (g_hEngine, &fwpmCallout, NULL , &g_uFwpmEstablishedCallOutId); if (!NT_SUCCESS (status) && (status != STATUS_FWP_ALREADY_EXISTS)) break ; status = STATUS_SUCCESS; } while (FALSE); return status; }; NTSTATUS WfpAddSubLayer (VOID) { NTSTATUS nStatus = STATUS_UNSUCCESSFUL; FWPM_SUBLAYER SubLayer = { 0 }; SubLayer.flags = 0 ; SubLayer.displayData.description = WFP_SAMPLE_SUB_LAYER_DISPLAY_NAME; SubLayer.displayData.name = WFP_SAMPLE_SUB_LAYER_DISPLAY_NAME; SubLayer.subLayerKey = WFP_SAMPLE_SUBLAYER_GUID; SubLayer.weight = 65535 ; if (g_hEngine != NULL ) nStatus = FwpmSubLayerAdd (g_hEngine, &SubLayer, NULL ); return nStatus; }; NTSTATUS WfpAddFilters (VOID) { NTSTATUS nStatus = STATUS_UNSUCCESSFUL; do { FWPM_FILTER0 Filter = { 0 }; FWPM_FILTER_CONDITION FilterCondition[1 ] = { 0 }; FWP_V4_ADDR_AND_MASK AddrAndMask = { 0 }; if (g_hEngine == NULL ) break ; Filter.displayData.description = WFP_SAMPLE_FILTER_ESTABLISH_DISPLAY_NAME; Filter.displayData.name = WFP_SAMPLE_FILTER_ESTABLISH_DISPLAY_NAME; Filter.flags = 0 ; Filter.layerKey = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; Filter.subLayerKey = WFP_SAMPLE_SUBLAYER_GUID; Filter.weight.type = FWP_EMPTY; Filter.numFilterConditions = 1 ; Filter.filterCondition = FilterCondition; Filter.action.type = FWP_ACTION_CALLOUT_TERMINATING; Filter.action.calloutKey = WFP_SAMPLE_ESTABLISHED_CALLOUT_V4_GUID; FilterCondition[0 ].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS; FilterCondition[0 ].matchType = FWP_MATCH_EQUAL; FilterCondition[0 ].conditionValue.type = FWP_V4_ADDR_MASK; FilterCondition[0 ].conditionValue.v4AddrMask = &AddrAndMask; nStatus = FwpmFilterAdd (g_hEngine, &Filter, NULL , &g_uEstablishedFilterId); if (STATUS_SUCCESS != nStatus) break ; nStatus = STATUS_SUCCESS; } while (FALSE); return nStatus; }; VOID NTAPI Wfp_Sample_Established_ClassifyFn_V4 (IN const FWPS_INCOMING_VALUES* inFixedValues, IN const FWPS_INCOMING_METADATA_VALUES* inMetaValues, IN OUT VOID* layerData, IN OPTIONAL const void * classifyContext, IN const FWPS_FILTER1* filter, IN UINT64 flowContext, OUT FWPS_CLASSIFY_OUT* classifyOut) { WORD wDirection = 0 ; WORD wRemotePort = 0 ; WORD wSrcPort = 0 ; WORD wProtocol = 0 ; ULONG ulSrcIPAddress = 0 ; ULONG ulRemoteIPAddress = 0 ; if (!(classifyOut->rights & FWPS_RIGHT_ACTION_WRITE)) return ; wDirection = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_DIRECTION].value.int8; wSrcPort = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_PORT].value.uint16; wRemotePort = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_PORT].value.uint16; ulSrcIPAddress = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_ADDRESS].value.uint32; ulRemoteIPAddress = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_ADDRESS].value.uint32; wProtocol = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_PROTOCOL].value.uint8; classifyOut->actionType = FWP_ACTION_PERMIT; if (IsHitRule (wRemotePort)) classifyOut->actionType = FWP_ACTION_BLOCK; if (filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT) classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE; return ; };
实例代码 WfpSample.c:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 #define NDIS630 #include "ntddk.h" #include "fwpmk.h" #include "fwpsk.h" #define INITGUID #include <guiddef.h> #include "WfpSample.h" #include "Fwpmu.h" #include "Rule.h" PDEVICE_OBJECT g_pDeviceObj = NULL ; UINT32 g_uFwpsEstablishedCallOutId = 0 ; UINT32 g_uFwpmEstablishedCallOutId = 0 ; UINT64 g_uEstablishedFilterId = 0 ; HANDLE g_hEngine = NULL ; NTSTATUS DriverEntry (__in struct _DRIVER_OBJECT* DriverObject, __in PUNICODE_STRING RegistryPath) { NTSTATUS nStatus = STATUS_UNSUCCESSFUL; UNREFERENCED_PARAMETER (RegistryPath); do { if (DriverObject == NULL ) break ; DriverObject->MajorFunction[IRP_MJ_CREATE] = WfpSampleIRPDispatch; DriverObject->MajorFunction[IRP_MJ_CLOSE] = WfpSampleIRPDispatch; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = WfpSampleIRPDispatch; if (FALSE == InitRuleInfo ()) break ; g_pDeviceObj = CreateDevice (DriverObject); if (g_pDeviceObj == NULL ) break ; if (InitWfp () != STATUS_SUCCESS) break ; DriverObject->DriverUnload = DriverUnload; nStatus = STATUS_SUCCESS; } while (FALSE); if (nStatus != STATUS_SUCCESS) { UninitWfp (); DeleteDevice (); UninitRuleInfo (); }; return nStatus; }; NTSTATUS WfpSampleIRPDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS nStatus = STATUS_SUCCESS; ULONG ulInformation = 0 ; UNREFERENCED_PARAMETER (DeviceObject); do { PIO_STACK_LOCATION IrpStack = NULL ; PVOID pSystemBuffer = NULL ; ULONG uInLen = 0 ; if (Irp == NULL ) break ; pSystemBuffer = Irp->AssociatedIrp.SystemBuffer; IrpStack = IoGetCurrentIrpStackLocation (Irp); if (IrpStack == NULL ) break ; uInLen = IrpStack->Parameters.DeviceIoControl.InputBufferLength; if (IrpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL) break ; switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_WFP_SAMPLE_ADD_RULE:{ BOOLEAN bSucc = FALSE; bSucc = AddNetRuleInfo (pSystemBuffer, uInLen); if (bSucc == FALSE) nStatus = STATUS_UNSUCCESSFUL; break ; }; default :{ ulInformation = 0 ; nStatus = STATUS_UNSUCCESSFUL; }; }; } while (FALSE); if (Irp != NULL ) { Irp->IoStatus.Information = ulInformation; Irp->IoStatus.Status = nStatus; IoCompleteRequest (Irp, IO_NO_INCREMENT); }; return nStatus; }; PDEVICE_OBJECT CreateDevice (__in struct _DRIVER_OBJECT* DriverObject) { UNICODE_STRING uDeviceName = { 0 }; UNICODE_STRING uSymbolName = { 0 }; PDEVICE_OBJECT pDeviceObj = NULL ; NTSTATUS nStatsus = STATUS_UNSUCCESSFUL; RtlInitUnicodeString (&uDeviceName, WFP_DEVICE_NAME); RtlInitUnicodeString (&uSymbolName, WFP_SYM_LINK_NAME); nStatsus = IoCreateDevice (DriverObject, 0 , &uDeviceName, FILE_DEVICE_UNKNOWN, 0 , FALSE, &pDeviceObj); if (pDeviceObj != NULL ) pDeviceObj->Flags |= DO_BUFFERED_IO; IoCreateSymbolicLink (&uSymbolName, &uDeviceName); return pDeviceObj; }; VOID DeleteDevice () { UNICODE_STRING uSymbolName = { 0 }; RtlInitUnicodeString (&uSymbolName, WFP_SYM_LINK_NAME); IoDeleteSymbolicLink (&uSymbolName); if (g_pDeviceObj != NULL ) IoDeleteDevice (g_pDeviceObj); g_pDeviceObj = NULL ; }; NTSTATUS InitWfp (VOID) { NTSTATUS nStatus = STATUS_UNSUCCESSFUL; do { g_hEngine = OpenEngine (); if (g_hEngine == NULL ) break ; if (STATUS_SUCCESS != WfpRegisterCallouts (g_pDeviceObj)) break ; if (STATUS_SUCCESS != WfpAddCallouts ()) break ; if (STATUS_SUCCESS != WfpAddSubLayer ()) break ; if (STATUS_SUCCESS != WfpAddFilters ()) break ; nStatus = STATUS_SUCCESS; } while (FALSE); return nStatus; }; VOID UninitWfp (VOID) { WfpRemoveFilters (); WfpRemoveSubLayer (); WfpRemoveCallouts (); WfpUnRegisterCallouts (); CloseEngine (); }; VOID DriverUnload (__in struct _DRIVER_OBJECT* DriverObject) { UninitWfp (); DeleteDevice (); UninitRuleInfo (); return ; }; HANDLE OpenEngine (VOID) { FWPM_SESSION0 Session = { 0 }; HANDLE hEngine = NULL ; FwpmEngineOpen (NULL , RPC_C_AUTHN_WINNT, NULL , &Session, &hEngine); return hEngine; }; VOID CloseEngine (VOID) { if (g_hEngine != NULL ) FwpmEngineClose (g_hEngine); g_hEngine = NULL ; return ; }; NTSTATUS WfpRegisterCalloutImple (IN OUT void * deviceObject, IN FWPS_CALLOUT_CLASSIFY_FN ClassifyFunction, IN FWPS_CALLOUT_NOTIFY_FN NotifyFunction, IN FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN FlowDeleteFunction, IN GUID const * calloutKey, IN UINT32 flags, OUT UINT32* calloutId) { FWPS_CALLOUT sCallout; NTSTATUS status = STATUS_SUCCESS; memset (&sCallout, 0 , sizeof (FWPS_CALLOUT)); sCallout.calloutKey = *calloutKey; sCallout.flags = flags; sCallout.classifyFn = ClassifyFunction; sCallout.notifyFn = NotifyFunction; sCallout.flowDeleteFn = FlowDeleteFunction; status = FwpsCalloutRegister (deviceObject, &sCallout, calloutId); return status; }; NTSTATUS WfpRegisterCallouts (IN OUT PVOID deviceObject) { NTSTATUS status = STATUS_UNSUCCESSFUL; do { if (deviceObject == NULL ) break ; status = WfpRegisterCalloutImple (deviceObject, Wfp_Sample_Established_ClassifyFn_V4, Wfp_Sample_Established_NotifyFn_V4, Wfp_Sample_Established_FlowDeleteFn_V4, &WFP_SAMPLE_ESTABLISHED_CALLOUT_V4_GUID, 0 , &g_uFwpsEstablishedCallOutId); if (status != STATUS_SUCCESS) break ; status = STATUS_SUCCESS; } while (FALSE); return status; }; VOID WfpUnRegisterCallouts (VOID) { FwpsCalloutUnregisterById (g_uFwpsEstablishedCallOutId); g_uFwpsEstablishedCallOutId = 0 ; return ; }; NTSTATUS WfpAddCallouts (VOID) { NTSTATUS status = STATUS_SUCCESS; FWPM_CALLOUT fwpmCallout = { 0 }; fwpmCallout.flags = 0 ; do { if (g_hEngine == NULL ) break ; fwpmCallout.displayData.name = (wchar_t *)WFP_SAMPLE_ESTABLISHED_CALLOUT_DISPLAY_NAME; fwpmCallout.displayData.description = (wchar_t *)WFP_SAMPLE_ESTABLISHED_CALLOUT_DISPLAY_NAME; fwpmCallout.calloutKey = WFP_SAMPLE_ESTABLISHED_CALLOUT_V4_GUID; fwpmCallout.applicableLayer = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; status = FwpmCalloutAdd (g_hEngine, &fwpmCallout, NULL , &g_uFwpmEstablishedCallOutId); if (!NT_SUCCESS (status) && (status != STATUS_FWP_ALREADY_EXISTS)) break ; status = STATUS_SUCCESS; } while (FALSE); return status; }; VOID WfpRemoveCallouts () { if (g_hEngine != NULL ) { FwpmCalloutDeleteById (g_hEngine, g_uFwpmEstablishedCallOutId); g_uFwpmEstablishedCallOutId = 0 ; }; return ; }; NTSTATUS WfpAddSubLayer () { NTSTATUS nStatus = STATUS_UNSUCCESSFUL; FWPM_SUBLAYER SubLayer = { 0 }; SubLayer.flags = 0 ; SubLayer.displayData.description = WFP_SAMPLE_SUB_LAYER_DISPLAY_NAME; SubLayer.displayData.name = WFP_SAMPLE_SUB_LAYER_DISPLAY_NAME; SubLayer.subLayerKey = WFP_SAMPLE_SUBLAYER_GUID; SubLayer.weight = 65535 ; if (g_hEngine != NULL ) nStatus = FwpmSubLayerAdd (g_hEngine, &SubLayer, NULL ); return nStatus; }; VOID WfpRemoveSubLayer () { if (g_hEngine != NULL ) FwpmSubLayerDeleteByKey (g_hEngine, &WFP_SAMPLE_SUBLAYER_GUID); return ; }; NTSTATUS WfpAddFilters () { NTSTATUS nStatus = STATUS_UNSUCCESSFUL; do { FWPM_FILTER0 Filter = { 0 }; FWPM_FILTER_CONDITION FilterCondition[1 ] = { 0 }; FWP_V4_ADDR_AND_MASK AddrAndMask = { 0 }; if (g_hEngine == NULL ) break ; Filter.displayData.description = WFP_SAMPLE_FILTER_ESTABLISH_DISPLAY_NAME; Filter.displayData.name = WFP_SAMPLE_FILTER_ESTABLISH_DISPLAY_NAME; Filter.flags = 0 ; Filter.layerKey = FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4; Filter.subLayerKey = WFP_SAMPLE_SUBLAYER_GUID; Filter.weight.type = FWP_EMPTY; Filter.numFilterConditions = 1 ; Filter.filterCondition = FilterCondition; Filter.action.type = FWP_ACTION_CALLOUT_TERMINATING; Filter.action.calloutKey = WFP_SAMPLE_ESTABLISHED_CALLOUT_V4_GUID; FilterCondition[0 ].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS; FilterCondition[0 ].matchType = FWP_MATCH_EQUAL; FilterCondition[0 ].conditionValue.type = FWP_V4_ADDR_MASK; FilterCondition[0 ].conditionValue.v4AddrMask = &AddrAndMask; nStatus = FwpmFilterAdd (g_hEngine, &Filter, NULL , &g_uEstablishedFilterId); if (STATUS_SUCCESS != nStatus) break ; nStatus = STATUS_SUCCESS; } while (FALSE); return nStatus; }; VOID WfpRemoveFilters () { if (g_hEngine != NULL ) FwpmFilterDeleteById (g_hEngine, g_uEstablishedFilterId); return ; }; VOID NTAPI Wfp_Sample_Established_ClassifyFn_V4 (IN const FWPS_INCOMING_VALUES* inFixedValues, IN const FWPS_INCOMING_METADATA_VALUES* inMetaValues, IN OUT VOID* layerData, IN OPTIONAL const void * classifyContext, IN const FWPS_FILTER1* filter, IN UINT64 flowContext, OUT FWPS_CLASSIFY_OUT* classifyOut) { WORD wDirection = 0 ; WORD wRemotePort = 0 ; WORD wSrcPort = 0 ; WORD wProtocol = 0 ; ULONG ulSrcIPAddress = 0 ; ULONG ulRemoteIPAddress = 0 ; if (!(classifyOut->rights & FWPS_RIGHT_ACTION_WRITE)) return ; wDirection = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_DIRECTION].value.int8; wSrcPort = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_PORT].value.uint16; wRemotePort = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_PORT].value.uint16; ulSrcIPAddress = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_ADDRESS].value.uint32; ulRemoteIPAddress = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_ADDRESS].value.uint32; wProtocol = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_PROTOCOL].value.uint8; classifyOut->actionType = FWP_ACTION_PERMIT; if (IsHitRule (wRemotePort)) classifyOut->actionType = FWP_ACTION_BLOCK; if (filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT) classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE; return ; }; NTSTATUS NTAPI Wfp_Sample_Established_NotifyFn_V4 (IN FWPS_CALLOUT_NOTIFY_TYPE notifyType, IN const GUID* filterKey, IN const FWPS_FILTER* filter) { return STATUS_SUCCESS; }; VOID NTAPI Wfp_Sample_Established_FlowDeleteFn_V4 (IN UINT16 layerId, IN UINT32 calloutId, IN UINT64 flowContext) {};
WfpSample.h:
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 37 38 #pragma once #ifndef MAX_PATH #define MAX_PATH (260) #endif #define WFP_DEVICE_NAME L"\\Device\\wfp_sample_device" #define WFP_SYM_LINK_NAME L"\\DosDevices\\wfp_sample_device" #define WFP_SAMPLE_ESTABLISHED_CALLOUT_DISPLAY_NAME L"WfpSampleEstablishedCalloutName" #define WFP_SAMPLE_SUB_LAYER_DISPLAY_NAME L"WfpSampleSubLayerName" #define WFP_SAMPLE_FILTER_ESTABLISH_DISPLAY_NAME L"WfpSampleFilterEstablishName" #define HTTP_DEFAULT_PORT 80 #define IOCTL_WFP_SAMPLE_ADD_RULE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_READ_ACCESS | FILE_WRITE_ACCESS) DEFINE_GUID (WFP_SAMPLE_ESTABLISHED_CALLOUT_V4_GUID, 0xd969fc67 , 0x6fb2 , 0x4504 , 0x91 , 0xce , 0xa9 , 0x7c , 0x3c , 0x32 , 0xad , 0x36 );DEFINE_GUID (WFP_SAMPLE_SUBLAYER_GUID,0xed6a516a , 0x36d1 , 0x4881 , 0xbc , 0xf0 , 0xac , 0xeb , 0x4c , 0x4 , 0xc2 , 0x1c );void DriverUnload (__in struct _DRIVER_OBJECT* DriverObject) ;PDEVICE_OBJECT CreateDevice (__in struct _DRIVER_OBJECT* DriverObject) ;NTSTATUS WfpSampleIRPDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) ;NTSTATUS WfpRegisterCalloutImple (IN OUT void * deviceObject,IN FWPS_CALLOUT_CLASSIFY_FN ClassifyFunction,IN FWPS_CALLOUT_NOTIFY_FN NotifyFunction,IN FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN FlowDeleteFunction,IN GUID const * calloutKey,IN UINT32 flags,OUT UINT32* calloutId) ;NTSTATUS WfpRegisterCallouts (IN OUT void * deviceObject) ;VOID NTAPI Wfp_Sample_Established_ClassifyFn_V4 (IN const FWPS_INCOMING_VALUES0* inFixedValues,IN const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,IN OUT VOID* layerData,IN OPTIONAL const void * classifyContext,IN const FWPS_FILTER1* filter,IN UINT64 flowContext,OUT FWPS_CLASSIFY_OUT0* classifyOut) ;NTSTATUS NTAPI Wfp_Sample_Established_NotifyFn_V4 (IN FWPS_CALLOUT_NOTIFY_TYPE notifyType, IN const GUID* filterKey, IN const FWPS_FILTER* filter) ;VOID NTAPI Wfp_Sample_Established_FlowDeleteFn_V4 (IN UINT16 layerId, IN UINT32 calloutId, IN UINT64 flowContext) ;NTSTATUS WfpAddCallouts () ;NTSTATUS WfpRegisterCallouts (IN OUT void * deviceObject) ;NTSTATUS WfpRegisterCalloutImple (IN OUT void * deviceObject,IN FWPS_CALLOUT_CLASSIFY_FN ClassifyFunction,IN FWPS_CALLOUT_NOTIFY_FN NotifyFunction,IN FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN FlowDeleteFunction,IN GUID const * calloutKey,IN UINT32 flags,OUT UINT32* calloutId) ;NTSTATUS WfpAddSubLayer () ;NTSTATUS WfpAddFilters () ;VOID WfpUnRegisterCallouts () ;VOID WfpRemoveCallouts () ;VOID WfpRemoveSubLayer () ;VOID WfpRemoveFilters () ;HANDLE OpenEngine () ;void CloseEngine () ;NTSTATUS InitWfp () ;VOID UninitWfp () ;VOID DeleteDevice () ;
Rule.c:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 #include "fltkernel.h" #include "Rule.h" LIST_ENTRY g_WfpRuleList = { 0 }; KSPIN_LOCK g_RuleLock = 0 ; BOOLEAN InitRuleInfo () { InitializeListHead (&g_WfpRuleList); KeInitializeSpinLock (&g_RuleLock); return TRUE; }; BOOLEAN UninitRuleInfo () { do { KIRQL OldIRQL = 0 ; PLIST_ENTRY pInfo = NULL ; PST_WFP_NETINFOLIST pRule = NULL ; if (g_WfpRuleList.Blink == NULL || g_WfpRuleList.Flink == NULL ) break ; KeAcquireSpinLock (&g_RuleLock, &OldIRQL); while (!IsListEmpty (&g_WfpRuleList)) { pInfo = RemoveHeadList (&g_WfpRuleList); if (pInfo == NULL ) break ; pRule = CONTAINING_RECORD (pInfo, ST_WFP_NETINFOLIST, m_linkPointer); ExFreePoolWithTag (pRule, WFP_TAG); pRule = NULL ; pInfo = NULL ; }; KeReleaseSpinLock (&g_RuleLock, OldIRQL); } while (FALSE); return TRUE; }; BOOLEAN AddNetRuleInfo (PVOID pBuf, ULONG uLen) { BOOLEAN bSucc = FALSE; PST_WFP_NETINFO pRuleInfo = NULL ; do { PST_WFP_NETINFOLIST pRuleNode = NULL ; KIRQL OldIRQL = 0 ; pRuleInfo = (PST_WFP_NETINFO)pBuf; if (pRuleInfo == NULL ) break ; if (uLen < sizeof (ST_WFP_NETINFO)) break ; pRuleNode = (PST_WFP_NETINFOLIST)ExAllocatePoolWithTag (NonPagedPool, sizeof (ST_WFP_NETINFOLIST), WFP_TAG); if (pRuleNode == NULL ) break ; memset (pRuleNode, 0 , sizeof (ST_WFP_NETINFOLIST)); pRuleNode->m_stWfpNetInfo.m_uSrcPort = pRuleInfo->m_uSrcPort; pRuleNode->m_stWfpNetInfo.m_uRemotePort = pRuleInfo->m_uRemotePort; pRuleNode->m_stWfpNetInfo.m_ulSrcIPAddr = pRuleInfo->m_ulSrcIPAddr; pRuleNode->m_stWfpNetInfo.m_ulRemoteIPAddr = pRuleInfo->m_ulRemoteIPAddr; pRuleNode->m_stWfpNetInfo.m_ulNetWorkType = pRuleInfo->m_ulNetWorkType; pRuleNode->m_stWfpNetInfo.m_uDirection = pRuleInfo->m_uDirection; KeAcquireSpinLock (&g_RuleLock, &OldIRQL); InsertHeadList (&g_WfpRuleList, &pRuleNode->m_linkPointer); KeReleaseSpinLock (&g_RuleLock, OldIRQL); bSucc = TRUE; break ; } while (FALSE); return bSucc; }; BOOLEAN IsHitRule (USHORT uRemotePort) { BOOLEAN bIsHit = FALSE; do { KIRQL OldIRQL = 0 ; PLIST_ENTRY pEntry = NULL ; if (g_WfpRuleList.Blink == NULL || g_WfpRuleList.Flink == NULL ) break ; KeAcquireSpinLock (&g_RuleLock, &OldIRQL); pEntry = g_WfpRuleList.Flink; while (pEntry != &g_WfpRuleList) { PST_WFP_NETINFOLIST pInfo = CONTAINING_RECORD (pEntry, ST_WFP_NETINFOLIST, m_linkPointer); if (uRemotePort == pInfo->m_stWfpNetInfo.m_uRemotePort) { bIsHit = TRUE; break ; }; pEntry = pEntry->Flink; }; KeReleaseSpinLock (&g_RuleLock, OldIRQL); } while (FALSE); return bIsHit; };
Rule.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #pragma once #define WFP_TAG 'wfpT' #pragma pack(push) #pragma pack(1) typedef struct _tagWfp_NetInfo { USHORT m_uSrcPort; USHORT m_uRemotePort; ULONG m_ulSrcIPAddr; ULONG m_ulRemoteIPAddr; ULONG m_ulNetWorkType; USHORT m_uDirection; } ST_WFP_NETINFO, * PST_WFP_NETINFO; typedef struct _tagWfp_NetInfoList { LIST_ENTRY m_linkPointer; ST_WFP_NETINFO m_stWfpNetInfo; }ST_WFP_NETINFOLIST, * PST_WFP_NETINFOLIST; #pragma pack(pop) BOOLEAN InitRuleInfo () ;BOOLEAN UninitRuleInfo () ;BOOLEAN AddNetRuleInfo (PVOID pRuleInfo, ULONG uLen) ;BOOLEAN IsHitRule (USHORT uRemotePort) ;