第一个WFP驱动

转载于原文地址

main.h

#ifndef __MAIN_H__
#define __MAIN_H__
 
#include <ntifs.h>
#include <ip2string.h>
 
#pragma warning(push)
#pragma warning(disable: 4201)
#pragma warning(disable: 4324)
#include <fwpsk.h>
#include <fwpmk.h>
#pragma warning(pop)
 
#define INITGUID
#include <guiddef.h>
 
// 
// Callout and sublayer GUIDs
//
 
DEFINE_GUID(
    SF_ALE_CONNECT_CALLOUT_V4,
    0x76b743d4,
    0x1249,
    0x4610,
    0xa6, 0x32, 0x6f, 0x9c, 0x4d, 0x08, 0xd2, 0x5a
    );
 
DEFINE_GUID(
    SF_ALE_RECV_ACCEPT_CALLOUT_V4,
    0x7ec7f7f5,
    0x1249,
    0x4614,
    0xa6, 0x32, 0x6f, 0x9c, 0x4d, 0x08, 0xd2, 0x5a
    );
    
DEFINE_GUID(
    SF_ALE_ESTABLISHED_CALLOUT_V4,
    0x7ec7f7f5,
    0x1249,
    0x4618,
    0xa6, 0x32, 0x6f, 0x9c, 0x4d, 0x08, 0xd2, 0x5a
    );
 
DEFINE_GUID(
    SF_SUBLAYER,
    0x7ec7f7f5,
    0x1249,
    0x4620,
    0xa6, 0x32, 0x6f, 0x9c, 0x4d, 0x08, 0xd2, 0x5a
    );
    
typedef enum _OP_TYPE
{
    OP_NONE = 0,
    OP_CONNECT = 1,
    OP_ACCEPT = 2,
    OP_ESTABLISHED = 3,
}OP_TYPE;
 
typedef struct _CALLOUT_INFO
{
    LIST_ENTRY    List;
    LARGE_INTEGER Time;
    OP_TYPE       Type;
    ULONG         ProcessId; 
    //UINT64        calloutId;       
    ULONG         localAddressV4;
    USHORT        localPort;
    ULONG         remoteAddressV4;
    USHORT        remotePort;
    USHORT        ipProto;    
    WCHAR         ProcessPath[1];
} CALLOUT_INFO, *PCALLOUT_INFO;
 
NTSTATUS
DriverEntry(
    __in PDRIVER_OBJECT DriverObject,
    __in PUNICODE_STRING RegistryPath
    );
 
VOID 
DriverUnload(
    __in PDRIVER_OBJECT DriverObject
    );
 
NTSTATUS
DeviceDispatch(
    __in PDEVICE_OBJECT DeviceObject,
    __in PIRP Irp
    );
 
NTSTATUS
SFRegistryCallouts(
    __in PDEVICE_OBJECT DeviceObject
    );
 
void
SFDeregistryCallouts(
    __in PDEVICE_OBJECT DeviceObject
    );
 
NTSTATUS
SFRegisterALEClassifyCallouts(
    __in const GUID* layerKey,
    __in const GUID* calloutKey,
    __in void* DeviceObject,
    __out UINT32* calloutId
    );
    
NTSTATUS
SFAddFilter(
    __in const wchar_t* filterName,
    __in const wchar_t* filterDesc,
    __in const GUID* layerKey,
    __in const GUID* calloutKey
    );
 
NTSTATUS
SFALEConnectNotify(
    __in FWPS_CALLOUT_NOTIFY_TYPE notifyType,
    __in const GUID* filterKey,
    __in const FWPS_FILTER0* filter
    );
 
NTSTATUS
SFALERecvAcceptNotify(
    __in FWPS_CALLOUT_NOTIFY_TYPE notifyType,
    __in const GUID* filterKey,
    __in const FWPS_FILTER0* filter
    );
 
NTSTATUS
SFALEEstablishedNotify(
    __in FWPS_CALLOUT_NOTIFY_TYPE notifyType,
    __in const GUID* filterKey,
    __in const FWPS_FILTER0* filter
    );
    
