Windows驱动_WFP之四WFP代码基本流程的剖析

        总说程序员是孤独的,因为,大部分的时间都在和机器打交道。大部分的时间都在自言自语。我的内心需要足够的强大。这种强大时建立的自信的基础上的。而自信又是建立在实力基础上的。实力又是建立在积累的基础上。积累又是建立在时间的基础上。所以归根结底,就是,需要花费更多的时间。第二,需要有足够的兴趣爱好。这两点对于现在的我来说,都有。既然,自己选择了这条路,就应该义无反顾的走下去,坚持的走下去。孤独,我不怕,困难,我也不怕,永远向上的动力,爱好,对知识的渴望,支持者我。相信自己,相信明天。


      今天实际看一下,WFP的Callout驱动的代码。先从DriverEntry开始:


1,在DriverEntry需要创建驱动对象和设备对象,
   
    1.1  由于不是PNP设备,需要设置创建驱动对象的标志为config.DriverInitFlags |= WdfDriverInitNonPnpDriver.
    1.2  调用WdfDriverCreate创建驱动对象。
    1.3  调用WdfControlDeviceInitAllocate通过驱动对象创建 WDFDEVICE_INIT结构体。
    1.4  调用WdfDeviceInitSetDeviceType设置设备类型为FILE_DEVICE_NETWORK.
    1.5  调用WdfDeviceInitSetCharacteristics设置设备的特性为FILE_DEVICE_SECURE_OPEN和FILE_AUTOGENERATED_DEVICE_NAME.
    1.6  调用WdfDeviceCreate创建设备对象。
    1.7  调用WdfControlFinishInitializing设置设备的初始化状态为完成。
    1.8  调用FwpsInjectionHandleCreate创建一个检测的句柄。并设置在哪里完成检查。通过在转发层,网络层,流层,传输层。
    1.9  调用WdfDeviceWdmGetDeviceObject将框架设备对象转换为设备对象的指针。
    1.10 调用FwpmEngineOpen打开一个和过滤引擎的会话,这个函数会返回一个过滤引擎的句柄。
    1.11 调用FwpmTransactionBegin在当前的会话下,开始一个明确的传输。
    1.12 调用FwpmSubLayerAdd函数玩系统中增加一个子层。
   
          DWORD WINAPI FwpmSubLayerAdd0(
    _In_      HANDLE engineHandle,
    _In_      const FWPM_SUBLAYER0 *subLayer,
    _In_opt_  PSECURITY_DESCRIPTOR sd
      );


      这里我们主要来看第二个参数,FWPM_SUBLAYER0这个结构体。
      
      typedef struct FWPM_SUBLAYER0_ {
    GUID               subLayerKey;
    FWPM_DISPLAY_DATA0 displayData;
    UINT16             flags;
    GUID               *providerKey;
    FWP_BYTE_BLOB      providerData;
    UINT16             weight;
    } FWPM_SUBLAYER0;
    
    这里,我们主要看第一个GUID,后面的需要在例子后分析。这个可以定义的GUID.
    
    DEFINE_GUID(
    DD_PROXY_SUBLAYER,
    0x0104fd7e,
    0xc825,
    0x414e,
    0x94, 0xc9, 0xf0, 0xd5, 0x25, 0xbb, 0xc1, 0x69
    );
    
       DDProxySubLayer.subLayerKey = DD_PROXY_SUBLAYER;
       DDProxySubLayer.displayData.name = L"Datagram-Data Proxy Sub-Layer";
       DDProxySubLayer.displayData.description = 
       L"Sub-Layer for use by Datagram-Data Proxy callouts";
       DDProxySubLayer.flags = 0;
       DDProxySubLayer.weight = FWP_EMPTY; // auto-weight.;
       
    1.13  调用FwpsCalloutRegister注册一个callout:
          NTSTATUS NTAPI FwpsCalloutRegister0(
      _Inout_    void *deviceObject,
      _In_       const FWPS_CALLOUT0 *callout,
      _Out_opt_  UINT32 *calloutId
    );
    这里主要是第二个参数的设置:
    
    typedef struct FWPS_CALLOUT0_ {
        GUID                                 calloutKey;
    UINT32                              flags;
    FWPS_CALLOUT_CLASSIFY_FN0           classifyFn;
    FWPS_CALLOUT_NOTIFY_FN0             notifyFn;
    FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN0 flowDeleteFn;
    } FWPS_CALLOUT0;
    
    这里的calloutKey是一个GUID值,我们可以定义。classifyFn为驱动分类的函数入口。notifyFn为通知消息的函数入口。flowDeleteFn为流程删除的函数入口。
    
    1.14  调用FwpmCalloutAdd,向过滤引擎增加一个callout.
   
    NTSTATUS NTAPI FwpmCalloutAdd0(
    _In_       HANDLE engineHandle,
    _In_       const FWPM_CALLOUT0 *callout,
    _In_opt_   PSECURITY_DESCRIPTOR sd,
    _Out_opt_  UINT32 *id
    );
    
    这里还是看第二个参数,FWPM_CALLOUT0.
    
    typedef struct FWPM_CALLOUT0_ {
    GUID               calloutKey;
    FWPM_DISPLAY_DATA0 displayData;
    UINT32             flags;
    GUID               *providerKey;
    FWP_BYTE_BLOB      providerData;
    GUID               applicableLayer;
    UINT32             calloutId;
    } FWPM_CALLOUT0;
    
    所以我们看到,这里我们有两个CALLOUT了,一个是FWPS_CALLOUT0,一个是FWPM_CALLOUT0,FWPS_CALLOUT0是给驱动用的,所以这里将其CALLOUT跟设备对象进行关联,但是后面还有个FWPM_CALLOUT0,这个就是跟过滤引擎进行交互的。再看其实这两个CALLOUT的GUID值是一样的,所以这样就进行了关联。两个CALLOUT相互关联,又相互独立,FWPM_CALLOUT0,负责和过滤引擎相关的操作。FWPS_CALLOUT0负责和驱动相关本身的操作。
