Windows8内核模式下开发NDIS应用-NDIS Filter讲解

本文介绍了在Windows 8系统下开发驱动程序的新要求,如需要数字证书和驱动签名认证,并指出与XP系统内核的区别。特别讨论了NDIS Filter驱动的开发,它是WDK提供的一种新框架,隐藏了原有的MiniportXXX和ProtocolXXX回调函数,取而代之的是新的函数机制。代码注释帮助理解微软提供的新功能。
摘要由CSDN通过智能技术生成


 在Win8系统下开发驱动程序,需要数字证书,还需要驱动签名认证。不能像XP下面那样疯狂滴耍流氓了。


 由于Win8系统的内核做了大幅度的修改,它和XP系统的内核起了很大的变化,最显著的就是刚才说的:需要签名和证书。  还有就是:不能随意的HOOK SSDT了。




在开发NDIS驱动程序的时候,WDK开发包提供了一个新的框架,叫着NDIS Filter
NDIS Filter是一个例子工程。
假入我把WDK安装在E盘,那么这个工程代码就在:
C:\WinDDK\8600.16385.1\src\network\ndis\filter目录下。


把这个例子工程和原来的Passthru工程代码做比较,您会发现,原来需要导出来的2种类型的回调函数MiniportXXX和ProtocolXXX 在新的框架里面被全部隐藏起来了。
微软提供了新的函数。 一起来看看,微软提供了什么。
在这里,为了方便分析, 我把函数代码都做了功能注释,请大家一起看看。
代码如下:



#pragma NDIS_INIT_FUNCTION(DriverEntry)

#define LITTLE_ENDIAN   (1)
//
// Global variables
// 
NDIS_HANDLE         FilterDriverHandle; // NDIS handle for filter driver
NDIS_HANDLE         FilterDriverObject;
NDIS_HANDLE         NdisFilterDeviceHandle = NULL;
PDEVICE_OBJECT      DeviceObject = NULL;

FILTER_LOCK         FilterListLock;
LIST_ENTRY          FilterModuleList;
PWCHAR              InstanceStrings = NULL;

NDIS_FILTER_PARTIAL_CHARACTERISTICS DefaultChars = {
{ 0, 0, 0},
      0,
      FilterSendNetBufferLists,
      FilterSendNetBufferListsComplete,
      NULL,
      FilterReceiveNetBufferLists,
      FilterReturnNetBufferLists
};    