void
SFALEConnectClassify(
    __in const FWPS_INCOMING_VALUES0* inFixedValues,
    __in const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
    __inout void* layerData,
    __in const FWPS_FILTER0* filter,
    __in UINT64 flowContext,
    __in FWPS_CLASSIFY_OUT0* classifyOut
    );
    
void
SFALERecvAcceptClassify(
    __in const FWPS_INCOMING_VALUES0* inFixedValues,
    __in const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
    __inout void* layerData,
    __in const FWPS_FILTER0* filter,
    __in UINT64 flowContext,
    __inout FWPS_CLASSIFY_OUT0* classifyOut
    );
    
void
SFALEEstablishedClassify(
    __in const FWPS_INCOMING_VALUES0* inFixedValues,
    __in const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
    __inout void* layerData,
    __in const FWPS_FILTER0* filter,
    __in UINT64 flowContext,
    __inout FWPS_CLASSIFY_OUT0* classifyOut
    );
    
VOID
ThreadStart(
   IN PVOID StartContext
   );
    
#endif//__MAIN_H__

main.c

#include "main.h"

HANDLE     gInjectionHandle;
HANDLE     gEngineHandle;
UINT32     gAleConnectCalloutIdV4;
UINT32     gAleRecvAcceptCalloutIdV4;
UINT32     gAleEstablishedCalloutIdV4;

LIST_ENTRY gCalloutInfoList;
KSPIN_LOCK gCalloutInfoLock;
KEVENT     gWorkerEvent;

NTSTATUS
DriverEntry(
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
	PDEVICE_OBJECT  DeviceObject = NULL;
	NTSTATUS        Status;
	HANDLE          ThreadHandle;
	UNICODE_STRING  DeviceName;

	//
	// Initialize the driver object with this driver's entry points.
	//

	DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceDispatch;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceDispatch;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceDispatch;

	DriverObject->DriverUnload = DriverUnload;

	//
	//  Create control device object
	//

	RtlInitUnicodeString(&DeviceName, L"\\Device\\NetFlow");

	Status = IoCreateDevice(DriverObject,
		sizeof(HANDLE)+sizeof(LONG),
		&DeviceName,
		FILE_DEVICE_UNKNOWN,
		FILE_DEVICE_SECURE_OPEN,
		FALSE,
		&DeviceObject);

	if (NT_SUCCESS(Status))
	{
		InitializeListHead(&gCalloutInfoList);
		KeInitializeSpinLock(&gCalloutInfoLock);
		KeInitializeEvent(&gWorkerEvent, NotificationEvent, FALSE); //KdBreakPoint();

		Status = SFRegistryCallouts(DeviceObject);

		if (NT_SUCCESS(Status))
		{
			*(PLONG)((PCH)DeviceObject->DeviceExtension + sizeof(HANDLE)) = FALSE;

			Status = PsCreateSystemThread(&ThreadHandle,
				THREAD_ALL_ACCESS,
				NULL,
				NULL,
				NULL,
				ThreadStart,
				(PVOID)((PCH)DeviceObject->DeviceExtension + sizeof(HANDLE)));
			if (!NT_SUCCESS(Status))
			{
				SFDeregistryCallouts(DeviceObject);
			}
			else
			{
				*(PHANDLE)DeviceObject->DeviceExtension = ThreadHandle;
			}
		}

		if (!NT_SUCCESS(Status))
		{
			IoDeleteDevice(DeviceObject);
		}
	}

	return Status;
}