这样,从驱动本身的驱动对象,设备对象和过滤引擎中的过滤层和CALLOUT进行联系上了。
  
    1.15  调用FwpmFilterAdd增加一个过滤对象到系统中。
   
          DWORD WINAPI FwpmFilterAdd0(
    _In_       HANDLE engineHandle,
    _In_       const FWPM_FILTER0 *filter,
    _In_opt_   SECURITY_DESCRIPTOR sd,
    _Out_opt_  UINT64 *id
      );
      
      这里还是第二个参数,const FWPM_FILTER0 *filter,非常复杂的结构,这个是精髓,必须好好看。
      
      typedef struct FWPM_FILTER0_ {
    GUID                   filterKey;
    FWPM_DISPLAY_DATA0     displayData;
    UINT32                 flags;
    GUID                   *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;
    };
    GUID                   *reserved;
    UINT64                 filterId;
    FWP_VALUE0             effectiveWeight;
    } FWPM_FILTER0;


    我们先把,结构体中包含的结构,进行展开。
    
    typedef struct FWPM_DISPLAY_DATA0_ {
      wchar_t *name;
      wchar_t *description;
    } FWPM_DISPLAY_DATA0;
    
    typedef struct FWP_BYTE_BLOB_ {
      UINT32 size;
      UINT8  *data;
    } FWP_BYTE_BLOB;
    
    关于providerKey代表的是WFP内部定义的一些GUID.
    
    typedef struct FWP_VALUE0_ {
    
      FWP_DATA_TYPE type;
      union {
      ;  // case(FWP_EMPTY)
 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
WFP 驱动程序的基本流程代码如下: ```c #include <ntddk.h> #include <wdf.h> #include <fwpmk.h> #include <fwpvi.h> #define WFP_DRIVER_TAG 'wfpd' DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_DEVICE_ADD WfpEvtDeviceAdd; EVT_WDF_OBJECT_CONTEXT_CLEANUP WfpEvtDriverContextCleanup; typedef struct _WFP_DRIVER_CONTEXT { HANDLE engineHandle; UINT32 calloutId; } WFP_DRIVER_CONTEXT, *PWFP_DRIVER_CONTEXT; WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WFP_DRIVER_CONTEXT, WfpGetDriverContext) NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { NTSTATUS status; WDF_DRIVER_CONFIG config; WDF_DRIVER_CONFIG_INIT(&config, WdfEvtDriverDeviceAdd); config.DriverPoolTag = WFP_DRIVER_TAG; status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE); if (!NT_SUCCESS(status)) { KdPrint(("WdfDriverCreate failed with status 0x%x\n", status)); } return status; } NTSTATUS WfpEvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit ) { NTSTATUS status; WDFDEVICE device; PWFP_DRIVER_CONTEXT driverContext; HANDLE engineHandle; FWP_BYTE_BLOB providerBlob; FWPM_SESSION session; FWPM_CALLOUT callout; FWPM_DISPLAY_DATA displayData; UINT32 calloutId; FWPM_FILTER filter; FWPM_FILTER_CONDITION filterConditions[1]; UNICODE_STRING filterName; UNREFERENCED_PARAMETER(Driver); KdPrint(("WfpEvtDeviceAdd called\n")); status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &device); if (!NT_SUCCESS(status)) { KdPrint(("WdfDeviceCreate failed with status 0x%x\n", status)); return status; } driverContext = WfpGetDriverContext(WdfObjectGetDriver(device)); status = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, NULL, &engineHandle); if (!NT_SUCCESS(status)) { KdPrint(("FwpmEngineOpen0 failed with status 0x%x\n", status)); return status; } providerBlob.size = sizeof(GUID); providerBlob.data = (BYTE*)&GUID_WFP_DRIVER; RtlZeroMemory(&session, sizeof(FWPM_SESSION)); session.flags = FWPM_SESSION_FLAG_DYNAMIC; RtlZeroMemory(&callout, sizeof(FWPM_CALLOUT)); callout.displayData.name = L"WFP Callout"; callout.displayData.description = L"Callout for WFP driver"; callout.providerKey = providerBlob; callout.applicableLayer = FWPM_LAYER_ALE_AUTH_CONNECT_V4; callout.flags = FWPM_CALLOUT_FLAG_ALLOW_MID_STREAM_INSPECTION; callout.calloutKey = GUID_WFP_CALLOUT; status = FwpmCalloutAdd0(engineHandle, &callout, &session, &calloutId); if (!NT_SUCCESS(status)) { KdPrint(("FwpmCalloutAdd0 failed with status 0x%x\n", status)); FwpmEngineClose0(engineHandle); return status; } RtlZeroMemory(&filter, sizeof(FWPM_FILTER)); RtlInitUnicodeString(&filterName, L"WFP Filter"); filter.displayData.name = filterName; filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4; filter.action.type = FWP_ACTION_CALLOUT_TERMINATING; filter.action.calloutKey = GUID_WFP_CALLOUT; filter.filterCondition = filterConditions; filter.numFilterConditions = 1; filterConditions[0].fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS; filterConditions[0].matchType = FWP_MATCH_EQUAL; filterConditions[0].conditionValue.type = FWP_BYTE_ARRAY16_TYPE; filterConditions[0].conditionValue.byteArray16[0] = 192; filterConditions[0].conditionValue.byteArray16[1] = 168; filterConditions[0].conditionValue.byteArray16[2] = 0; filterConditions[0].conditionValue.byteArray16[3] = 1; status = FwpmFilterAdd0(engineHandle, &filter, &session, &filter.filterId); if (!NT_SUCCESS(status)) { KdPrint(("FwpmFilterAdd0 failed with status 0x%x\n", status)); FwpmCalloutDeleteByKey0(engineHandle, &GUID_WFP_CALLOUT); FwpmEngineClose0(engineHandle); return status; } driverContext->engineHandle = engineHandle; driverContext->calloutId = calloutId; return status; } VOID WfpEvtDriverContextCleanup( _In_ WDFOBJECT DriverObject ) { PWFP_DRIVER_CONTEXT driverContext; KdPrint(("WfpEvtDriverContextCleanup called\n")); driverContext = WfpGetDriverContext(DriverObject); FwpmFilterDeleteById0(driverContext->engineHandle, driverContext->calloutId); FwpmCalloutDeleteByKey0(driverContext->engineHandle, &GUID_WFP_CALLOUT); FwpmEngineClose0(driverContext->engineHandle); } ``` 以上代码是一个简单的 WFP 驱动程序,它实现了一个基于 IP 地址的过滤器,只允许指定的 IP 地址进行连接。在 `DriverEntry` 函数中创建了 WDF 驱动程序对象,并指定了设备添加回调函数 `WfpEvtDeviceAdd`。在 `WfpEvtDeviceAdd` 函数中创建了 WDF 设备对象,并初始化了 WFP 引擎、WFP 回调函数、WFP 过滤器等。在 `WfpEvtDriverContextCleanup` 函数中清理 WFP 引擎和 WFP 对象。需要注意的是,以上代码仅供参考,具体实现需要根据实际需求进行修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值