WFP网络过滤

简介

WFP框架整体代码比较死板,直接使用其封装好的API调用,此项目代码整体框架源于WFP网络过滤驱动——限制网站访问,利用WFP框架和IRP通信框架由应用层发送指定的目标IP到驱动层进行封禁访问,也可以对端口、源IP等进行封禁,其中对其代码框架做了初步修改,修改内容如下:

修改内容

增加了封禁和解除封禁目标网站功能,应用层代码从MFC窗口程序转换为普通C项目程序

代码

驱动层Rule.h

#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;//数据包的方向,0表示发送,1表示接收
	BOOLEAN     m_Open;//开启过滤
} 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(ULONG uRemotePort);

驱动层WfpSample.h

#pragma once


#define FILTER_MAJOR_NDIS_VERSION   6

#if defined(NDIS60)
#define FILTER_MINOR_NDIS_VERSION   0
#elseif defined(NDIS620)
#define FILTER_MINOR_NDIS_VERSION   20
#elseif defined(NDIS630)
#define FILTER_MINOR_NDIS_VERSION   30
#endif
#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	55485
#define HTTP_DEFAULT_PORT2	60210
#define IOCTL_WFP_SAMPLE_ADD_RULE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_READ_ACCESS | FILE_WRITE_ACCESS)

// {D969FC67-6FB2-4504-91CE-A97C3C32AD36}
DEFINE_GUID(WFP_SAMPLE_ESTABLITSHE_CALLOUT_V4_GUID, 0xd969fc67, 0x6fb2, 0x4504, 0x91, 0xce, 0xa9, 0x7c, 0x3c, 0x32, 0xad, 0x36);

// {ED6A516A-36D1-4881-BCF0-ACEB4C04C21C}
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  const GUID* 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 WfpAddSubLayer();

NTSTATUS WfpAddFilters();


VOID WfpUnRegisterCallouts();

VOID WfpRemoveCallouts();

VOID WfpRemoveSubLayer();

VOID WfpRemoveFilters();

HANDLE OpenEngine();

void CloseEngine();

NTSTATUS InitWfp();

VOID UninitWfp();

VOID DeleteDevice();

驱动层Rule.c

#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;
		pRuleNode->m_stWfpNetInfo.m_Open = pRuleInfo->m_Open;
		KeAcquireSpinLock(&g_RuleLock,&OldIRQL);
		BOOLEAN exit = FALSE;
		//searchValueInList(&g_WfpRuleList,)
		do
		{
			if (g_WfpRuleList.Blink == NULL ||
				g_WfpRuleList.Flink == NULL)
			{
				DbgPrint("q");
				break;
			}

			PLIST_ENTRY	pEntry = NULL;
			pEntry = g_WfpRuleList.Flink;
			while (pEntry != &g_WfpRuleList)
			{
				//pInfo代表当前存在的链表
				PST_WFP_NETINFOLIST pInfo = CONTAINING_RECORD(pEntry, ST_WFP_NETINFOLIST, m_linkPointer);
				//判断链表是否存在,存在就进入里面
				if (pRuleNode->m_stWfpNetInfo.m_ulRemoteIPAddr == pInfo->m_stWfpNetInfo.m_ulRemoteIPAddr)
				{
					pInfo->m_stWfpNetInfo.m_Open = pRuleNode->m_stWfpNetInfo.m_Open;
					exit = TRUE;
					break;
				}
				pEntry = pEntry->Flink;
			}
		} while (FALSE);
		if (exit == FALSE)
		{
			InsertHeadList(&g_WfpRuleList, &pRuleNode->m_linkPointer);
		}
		exit = FALSE;
		KeReleaseSpinLock(&g_RuleLock,OldIRQL);
		bSucc = TRUE;
		break;
	}
	while (FALSE);
	return bSucc;
}

BOOLEAN IsHitRule(ULONG ulRemoteIPAddress)
{
	BOOLEAN bIsHit = FALSE;
	do 
	{
		
		KIRQL	OldIRQL = 0;
		PLIST_ENTRY	pEntry = NULL;
		if( g_WfpRuleList.Blink == NULL || 
			g_WfpRuleList.Flink == NULL )
		{
			DbgPrint("q");
			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 ((ulRemoteIPAddress == pInfo->m_stWfpNetInfo.m_ulRemoteIPAddr) && pInfo->m_stWfpNetInfo.m_Open == TRUE)
			{
				bIsHit = TRUE;
				break;
			}
			pEntry = pEntry->Flink;
		}
		KeReleaseSpinLock(&g_RuleLock,OldIRQL);
	} 
	while (FALSE);
	return bIsHit;

}

驱动层WfpSample.c

#define NDIS620
#include<ntifs.h>
#include <fwpmk.h>
#include<fwpmk.h>
#include <fwpsk.h>
#define INITGUID
#include <guiddef.h>
#include "WfpSample.h"
//#include "Fwpmu.h"
#include "Rule.h"
#include<fwpmu.h>