VOID
DriverUnload(
__in PDRIVER_OBJECT DriverObject
)
{
	KIRQL          OldIrql;
	PLIST_ENTRY    lpEntry;
	PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
	HANDLE         ThreadHandle = *(PHANDLE)DeviceObject->DeviceExtension;
	PLONG          pbUnloading = (PLONG)((PCH)DeviceObject->DeviceExtension + sizeof(HANDLE));

	SFDeregistryCallouts(DeviceObject);

	InterlockedExchange(pbUnloading, TRUE);
	KeSetEvent(&gWorkerEvent, IO_NO_INCREMENT, FALSE);

	ZwWaitForSingleObject(ThreadHandle, FALSE, NULL);
	ZwClose(ThreadHandle);

	KeAcquireSpinLock(&gCalloutInfoLock, &OldIrql);
	while (!IsListEmpty(&gCalloutInfoList))
	{
		lpEntry = RemoveHeadList(&gCalloutInfoList);

		KeReleaseSpinLock(&gCalloutInfoLock, OldIrql);

		ExFreePoolWithTag(lpEntry, ' lT ');

		KeAcquireSpinLock(&gCalloutInfoLock, &OldIrql);
	}
	KeReleaseSpinLock(&gCalloutInfoLock, OldIrql);

	IoDeleteDevice(DeviceObject);
}

NTSTATUS
DeviceDispatch(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
{
	PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);
	NTSTATUS Status = STATUS_NOT_SUPPORTED;

	Irp->IoStatus.Information = 0;

	switch (irpsp->MajorFunction)
	{
	case IRP_MJ_CREATE:
	case IRP_MJ_CLOSE:
		Status = STATUS_SUCCESS;
		break;
	case IRP_MJ_DEVICE_CONTROL:
		Status = STATUS_INVALID_DEVICE_REQUEST;
		break;
	}

	Irp->IoStatus.Status = Status;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return Status;
}

NTSTATUS
SFRegistryCallouts(
__in PDEVICE_OBJECT DeviceObject
)
{
	NTSTATUS        Status = STATUS_SUCCESS;
	BOOLEAN         EngineOpened = FALSE;
	BOOLEAN         InTransaction = FALSE;
	FWPM_SESSION0   Session = { 0 };
	FWPM_SUBLAYER0  FirewallSubLayer;

	Session.flags = FWPM_SESSION_FLAG_DYNAMIC;

	Status = FwpmEngineOpen0(NULL,
		RPC_C_AUTHN_WINNT,
		NULL,
		&Session,
		&gEngineHandle);

	if (!NT_SUCCESS(Status))
	{
		goto Exit;
	}

	EngineOpened = TRUE;

	Status = FwpmTransactionBegin0(gEngineHandle, 0);

	if (!NT_SUCCESS(Status))
	{
		goto Exit;
	}

	InTransaction = TRUE;

	RtlZeroMemory(&FirewallSubLayer, sizeof(FWPM_SUBLAYER0));

	FirewallSubLayer.subLayerKey = SF_SUBLAYER;
	FirewallSubLayer.displayData.name = L"Transport SimpleFirewall Sub-Layer";
	FirewallSubLayer.displayData.description = L"Sub-Layer for use by Transport SimpleFirewall callouts";
	FirewallSubLayer.flags = 0;
	FirewallSubLayer.weight = 0;

	Status = FwpmSubLayerAdd0(gEngineHandle, &FirewallSubLayer, NULL);

	if (!NT_SUCCESS(Status))
	{
		goto Exit;
	}

	Status = SFRegisterALEClassifyCallouts(&FWPM_LAYER_ALE_AUTH_CONNECT_V4,
		&SF_ALE_CONNECT_CALLOUT_V4,
		DeviceObject,
		&gAleConnectCalloutIdV4);

	if (!NT_SUCCESS(Status))
	{
		goto Exit;
	}

	Status = SFRegisterALEClassifyCallouts(&FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4,
		&SF_ALE_RECV_ACCEPT_CALLOUT_V4,
		DeviceObject,
		&gAleRecvAcceptCalloutIdV4);

	if (!NT_SUCCESS(Status))
	{
		goto Exit;
	}

	Status = SFRegisterALEClassifyCallouts(&FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4,
		&SF_ALE_ESTABLISHED_CALLOUT_V4,
		DeviceObject,
		&gAleEstablishedCalloutIdV4);

	if (!NT_SUCCESS(Status))
	{
		goto Exit;
	}

	Status = FwpmTransactionCommit0(gEngineHandle);

	if (!NT_SUCCESS(Status))
	{
		goto Exit;
	}

	InTransaction = FALSE;

Exit:

	if (!NT_SUCCESS(Status))
	{
		if (InTransaction)
		{
			FwpmTransactionAbort0(gEngineHandle);
		}

		if (EngineOpened)
		{
			FwpmEngineClose0(gEngineHandle);
			gEngineHandle = NULL;
		}
	}

	return Status;
}

