在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