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

本文深入剖析Windows过滤平台(WFP)的Callout驱动代码流程,从DriverEntry开始,详细讲解创建驱动对象、设备对象、过滤引擎会话、注册Callout以及添加过滤对象的过程。通过实例解析FWPM_SUBLAYER0、FWPS_CALLOUT0、FWPM_CALLOUT0等关键结构体,并探讨如何进行包过滤和重注入。文章强调WFP涉及网络知识和NDIS理解的重要性,指出需要深入学习和实践。
摘要由CSDN通过智能技术生成

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


      今天实际看一下,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)
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值