void
SFDeregistryCallouts(
__in PDEVICE_OBJECT DeviceObject
)
{
	UNREFERENCED_PARAMETER(DeviceObject);

	FwpmEngineClose0(gEngineHandle);
	gEngineHandle = NULL;

	FwpsCalloutUnregisterById0(gAleConnectCalloutIdV4);
	FwpsCalloutUnregisterById0(gAleRecvAcceptCalloutIdV4);
	FwpsCalloutUnregisterById0(gAleEstablishedCalloutIdV4);
}

NTSTATUS
SFRegisterALEClassifyCallouts(
__in const GUID* layerKey,
__in const GUID* calloutKey,
__in void* DeviceObject,
__out UINT32* calloutId
)
{
	NTSTATUS Status = STATUS_SUCCESS;

	FWPS_CALLOUT0 sCallout = { 0 };
	FWPM_CALLOUT0 mCallout = { 0 };

	FWPM_DISPLAY_DATA0 DisplayData = { 0 };

	BOOLEAN calloutRegistered = FALSE;

	sCallout.calloutKey = *calloutKey;

	if (IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_CONNECT_V4))
	{
		sCallout.classifyFn = SFALEConnectClassify;
		sCallout.notifyFn = SFALEConnectNotify;
	}
	else if (IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4))
	{
		sCallout.classifyFn = SFALERecvAcceptClassify;
		sCallout.notifyFn = SFALERecvAcceptNotify;
	}
	else
	{
		sCallout.classifyFn = SFALEEstablishedClassify;
		sCallout.notifyFn = SFALEEstablishedNotify;
	}

	Status = FwpsCalloutRegister0(DeviceObject,
		&sCallout,
		calloutId);

	if (NT_SUCCESS(Status))
	{
		DisplayData.name = L"Transport SimpleFirewall ALE Classify Callout";
		DisplayData.description = L"Intercepts inbound or outbound connect attempts";

		mCallout.calloutKey = *calloutKey;
		mCallout.displayData = DisplayData;
		mCallout.applicableLayer = *layerKey;

		Status = FwpmCalloutAdd0(gEngineHandle,
			&mCallout,
			NULL,
			NULL);

		if (NT_SUCCESS(Status))
		{
			//没有Filter(FwpmFilterAdd0), ClassifyFn/NotifyFn就处于未激活状态

			Status = SFAddFilter(L"Transport SimpleFirewall ALE Classify",
				L"Intercepts inbound or outbound connect attempts",
				layerKey,
				calloutKey);
		}

		if (!NT_SUCCESS(Status))
		{
			FwpsCalloutUnregisterById0(*calloutId);
			*calloutId = 0;
		}
	}

	return Status;
}

NTSTATUS
SFAddFilter(
__in const wchar_t* filterName,
__in const wchar_t* filterDesc,
__in const GUID* layerKey,
__in const GUID* calloutKey
)
{
	FWPM_FILTER0 Filter = { 0 };

	Filter.layerKey = *layerKey;
	Filter.displayData.name = (wchar_t*)filterName;
	Filter.displayData.description = (wchar_t*)filterDesc;

	Filter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
	Filter.action.calloutKey = *calloutKey;
	Filter.subLayerKey = SF_SUBLAYER;
	Filter.weight.type = FWP_EMPTY;
	Filter.rawContext = 0;

	return FwpmFilterAdd0(gEngineHandle, &Filter, NULL, NULL);
}

