WFP学习记录

狂风中的少年 提交于 2020-04-20 08:54:24

最近闲来无事,翻看wfp的资料,发现WFP真是好用,就是资料太稀少~好在有WDK的src目录和万能的搜索引擎. 后来发现http://www.cnblogs.com/nevergone/archive/2013/04/05/3001765.html 挺不错的,于是就把那份代码给改了一下,做一个网络日志记录小程序. 

#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.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

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!