分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
在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 driverNDIS_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_STATUSFilterRegisterOptions( 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_STATUSFilterAttach( 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 structure.\n")); Status = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(pFilter, sizeof(MS_FILTER)); pFilter->FilterModuleName.Length = pFilter->FilterModuleName.MaximumLength = AttachParameters->FilterModuleGuidName->Length; pFilter->FilterModuleName.Buffer = (PWSTR)((PUCHA