NTSTATUS
SFALERecvAcceptNotify(
__in FWPS_CALLOUT_NOTIFY_TYPE notifyType,
__in const GUID* filterKey,
__in const FWPS_FILTER0* filter
)
{
	UNREFERENCED_PARAMETER(notifyType);
	UNREFERENCED_PARAMETER(filterKey);
	UNREFERENCED_PARAMETER(filter);

	return STATUS_SUCCESS;
}

NTSTATUS
SFALEConnectNotify(
__in FWPS_CALLOUT_NOTIFY_TYPE notifyType,
__in const GUID* filterKey,
__in const FWPS_FILTER0* filter
)
{
	UNREFERENCED_PARAMETER(notifyType);
	UNREFERENCED_PARAMETER(filterKey);
	UNREFERENCED_PARAMETER(filter);

	return STATUS_SUCCESS;
}

NTSTATUS
SFALEEstablishedNotify(
__in FWPS_CALLOUT_NOTIFY_TYPE notifyType,
__in const GUID* filterKey,
__in const FWPS_FILTER0* filter
)
{
	UNREFERENCED_PARAMETER(notifyType);
	UNREFERENCED_PARAMETER(filterKey);
	UNREFERENCED_PARAMETER(filter);

	return STATUS_SUCCESS;
}

void
SFALEConnectClassify(
__in const FWPS_INCOMING_VALUES0* inFixedValues,
__in const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
__inout void* layerData,
__in const FWPS_FILTER0* filter,
__in UINT64 flowContext,
__in FWPS_CLASSIFY_OUT0* classifyOut
)
{
	NTSTATUS status = STATUS_SUCCESS;
	KIRQL    OldIrql;
	UINT32   index;
	ULONG    Length;
	PCALLOUT_INFO Info;


	//classifyOut->actionType = FWP_ACTION_CONTINUE;
	classifyOut->actionType = FWP_ACTION_PERMIT;

	//
	// We don't have the necessary right to alter the classify, exit.
	//
	if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
	{
		return;
	}

	if (!FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_PROCESS_ID))
	{
		return;
	}
	if (!FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_PROCESS_PATH))
	{
		return;
	}

	Length = sizeof(CALLOUT_INFO)+inMetaValues->processPath->size;
	Info = ExAllocatePoolWithTag(NonPagedPool, Length, ' lT ');

	if (Info == NULL)
	{
		return;
	}

	RtlZeroMemory(Info, Length);
	RtlCopyMemory(Info->ProcessPath, inMetaValues->processPath->data, inMetaValues->processPath->size);

	Info->Type = OP_CONNECT;
	Info->ProcessId = (ULONG)inMetaValues->processId;

	index = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS;
	Info->localAddressV4 = RtlUlongByteSwap(inFixedValues->incomingValue[index].value.uint32);

	index = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_PORT;
	Info->localPort = inFixedValues->incomingValue[index].value.uint16;

	index = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS;
	Info->remoteAddressV4 = RtlUlongByteSwap(inFixedValues->incomingValue[index].value.uint32);

	index = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_PORT;
	Info->remotePort = inFixedValues->incomingValue[index].value.uint16;

	index = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL;
	Info->ipProto = inFixedValues->incomingValue[index].value.uint8;

	KeQuerySystemTime(&Info->Time);
	InitializeListHead(&Info->List);

	KeAcquireSpinLock(&gCalloutInfoLock, &OldIrql);
	InsertTailList(&gCalloutInfoList, &Info->List);
	KeReleaseSpinLock(&gCalloutInfoLock, OldIrql);

	//if ( KeGetCurrentIrql() <= APC_LEVEL )
	{
		KeSetEvent(&gWorkerEvent, IO_NO_INCREMENT, FALSE);
	}
}