/*
本例子只是为了介绍WFP的用法,在实际应用中,如果只是根据简单的规则拦截数据包的话,
可以通过添加过滤器的方法实现。
*/
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;
		}
		// 开始处理DeivceIoControl的情况
		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()
{
	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()
{
	WfpRemoveFilters();
	WfpRemoveSubLayer();
	WfpRemoveCallouts();
	WfpUnRegisterCallouts();
	CloseEngine();
}

void  DriverUnload(__in struct _DRIVER_OBJECT  *DriverObject)
{
	UninitWfp();
	DeleteDevice();
	UninitRuleInfo();
	return;
}


HANDLE OpenEngine()
{
	FWPM_SESSION0 Session = {0};
	HANDLE hEngine = NULL;
	FwpmEngineOpen(NULL,RPC_C_AUTHN_WINNT,NULL,&Session,&hEngine);
	return hEngine;
}

void CloseEngine()
{
	if( g_hEngine != NULL )
	{
		FwpmEngineClose(g_hEngine);
	}
	g_hEngine = NULL;
}


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  const GUID* 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 void* 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_ESTABLITSHE_CALLOUT_V4_GUID,
			0,
			&g_uFwpsEstablishedCallOutId);
		if( status != STATUS_SUCCESS )
		{
			break;
		}
		status = STATUS_SUCCESS;
	} 
	while (FALSE);
	return status;
}

VOID WfpUnRegisterCallouts()
{
	FwpsCalloutUnregisterById(g_uFwpsEstablishedCallOutId);
	g_uFwpsEstablishedCallOutId = 0;
}


NTSTATUS WfpAddCallouts()
{
	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_ESTABLITSHE_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;
	}
	
}

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);
	}
}


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_ESTABLITSHE_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);
	}
}

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
)

{
	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表示数据包的方向,取值为	//FWP_DIRECTION_INBOUND/FWP_DIRECTION_OUTBOUND
	wDirection  = 	inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_DIRECTION].value.int8;

	//wSrcPort表示本地端口,主机序
	wSrcPort	=	inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_PORT].value.uint16;

	//wRemotePort表示远端端口,主机序
	wRemotePort = 	inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_PORT].value.uint16;

	//ulSrcIPAddress 表示源IP
	ulSrcIPAddress = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_ADDRESS].value.uint32;

	//ulRemoteIPAddress 表示远端IP
	ulRemoteIPAddress = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_ADDRESS].value.uint32;
	DbgPrint("remote ip is %x\n", ulRemoteIPAddress);
	
	//wProtocol表示网络协议,可以取值是IPPROTO_ICMP/IPPROTO_UDP/IPPROTO_TCP
	wProtocol = 	inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_PROTOCOL].value.uint8;
	
	//默认"允许"(PERMIT)
	classifyOut->actionType = FWP_ACTION_PERMIT;


	if (IsHitRule(ulRemoteIPAddress))
	{
		classifyOut->actionType = FWP_ACTION_BLOCK;
	}

	
	//清除FWPS_RIGHT_ACTION_WRITE标记
	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
			 )
{

}

应用层代码

#include<stdio.h>
#include<ws2tcpip.h>
#include<windows.h>
#pragma comment(lib,"ws2_32.lib")
typedef struct _tagWfp_NetInfo
{
	USHORT      m_uSrcPort;	//源端口
	USHORT      m_uRemotePort;	//目标端口
	ULONG       m_ulSrcIPAddr; //源地址
	ULONG       m_ulRemoteIPAddr; //目标地址
	ULONG       m_ulNetWorkType; //协议
	USHORT		m_uDirection;//数据包的方向,0表示发送,1表示接收
	BOOLEAN     m_Open;//开启过滤
} ST_WFP_NETINFO, * PST_WFP_NETINFO;
#define IOCTL_WFP_SAMPLE_ADD_RULE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_READ_ACCESS | FILE_WRITE_ACCESS)