typedef struct in_addr {
  union {
    struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
    struct { USHORT s_w1,s_w2; } S_un_w;
    ULONG S_addr;
  } S_un;
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;


#pragma push(1)
typedef struct IP_HEADER
{

#if LITTLE_ENDIAN
  unsigned char  ip_hl:4;    /* 头长度 */
  unsigned char  ip_v:4;      /* 版本号 */
#else
  unsigned char   ip_v:4;
  unsigned char   ip_hl:4;     
#endif

  unsigned char  TOS;           // 服务类型

  unsigned short   TotLen;      // 封包总长度,即整个IP包的长度
  unsigned short   ID;          // 封包标识,唯一标识发送的每一个数据报
  unsigned short   FlagOff;     // 标志
  unsigned char  TTL;           // 生存时间,就是TTL
  unsigned char  Protocol;      // 协议,可能是TCP、UDP、ICMP等
  unsigned short Checksum;      // 校验和
  struct in_addr        iaSrc;  // 源IP地址
  struct in_addr        iaDst;  // 目的PI地址

}IP_HEADER, *PIP_HEADER;


typedef struct tcp_header
{
  unsigned short src_port;    //源端口号
  unsigned short dst_port;    //目的端口号
  unsigned int   seq_no;      //序列号
  unsigned int   ack_no;      //确认号
#if LITTLE_ENDIAN
  unsigned char reserved_1:4; //保留6位中的4位首部长度
  unsigned char thl:4;    //tcp头部长度
  unsigned char flag:6;  //6位标志
  unsigned char reseverd_2:2; //保留6位中的2位
#else
  unsigned char thl:4;    //tcp头部长度
  unsigned char reserved_1:4; //保留6位中的4位首部长度
  unsigned char reseverd_2:2; //保留6位中的2位
  unsigned char flag:6;  //6位标志 
#endif
  unsigned short wnd_size;   //16位窗口大小
  unsigned short chk_sum;    //16位TCP检验和
  unsigned short urgt_p;     //16为紧急指针

}TCP_HEADER,*PTCP_HEADER;


typedef struct udp_header 
{
  USHORT srcport;   // 源端口
  USHORT dstport;   // 目的端口
  USHORT total_len; // 包括UDP报头及UDP数据的长度(单位:字节)
  USHORT chksum;    // 校验和

}UDP_HEADER,*PUDP_HEADER;
#pragma push()


#define IP_OFFSET                               0x0E

//IP 协议类型
#define PROT_ICMP                               0x01 
#define PROT_TCP                                0x06 
#define PROT_UDP                                0x11 


USHORT UTIL_htons( USHORT hostshort )
{
  PUCHAR  pBuffer;
  USHORT  nResult;

  nResult = 0;
  pBuffer = (PUCHAR )&hostshort;

  nResult = ( (pBuffer[ 0 ] << 8) & 0xFF00) | (pBuffer[ 1 ] & 0x00FF);

  return( nResult );
}


/*UTIL_ntohs把网络字节顺序转换成主机字节顺序*/
USHORT UTIL_ntohs( USHORT netshort )
{
  return( UTIL_htons( netshort ) );
}



NTSTATUS 
DriverEntry(IN  PDRIVER_OBJECT  DriverObject, IN  PUNICODE_STRING   RegistryPath)
{
    NDIS_STATUS                             Status;
    NDIS_FILTER_DRIVER_CHARACTERISTICS      FChars;
    NDIS_STRING                             ServiceName;
    NDIS_STRING                             UniqueName;
    NDIS_STRING                             FriendlyName;
    BOOLEAN                                 bFalse = FALSE;

    UNREFERENCED_PARAMETER(RegistryPath);
    
    DEBUGP(DL_TRACE,("===>DriverEntry...\n"));
   
    RtlInitUnicodeString(&ServiceName, FILTER_SERVICE_NAME);
    RtlInitUnicodeString(&FriendlyName, FILTER_FRIENDLY_NAME);
    RtlInitUnicodeString(&UniqueName, FILTER_UNIQUE_NAME);
    FilterDriverObject = DriverObject;
    
    do
    {
        NdisZeroMemory(&FChars, sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS));  

/*
大多数的NDIS6.0数据结构中包含的对象头结构的成员,即NDIS_OBJECT_HEADER结构。
对象头有三个成员:类型,大小和修改。如果头信息是不正确的,那么调用NDIS6.0函数将失败。
*/
        FChars.Header.Type =  
        NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS;
        FChars.Header.Size = sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS);
        FChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_1;

        FChars.MajorNdisVersion = FILTER_MAJOR_NDIS_VERSION;
        FChars.MinorNdisVersion = FILTER_MINOR_NDIS_VERSION;
        FChars.MajorDriverVersion = 1;
        FChars.MinorDriverVersion = 0;
        FChars.Flags = 0;

        FChars.FriendlyName = FriendlyName;
        FChars.UniqueName = UniqueName;
        FChars.ServiceName = ServiceName;

            
/******************************************************
NDIS_FILTER_DRIVER_CHARACTERISTICS结构中Mandatory例程
******************************************************/
        FChars.AttachHandler = FilterAttach;
        FChars.DetachHandler = FilterDetach;
        FChars.RestartHandler = FilterRestart;
        FChars.PauseHandler = FilterPause;


/************************************************************
NDIS_FILTER_DRIVER_CHARACTERISTICS结构中Optional且不能在运行时变更的例程
*************************************************************/
        FChars.SetOptionsHandler = FilterRegisterOptions;
        FChars.SetFilterModuleOptionsHandler = FilterSetModuleOptions;
        FChars.OidRequestHandler = FilterOidRequest;
        FChars.OidRequestCompleteHandler = FilterOidRequestComplete;
        FChars.StatusHandler = FilterStatus;
       FChars.DevicePnPEventNotifyHandler = FilterDevicePnPEventNotify;
       FChars.NetPnPEventHandler = FilterNetPnPEvent;      
      FChars.CancelSendNetBufferListsHandler = FilterCancelSendNetBufferLists;



/**************************************************************
DIS_FILTER_DRIVER_CHARACTERISTICS结构中Optional且能在运行时变更的例程。
        
下面这4个例程也被定义在NDIS_FILTER_PARTIAL_CHARACTERISTICS中,这个结构指定的
例程可以在运行时的FilterSetModuleOptions例程中调用NdisSetOptionHandles来改变。
如果过滤驱动要在例程中修改自身的一个特性,那么必须提供FilterSetModuleOptions例程。
****************************************************************/
        FChars.SendNetBufferListsHandler = FilterSendNetBufferLists;  
   FChars.SendNetBufferListsCompleteHandler = FilterSendNetBufferListsComplete;
        FChars.ReturnNetBufferListsHandler = FilterReturnNetBufferLists;
        FChars.ReceiveNetBufferListsHandler = FilterReceiveNetBufferLists;

       ///
        FChars.CancelOidRequestHandler = FilterCancelOidRequest;        
      
        DriverObject->DriverUnload = FilterUnload;
    
        FilterDriverHandle = NULL;

        FILTER_INIT_LOCK(&FilterListLock);

        InitializeListHead(&FilterModuleList);
        
  // 把Filter驱动注册给NDIS
        Status = NdisFRegisterFilterDriver(DriverObject,
                                           (NDIS_HANDLE)FilterDriverObject,
                                           &FChars, 
                                           &FilterDriverHandle);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            DEBUGP(DL_WARN, ("MSFilter: Register filter driver failed.\n")); 
            break;
        }
        //
        // Initilize spin locks
        //

        Status = FilterRegisterDevice();

        if (Status != NDIS_STATUS_SUCCESS)
        {
            NdisFDeregisterFilterDriver(FilterDriverHandle);
            FILTER_FREE_LOCK(&FilterListLock);
            DEBUGP(DL_WARN, ("MSFilter: Register device for the filter driver failed.\n")); 
            break;
        }

        
    } 
    while(bFalse);
    
    
    DEBUGP(DL_TRACE, ("<===DriverEntry, Status = %8x\n", Status));
    return Status;
    
}