void
SFALERecvAcceptClassify(
__in const FWPS_INCOMING_VALUES0* inFixedValues,
__in const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
__inout void* layerData,
__in const FWPS_FILTER0* filter,
__in UINT64 flowContext,
__inout FWPS_CLASSIFY_OUT0* classifyOut
)
{
	NTSTATUS status = STATUS_SUCCESS;
	KIRQL    OldIrql;
	UINT32   index;
	ULONG    Length;
	PCALLOUT_INFO Info;


	//classifyOut->actionType = FWP_ACTION_CONTINUE;
	classifyOut->actionType = FWP_ACTION_PERMIT;

	//
	// We don't have the necessary right to alter the classify, exit.
	//
	if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
	{
		return;
	}

	if (!FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_PROCESS_ID))
	{
		return;
	}
	if (!FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_PROCESS_PATH))
	{
		return;
	}

	Length = sizeof(CALLOUT_INFO)+inMetaValues->processPath->size;
	Info = ExAllocatePoolWithTag(NonPagedPool, Length, ' lT ');

	if (Info == NULL)
	{
		return;
	}

	RtlZeroMemory(Info, Length);
	RtlCopyMemory(Info->ProcessPath, inMetaValues->processPath->data, inMetaValues->processPath->size);

	Info->Type = OP_ACCEPT;
	Info->ProcessId = (ULONG)inMetaValues->processId;

	index = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_LOCAL_ADDRESS;
	Info->localAddressV4 = RtlUlongByteSwap(inFixedValues->incomingValue[index].value.uint32);

	index = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_LOCAL_PORT;
	Info->localPort = inFixedValues->incomingValue[index].value.uint16;

	index = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_REMOTE_ADDRESS;
	Info->remoteAddressV4 = RtlUlongByteSwap(inFixedValues->incomingValue[index].value.uint32);

	index = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_REMOTE_PORT;
	Info->remotePort = inFixedValues->incomingValue[index].value.uint16;

	index = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_PROTOCOL;
	Info->ipProto = inFixedValues->incomingValue[index].value.uint8;

	KeQuerySystemTime(&Info->Time);
	InitializeListHead(&Info->List);

	KeAcquireSpinLock(&gCalloutInfoLock, &OldIrql);
	InsertTailList(&gCalloutInfoList, &Info->List);
	KeReleaseSpinLock(&gCalloutInfoLock, OldIrql);

	//if ( KeGetCurrentIrql() <= APC_LEVEL )
	{
		KeSetEvent(&gWorkerEvent, IO_NO_INCREMENT, FALSE);
	}
}

void
SFALEEstablishedClassify(
__in const FWPS_INCOMING_VALUES0* inFixedValues,
__in const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
__inout void* layerData,
__in const FWPS_FILTER0* filter,
__in UINT64 flowContext,
__inout FWPS_CLASSIFY_OUT0* classifyOut
)
{
	NTSTATUS status = STATUS_SUCCESS;
	KIRQL    OldIrql;
	UINT32   index;
	ULONG    Length;
	PCALLOUT_INFO Info;

	//classifyOut->actionType = FWP_ACTION_CONTINUE;
	classifyOut->actionType = FWP_ACTION_PERMIT;

	//
	// We don't have the necessary right to alter the classify, exit.
	//
	if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
	{
		return;
	}

	if (!FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_PROCESS_ID))
	{
		return;
	}
	if (!FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_PROCESS_PATH))
	{
		return;
	}

	Length = sizeof(CALLOUT_INFO)+inMetaValues->processPath->size;
	Info = ExAllocatePoolWithTag(NonPagedPool, Length, ' lT ');

	if (Info == NULL)
	{
		return;
	}

	RtlZeroMemory(Info, Length);
	RtlCopyMemory(Info->ProcessPath, inMetaValues->processPath->data, inMetaValues->processPath->size);

	Info->Type = OP_ESTABLISHED;
	Info->ProcessId = (ULONG)inMetaValues->processId;

	index = FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_ADDRESS;
	Info->localAddressV4 = RtlUlongByteSwap(inFixedValues->incomingValue[index].value.uint32);

	index = FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_PORT;
	Info->localPort = inFixedValues->incomingValue[index].value.uint16;

	index = FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_ADDRESS;
	Info->remoteAddressV4 = RtlUlongByteSwap(inFixedValues->incomingValue[index].value.uint32);

	index = FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_PORT;
	Info->remotePort = inFixedValues->incomingValue[index].value.uint16;

	index = FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_PROTOCOL;
	Info->ipProto = inFixedValues->incomingValue[index].value.uint8;

	KeQuerySystemTime(&Info->Time);
	InitializeListHead(&Info->List);

	KeAcquireSpinLock(&gCalloutInfoLock, &OldIrql);
	InsertTailList(&gCalloutInfoList, &Info->List);
	KeReleaseSpinLock(&gCalloutInfoLock, OldIrql);

	//if ( KeGetCurrentIrql() <= APC_LEVEL )
	{
		KeSetEvent(&gWorkerEvent, IO_NO_INCREMENT, FALSE);
	}
}