int main()
{
	// TODO: Add your control notification handler code here
	//获取端口号
	char** pptr;
	char temp[100] = {0};
	char	str[INET_ADDRSTRLEN];

	printf("请输入你要禁用的网站地址:");
	scanf("%s", temp);
	printf("\r\n");

	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(1, 1);

	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		printf_s("初始化网络库错误\n");
		system("pause");
		return -1;
	}
	
	hostent * host = gethostbyname(temp);

	switch (host->h_addrtype) {
	case AF_INET:
		for (pptr = host->h_addr_list; *pptr != NULL; pptr++) {
			printf("\taddress: %s\n",
				inet_ntop(host->h_addrtype, *pptr, str, sizeof(str)));
		}
		break;
	default:
		printf("unknown address type\n");
		break;
	}

	ULONG a[10] = { 0 };
	int x = 0;
	for (x;; x++)
	{

		ULONG c1 = inet_addr(inet_ntoa(*((in_addr*)host->h_addr_list[x])));


		a[x] = htonl(c1);


		if (host->h_addr_list[x] + host->h_length >= host->h_name)
		{
			break;
		}
	}
	printf("解除禁用过滤请输入0,开启禁用过滤请输入1\r\n");
	int open = 1;
	scanf("%d", &open);

	HANDLE hFile = CreateFile(L"\\\\.\\wfp_sample_device", GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf_s("打开文件wfp_sample_device失败\r\n");
		system("pause");
		return -1;
	}

	// 读者可以在此基础上增加其他域的过滤,如IP,协议类型、数据包方向等
	// Info.m_uRemotePort = uPort;
	for (x; x >= 0; x--)
	{
		ST_WFP_NETINFO Info = { 0 };
		Info.m_ulRemoteIPAddr = a[x];
		DWORD dwNeedSize = 0;
		if (open == 0)
		{
			Info.m_Open = FALSE;
		}
		else
		{
			Info.m_Open = TRUE;
		}
		BOOL rValue = DeviceIoControl(hFile, IOCTL_WFP_SAMPLE_ADD_RULE, (LPVOID)&Info, sizeof(Info), NULL, 0, &dwNeedSize, NULL);
		if (rValue == 0)
		{
			printf_s("failed in x:%d\r\n", x);
			system("pause");
			return -1;
		}
		else
		{
			char* str[] = { "解除禁用","禁用"};
			printf_s("目标主机 %x %s成功\r\n", a[x], str[open]);
		}
	}

	CloseHandle(hFile);
	hFile = INVALID_HANDLE_VALUE;
	system("pause");
	return 0;
}

参考资料

VS驱动开发错误解决
WFP网络过滤驱动——限制网站访问

### WFP过滤实现方式及相关教程 Windows Filtering Platform (WFP) 是一种由 Microsoft 提供的强大网络过滤框架,能够支持开发者在网络协议栈的不同层次上执行复杂的过滤逻辑。以下是关于 WFP 过滤机制的实现方式以及一些常见的示例。 #### 1. **基本概念** WFP 提供了一种分层架构来处理网络流量。这些层包括传输层、网络层和应用层等[^1]。每一层都可以注册回调函数(Callout),以便在特定事件发生时触发自定义行为。例如,当一个数据包进入或离开系统时,可以通过 Callout 函数对其进行分析并决定是否放行。 #### 2. **核心组件** - **Filter Conditions**: 定义哪些类型的流量应该被拦截或者检查。 - **Actions**: 对匹配条件的数据流采取的操作,比如允许通行、丢弃或是进一步加工。 - **Callouts**: 用户编写的代码片段,用来扩展默认的功能集;每当符合条件的新连接建立起来的时候就会调用相应的 Callout 方法[^3]。 #### 3. **具体实现步骤** ##### 注册一个新的 Filter 和关联的 Callout 下面是一个简单的例子展示如何设置基础的 IP 地址过滤器: ```c++ // 创建 filter 条件对象 FWPM_FILTER_CONDITION0 condition; condition.fieldKey = FWPM_FIELD_IP_REMOTE_ADDRESS; // 设置字段关键字为目标地址 condition.matchType = FWP_MATCH_EQUAL; // 使用等于比较运算符 condition.conditionValue.type = FWP_UINT32_TYPE; condition.conditionValue.uint32 = inet_addr("192.168.1.1"); // 构建完整的 filters 结构体数组 FWP_VALUE0 values[] = { ... }; // 初始化其他必要参数... UINT32 numFilters = sizeof(values)/sizeof(FWP_VALUE0); FWPM_FILTER0* pFilter = new FWPM_FILTER0[numFilters]; for(UINT i=0;i<numFilters;++i){ memset(&pFilter[i], 0, sizeof(FWPM_FILTER0)); ... } // 调用 API 将其加入到系统中生效 HRESULT hr = FwpmFilterAdd(engineHandle,&filter,NULL,&id); if(SUCCEEDED(hr)){ printf("Successfully added filter with ID %llu\n", id.QuadPart); } else{ fprintf(stderr,"Failed adding filter! Error code:%X\n",hr); } ``` 此段伪代码展示了怎样构建基于远程IP地址的具体规则,并将其提交给操作系统以实际运用。注意这里省略了许多细节部分如错误检测等等[^5]。 另外还有一种情况涉及到长时间决策过程的情况,则可能需要用到异步完成模型即所谓的ALE Pend/Complete Mechanism[^4]。在这种模式下,初始阶段仅做初步判定并将请求挂起等待最终裁定结果出来后再继续后续动作。 #### 4. **参考资料链接** 虽然提到过几个项目资源但并未详细介绍,如果想更深入了解实践案例的话可以从官方文档入手学习更多高级特性[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值