//过滤驱动注册可选服务
NDIS_STATUS
FilterRegisterOptions(
        IN NDIS_HANDLE  NdisFilterDriverHandle, //它指向了这个过滤驱动
        IN NDIS_HANDLE  FilterDriverContext     //它是这个驱动的上下文
        )
{
    DEBUGP(DL_TRACE, ("===>FilterRegisterOptions\n"));
    
    ASSERT(NdisFilterDriverHandle == FilterDriverHandle);
    ASSERT(FilterDriverContext == (NDIS_HANDLE)FilterDriverObject);

    if ((NdisFilterDriverHandle != (NDIS_HANDLE)FilterDriverHandle) ||
        (FilterDriverContext != (NDIS_HANDLE)FilterDriverObject))
    {
        return NDIS_STATUS_INVALID_PARAMETER;
    }

    DEBUGP(DL_TRACE, ("<===FilterRegisterOptions\n"));

    return (NDIS_STATUS_SUCCESS);
}

    

/***************************************************************  
FilterAttach函数的功能:
   Attaching状态表示:一个Filter Driver正准备附加一个Filter Module到一个驱动栈上。
   一个过滤驱动进入Attaching状态下不能进行发送请求、接收指示、状态指示、OID请求操作。

   当一个过滤驱动进入Attaching状态时,它可以:
   (1)创建一个环境上下文区域并且初始化一个缓冲区池以及其Filter Module特点的资源。
  (2)用NDIS 传来给Filter Attach的NdisFilterHandle作为输入来调用NdisFSetAttributes例程。


   Attach is complete
   当Filter Module在Attaching状态下并且Filter Driver初始化了所有的Filter Module所需要的
   所有资源时,Filter Module进入Paused状态。


   参数说明:
    NdisFilterHandle     它用于所有过滤驱动中对Ndisxxx类例程的调用时引用指示这个过滤模块。
    FilterDriverContext  它由NdisFRegisterFilterDriver的FilterDriverContext来指定。
    AttachParameters     它是过滤模块的初始化参数结构体。
 **************************************************************/
NDIS_STATUS
FilterAttach(
    IN  NDIS_HANDLE                     NdisFilterHandle,
    IN  NDIS_HANDLE                     FilterDriverContext,
    IN  PNDIS_FILTER_ATTACH_PARAMETERS  AttachParameters
    )

{
    PMS_FILTER              pFilter = NULL;
    NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;
    NDIS_FILTER_ATTRIBUTES  FilterAttributes;
    ULONG                   Size;
    BOOLEAN               bFalse = FALSE;
    
    DEBUGP(DL_TRACE, ("===>FilterAttach: NdisFilterHandle %p\n", NdisFilterHandle));

    do
    {
        ASSERT(FilterDriverContext == (NDIS_HANDLE)FilterDriverObject);
        if (FilterDriverContext != (NDIS_HANDLE)FilterDriverObject)
        {
            Status = NDIS_STATUS_INVALID_PARAMETER;
            break;
        }
        
        if ((AttachParameters->MiniportMediaType != NdisMedium802_3)
                && (AttachParameters->MiniportMediaType != NdisMediumWan))
        {
           DEBUGP(DL_ERROR, ("MSFilter: Doesn't support media type other than NdisMedium802_3.\n")); 
        
           Status = NDIS_STATUS_INVALID_PARAMETER;
           break;
        }
        
        Size = sizeof(MS_FILTER) + 
               AttachParameters->FilterModuleGuidName->Length + 
               AttachParameters->BaseMiniportInstanceName->Length + 
               AttachParameters->BaseMiniportName->Length;
        
        pFilter = (PMS_FILTER)FILTER_ALLOC_MEM(NdisFilterHandle, Size);
        if (pFilter == NULL)
        {
            DEBUGP(DL_WARN, ("MSFilter: Failed to allocate context struct
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尹成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值