VOID
HandleCalloutInfo(
IN PVOID Context
)
{
	PCWSTR OpType[4] = { L"N/A", L"Connect", L"Accept", L"Established" };
	PCALLOUT_INFO Info = Context;

	WCHAR szlocalAddressV4[24] = { 0 };
	WCHAR szremoteAddressV4[24] = { 0 };

	RtlIpv4AddressToStringW((PIN_ADDR)&Info->localAddressV4, szlocalAddressV4);
	RtlIpv4AddressToStringW((PIN_ADDR)&Info->remoteAddressV4, szremoteAddressV4);

	DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[@] %ws(%d) <-%d-> %ws(%d), %ws : %d, %ws\r\n",
		szlocalAddressV4,
		Info->localPort,
		Info->ipProto,
		szremoteAddressV4,
		Info->remotePort,
		OpType[Info->Type],
		Info->ProcessId,
		Info->ProcessPath);
}

VOID
ThreadStart(
IN PVOID StartContext
)
{
	PLONG         pbUnloading = StartContext;
	LARGE_INTEGER Interval = { (ULONG)(-5 * 1000 * 1000 * 10), -1 };
	KIRQL         OldIrql;
	PLIST_ENTRY   lpEntry;

	while (TRUE)
	{
		KeWaitForSingleObject(&gWorkerEvent, Executive, KernelMode, FALSE, &Interval);

		if (InterlockedCompareExchange(pbUnloading, TRUE, TRUE))
		{
			break;
		}

		KeAcquireSpinLock(&gCalloutInfoLock, &OldIrql);
		while (!IsListEmpty(&gCalloutInfoList))
		{
			lpEntry = RemoveHeadList(&gCalloutInfoList);

			KeReleaseSpinLock(&gCalloutInfoLock, OldIrql);

			HandleCalloutInfo(lpEntry);

			ExFreePoolWithTag(lpEntry, ' lT ');

			KeAcquireSpinLock(&gCalloutInfoLock, &OldIrql);
		}
		KeReleaseSpinLock(&gCalloutInfoLock, OldIrql);
	}
}

sources文件

TARGETNAME=netflow
TARGETTYPE=DRIVER
TARGETPATH=..
 
INCLUDES=\
   $(DDK_INC_PATH);
 
TARGETLIBS=\
    $(DDK_LIB_PATH)\ntoskrnl.lib \
    $(DDK_LIB_PATH)\ndis.lib \
    $(DDK_LIB_PATH)\fwpkclnt.lib \
    $(SDK_LIB_PATH)\uuid.lib
 
C_DEFINES=$(C_DEFINES) -DBINARY_COMPATIBLE=0 -DNT -DUNICODE -D_UNICODE -DNDIS60 -DNDIS_SUPPORT_NDIS6
 
SOURCES = main.c

使用WDK7600 checked 64编译通过,win7 64正常运行
有多个源文件的情况下sources需要像下面这么编写

SOURCES = TL_drv.c\
inspect.c\
utils.c
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值