整个电脑系统移植_dism移植电脑系统
1.电脑驱动可不可以备份
首先简单介绍硬件结构,硬件的实现方案如下图1-1。网卡工作在半双工状态。USB接口依USB 2.0,用ICSI的IC9211芯片。物理层芯片使用Intersil公司芯片。MAC层控制引擎需要使用微码编程或嵌入CPU Core。
作为一个新的项目,首先要列出开发的工作量,制定出合理的开发,将整个项目细分为几个小的项目,一步一步推进。下面介绍一下工作内容。
这些内容中,首先要解决的是USB通信问题,由于硬件接口为USB总线接口,所以必须要打通USB通道。微软windows系统中有专门的编程接口,我们只要将需要的功能封装成URB(USB Request Block)请求包,通过调用USBD class driver接口,将URB包发到下一层。最总由总线驱动与设备交互。
其次是开发NDIS miniport驱动框架。NDIS是微软的网络设备的开发库,提供了许多和网络设备相关的接口函数供调用。根据设计,本驱动为一个miniport类型的驱动,所以需要开发标准的miniport接口供系统调用。和传统的驱动一样,也是封装一系列的回调函数给系统,这些调用接口形式微软的NDIS规范已经定义好了。
接下来就是对这些接口的完善。加入802.11协议内容,作为驱动的实体。由于intersil的芯片没有集成802.11协议功能,所以我们需要在软件中开发协议中的MAC层规定的内容。这部分也是我们驱动的主要内容。
802.11协议有三个主要状态。根据协议规范只有在关联的状态下,才可以进行数据通信。认证,加密是安全相关的,理论上与协议没有必然关系,802.11无线协议为了安全,将加密和认证也作为协议的一部分,从而使得其具有等同有线网络的安全级别。同时,802.11协议定义很多命令,如Probe request/response,Beacon,Authentication,Deauthentication,Association,Deassociation等,程序的主体是一个状态机,只要发送相应的命令就可以进行状态切换,完成相应的功能。
协议中涉及到AP列表的搜索,认证过程,关联过程,信道的切换等需要分别实现,分别是一个更细节的状态机。关于802.11协议详细内容请参考相关的文档。这里不多说了。下图1-2是802.11协议的状态图。
按照功能划分:可分为管理、控制和数据3种不同类型帧。Class 1,Class 2&3 Frame的定义请参考802.11-1999。
1, Usb总线介绍
USB是Intel公司开发的通用串行总线架构,以简单的设计,易用性,热插拔特性受到了广泛的欢迎,很多设备都开始支持USB规范。
一个USB系统主要被定义为三个部分:USB的互连;USB的设备;USB的主机。
在任何USB系统中,只有一个主机。USB和主机系统的接口称作主机控制器,主机控制器可由硬件、固件和软件综合实现。根集线器是由主机系统整合的,用以提供更多的连接点。
图2-1 总线的拓扑结构
图2-1显示了USB总线的拓扑结构。
标准USB规范有四根线,分别是电压正负极,两根数据线。外观为扁平的方形接口。USB传送信号和电源是通过一种四线的电缆,图2-2中的两根线是用于发送信号。电缆中包括VBUS?、GND二条线,向设备提供电源 。VBUS?使用+5V电源。
USB总线属一种轮讯方式的总线,主机控制端口初始化所有的数据传输。在USB设备安装后,主机通过设备控制通道激活该端口并以预设的地址值给USB设备。主机对每个设备指定唯一的USB地址。
USB定义了一些请求命令,所有的USB设备在设备的缺省控制通道(Default Control Pipe)处对主机的请求发出响应。这些请求是通过使用控制传输来达到的,请求及请求的参数通过Setup包发向设备,由主机负责设置Setup包内的每个域的值。每个Setup包有8个字节。见表2-1。
bmRequestType域
这个域表明此请求的特性。特别地,这个域表明了第二阶段控制传输方向。如果wLength域被设作0的话,表明没有数据传送阶段,那Direction位就会被忽略。
USB说明定义了一系列所有设备必须支持的标准请求。这些请求被例举在表8-3中。另外,一个设备类可定义更多的请求。设备厂商也可定义设备支持的请求。
请求可被导引到设备,设备接口,或某一个设备端结点(endpoint)上。这个请求域也指定了接收者。当指定的是接口或端结点(endpoint)时,wIndex域指出那个接口或端节点。
bRequest域
这个域标识特别的请求。bmRequestType域的Type啦可修改此域的含义。本说明仅定义Type 字位为0即标准设备请求时bRequest域值的含义。
wValue域
此域用来传送当前请求的参数,随请求不同而变。
wIndex域
wIndex域用来表明是哪一个接口或端结点,图2-3表明wIndex的格式(当标识端结点时)。Direction位在设为0时表示出结点,设为1时表示是入结点,Endpoint Number是结点号。图2-4表明wIndex用于标识接口时的格式。
wLength域
这个域表明第二阶段的数据传输长度。传输方向由bmRequstType域的Direction位指出。wLength域为0则表明无数据传输。在输入请求下,设备返回的数据长度不应多于wLength,但可以少于。在输出请求下,wLength指出主机发出的确切数据量。如果主机发送多于wLength的数据,设备做出的响应是无定义的。
表2-2描述了所有USB设备都定义的标准设备请求将它们列出。不管设备是否被分配了非缺省地址或设备当前是被配置了的,它们都应当对标准请求产生响应。具体请参考USB规范。
讲到USB总线,就不得不讲USB总线的传输方式。
一个USB通道是设备上的一个端点和主机上软件之间的联系。USB设备的设计者可以决定设备上每个端点的能力。一旦为这个端点建立了一个通道,这个通道的绝大多数传送特征也就固定下来了,一直到这个通道被取消为止。
USB定义了4种传送类型:
·控制传送:可靠的、非周期性的、由主机软件发起的请求或者回应的传送,通常用于命令事务和状态事务。
·同步传送:在主机与设备之间的周期性的、连续的通信,一般用于传送与时间相关的信息。这种类型保留了将时间概念包含于数据中的能力。但这并不意味着,传送这样数据的时间总是很重要的,即传送并不一定很紧急。
·中断传送:小规模数据的、低速的、固定延迟的传送。
·批传送:非周期性的,大包的可靠的传送。典型地用于传送那些可以利用任何带宽的数据,而且这些数据当没有可用带宽时,可以容忍等待。
每一个端点Endpoint都有自己的传输方式,通过配置描述符,主机就可以知道每一个端点的传输方式,从而以该方式进行通信。
1, WDM框架介绍
WDM(windows driver model)是微软对于驱动开发定义的一整套规范。与原来的Vxd驱动相比,WDM更加封装完好,并且可以对Windows各版本的做到二进制兼容,在一个系统下完成了,可以很轻松的移植到其他windows系统下。本人有幸将windows xp下开发的驱动,移植到了windows 2000,window me和windows 98下。这是我很好的经验。
根据Walter oney的观点,设备驱动程序是一个包含了许多操作系统可调用例程的容器,这些例程可以使硬件设备执行相应的动作。
WDM模型使用了层次结构,如图3-1所示,左边是一个设备对象堆栈。设备对象是系统为帮助软件管理硬件而创建的数据结构。一个物理硬件可以有多个这样的数据结构。出于堆栈最底层的设备对象称为物理设备对象(physical device object),简称PDO。在设备对象堆栈的中间摸出有一个对象称为功能设备对象(function device object),简称FDO。在FDO的上面和下面还会有过滤器设备对象(filter device object),简称FiDO。
总线是个广义的定义,包括PCI,SCSI卡,并行口,串行口,USB集线器(hub),等等。实际上它可以是任何能插入多个设备的硬件设备。总线驱动程序的一个任务就是枚举总线上的设备,并为每一个设备创建一个PDO。
我们的miniport其实也是一个功能驱动程序。
1, 开发环境介绍
下面介绍一下开发环境,windows驱动开发使用VC工具,也可以使用脚本直接编译,关键是设置好环境变量,DDK库的路径设置好。编译出的驱动有checked和free两种,checked对应的debug版本,free对应release版本。
调试工具使用Softice,我使用的是2.7版本,这个工具非常强,可以看变量,内存,也可以看堆栈调用,很多棘手的问题手到擒来。
或者一般也可以通过debugview工具调试,需要的程序的关键路径上打印变量即可。当程序比较稳定了,就可以使用debugview观察逻辑上的问题,这样就可以比较快的定位,然后再使用softice进行细节调试。
2, WDM模型和USB底层的实现
微软windows实现了usb总线的驱动,和一部分USB类驱动,通过URB封装好以后,把URB包发送给下一层的驱动,最终由总线驱动与设备通信。
WDM模型提供了USB的编程架构。这个架构包含了多个概念,包括把设备夫做到计算机上的层次方法,电源管理的通用方案,硬件的多层次描述符的自识别标准。USB标准把定时帧(frame)分解成数据包(packet),从而实现设备和主机之间的数据传输。最后,在主机和设备上的端点之间,USB支持四种数据传输模式。一种模式称为等时传输(isochronous),它可以每个一毫秒传输固定量无错误校验的数据。其他模式为:控制传输,批量传输和中段传输,它们仅能传输少量(64字节或更少)带有错误校验的数据。
USB驱动高度依赖于总线驱动程序(USBD.sys),而不直接使用HAL函数与硬件通信。它仅靠创建URB(USB请求块)并把URB提交到总线驱动程序就可以完成硬件操作。USBD.sys可以理解为接受URB的实体,向USBD的调用被转化为带有主功能代码为IRP_MJ_INTERNAL_DEVICE_CONTROL的IRP。然后USBD再调度总线时间,发出URB中指定的操作。
一般我们可以按照如下的方法建立并提交一个URB给USBD驱动。
如当相应IRP_START_DEVICE消息时,首先需要读取设备描述符,然后
URB urb;
USB_DEVICE_DESCRIPTOR deviceDesc;
UsbBuildGetDescriptorRequest
(
&urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
&deviceDesc,
NULL,
sizeof(USB_DEVICE_DESCRIPTOR),
NULL
);
UsbBuildGetDescriptorRequest其实是一个宏,在USBDLIB.H中声明,用于生成读描述符请求子结构各个域。
创建完URB后,需要发一个内部IO控制(IOCTL)请求到USBD驱动程序,USBD驱动程序位于驱动程序层次结构的低端,一般需要等待设备回应。
NTSTATUS MPUSB_CallUSBD
(
IN PDEVICE_OBJECT DeviceObject,
IN PURB Urb
)
{
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PDEVICE_EXTENSION pDevExt;
pDevExt = DeviceObject->DeviceExtension;
// issue a synchronous request to read the UTB
KeInitializeEvent(&event, NotificationEvent, FALSE);
PIRP irp = IoBuildDeviceIoControlRequest
(
IOCTL_INTERNAL_USB_SUBMIT_URB,
pDevExt -> StackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, /* INTERNAL */
&event,
&ioStatus
);
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation( irp );
nextStack->Parameters.Others.Argument1 = Urb;
NTSTATUS ntStatus = IoCallDriver( pDevExt -> StackDeviceObject, irp );
if (ntStatus == STATUS_PENDING)
{
ntStatus = KeWaitForSingleObject
(
&event,
Executive,
KernelMode,
FALSE,
NULL
);
}
// USBD maps the error code for us
ntStatus = ioStatus.Status;
return ntStatus;
}
这样我们就可以通过USB总线与设备通信了。
当然这个过程比较复杂,需要读取并配置设备描述符,配置描述符,接口描述符和端点描述符,这些描述符在USB协议规范中有讲述,在相应的USB类规范中也有详细的描述。
一般配置描述符格式如下,
这个示例表明这个设备有两个接口,对一个接口有两个端点,第二个接口也有两个端点。每一个接口可以是一个独立的功能,这个时候设备就是复符合设备,在配置描述符中就需要声明这是个复合设备。而每一个接口也需要分别声明他的类型。
比如本人曾经有一个项目中有三个接口,分别是modem,普通串口,USB mass storage。这三个接口都需要分别声明他的类型,这些类型在USB的类规范中有详细的定义。
一般由于配置描述符的长度是不定的,所以我们需要先获取这个长字符串的前面9个字节,即配置描述符(见规范)。格式如下,
typedef struct
{
byte length; // bLength: size in bytes
byte descriptor_type; // bDescriptorType
word total_length; // wTotalLength: in bytes
byte num_interfaces; // bNumInterfaces
byte configuration; // bConfigurationValue
byte config_index; // iConfiguration
byte attributes; // bmAttributes
byte max_power; // MaxPower: in 2mA units
} usbdc_configuration_descriptor_type;
这样,在这个字符串的第三、四字节会指明整个字符串的长度,然后再读取一次该长度,就可以完整地得到整个配置字符串。
1, NDIS模型和带有WDM底层的miniport驱动
NDIS(Network Device Interface Specification)是微软的网络设备的开发库。但是由于本设备是一个USB设备,需要通过WDM模型访问。故而我们在设计时,考虑为一个NDIS miniport上层接口,带有一个WDM访问接口的驱动,很,微软支持这样的设计。
根据设计,本驱动为一个miniport类型的驱动,所以需要开发标准的miniport接口供系统调用。和传统的驱动一样,也是封装状一系列的调用函数给系统,这些调用接口形式微软的NDIS规范已经定义好了。入口函数为DriverEntry,
入口函数的功能是系统调用驱动的第一个函数,它负责初始化驱动,注册回调函数(call back)。这些函数包括如下,通过一个结构完成。
首先必须调用如下的函数,使得miniport驱动和NDIS相关联,通过调用这个函数存储miniport驱动的信息。返回的句柄NdisWrerHandle,用于后面的回调函数注册。NDIS也通过NdisWrerHandle来区分不同的驱动。
NdisMInitializeWrer(
&NdisWrerHandle,
DriverObject,
RegistryPath,
NULL
);
注册回调函数方法如下,注册结构类型为NDIS_MINIPORT_CHARACTERISTICS。
// and the entry points for driver-supplied MiniportXxx
NdisZeroMemory(&MPChar, sizeof(MPChar));
//
// The NDIS version number, in addition to being included in
// NDIS_MINIPORT_CHARACTERISTICS, must also be specified when the
// miniport driver source code is compiled.
//
MPChar.MajorNdisVersion = MP_NDIS_MAJOR_VERSION;
MPChar.MinorNdisVersion = MP_NDIS_MINOR_VERSION;
MPChar.InitializeHandler = MPInitialize;
MPChar.HaltHandler = MPHalt;
MPChar.SetInformationHandler = MPSetInformation;
MPChar.QueryInformationHandler = MPQueryInformation;
MPChar.SendPacketsHandler = MiniportTxPackets;
MPChar.ReturnPacketHandler = MiniportReturnPacket;
MPChar.ResetHandler = MPReset;
MPChar.CheckForHangHandler = MPCheckForHang; //optional
#ifdef NDIS51_MINIPORT
// MPChar.CancelSendPacketsHandler = MPCancelSendPackets;
MPChar.PnPEventNotifyHandler = MPPnPEventNotify;
MPChar.AdapterShutdownHandler = MPShutdown;
#endif
NdisMRegisterMiniport(
NdisWrerHandle,
&MPChar,
sizeof(NDIS_MINIPORT_CHARACTERISTICS));
当注册好了后,系统会检测NDIS版本号,然后调用初始化接口,MPChar.InitializeHandler = MPInitialize; 初始化驱动的其他内容,如变量的初始化,注册表的读写,/互斥信号量的初始化等。
如果初始化完成,那么驱动就可以正常工作了。一般通过如下接口:
MPChar.SetInformationHandler = MPSetInformation;
MPChar.QueryInformationHandler = MPQueryInformation;
进行属性的获取和设置。通过如下接口:
MPChar.SendPacketsHandler = MiniportTxPackets;
MPChar.ReturnPacketHandler = MiniportReturnPacket;
进行数据的收发。
现在可以看到,NDIS和传统的驱动没有什么区别,但是作为网络的接口,它更加稳定,更加标准化,是开发更加简单。
1, 802.11协议的实现
1996年,ETSI提出了HiperLAN的无线局域网协议,1998年日本出现HomeRFSWAP。最近几年流行的Bluetooth(严格的说, Bluetooth不属于无线局域网,而是无线PAN(Personal Area Net-work) ,应该算作无线局域网的一个子集。19年通过的IEEE 802.11是第一种无线以太网标准,已经成为无线局域网的代名词。1999年的修订版是当前的标准主要参考。
802.11包括MAC(Media Access Control)层和物理层
3种不同物理层:–DSSS or Direct Sequence Spread Spectrum
–FHSS or Frequency Hopping Spread Spetrum
–红线(IR or Infrared)
所以MAC层可以同时支持3种不同的物理层基本服务集(basic service set or BSS)
无线局域网的最小单元,由2个或多个移动台Wireless station or STA)构成 一个基本服务集(BSS)内的移动台(STA)间可以直接通信; 一个基本服务集(BSS)实际上是一个自组织网络(ad hoc),在802.11中称成IBSS(independent BSS) STA到BSS的连接是动态的,自发的(non-preplanned)扩展服务集(Extended service set or ESS)
AP+BSS可以组成任意大的无线局域网,称作扩展服务集网络,它的所有组成部分合称扩展服务集(ESS)
Infrastructure BSS:非IBSS都称为Infrastructure BSS
802.11定义了9种服务类型:移动台服务(Station Service or SS)有四种:
1.鉴别(Authentication)=who are you?
2.取消鉴别(Deauthentication)=I am about to lee, Stop communicating with me please
3.加密(privacy):数据怎能让别人偷听(Eesdrop)
4.MSDU发送(MSDU delivery)
(MSDU是什么?MAC service data unit; SDU是来自(OSI)上一层的协议数据单元PDU,它定义了对下层协议的服务请求;而PDU协议数据单元(Protocol Data Unit)指对等层水平方向传送的数据单元)
分布系统服务(Station Service or DSS)
要提供全部9种服务:
前4种:鉴别、取消鉴别、加密、MSDU发送 后5种:5.关联(Association):它是一个DSS(Distribution system service),STA如果希望将消息传输给其他BSS的STA,首先要与所在BSS的AP实现关联。
6.取消关联(Disassocation):关联的反过程
7.分配(Distribution):将BSS1的STA1的数据(也可以说是消息)经过DS传送到BSS2的STA2,即跨DS的数据传送功能
8.集成(Integration):完成与有线网之间互通
9.再关联(Reassociation):当STA从BSS1移动到BSS2时,要与BSS的AP实现再关联,以支持跨BSS消息传送
按照功能划分:可分为管理、控制和数据3种不同类型帧
所有MAC帧由一下3部分构成:
帧头(MAC header) 可变长帧体(Frame body):与帧类型有关 校验序列(frame check sequence or FCS):CRC-32SSID说白了就是IBSS或ESS的一个32字节的一个标识,一个字节对应一个字符,所有可以用32个以下的字符来表示某个公司或其他组织的无线网络,类似于有线网络的工作组名字,比如我们组就叫Eda(其它字节为0)
鉴别服务分为两种:
开放系统(Open System)和共享密钥(Shared Key)
开放系统:如果dot11AuthenticationType被置位为1,则为“开放系统鉴别”,要建立鉴别,共需要2帧就可完成任务:鉴别请求,鉴别应答
共享密钥:共享密钥鉴别需要4帧。首先requester发出请求帧,然后responder发送质问(challenge)文本,该文本是WEP PRNG生产的128字节随机数,然后requester对收到的质问(challenge)文本进行WEP算法加密,responder将返回的文本解密得到相应质问文本,如果双方(responder和requester)所用密钥相同,则responder将返回的文本解密得到原始质问文本,鉴别成功
WEP加密已经被认为是不安全的算法。所以WiFi有提出了更高安全级别的算法,如WAP等。
MAC层功能:
1.点协调功能(PCF)
2.分布协调功能(DCF)
3.分段(Fragmentation)
4.去分段(defragmentation)
5.MSDU重新排序和丢弃
长度大于aFramentationThreshold的MSDU和
MMPDU(MAC管理协议数据单元)都要分段,
以提高传输成功率分段后的数据长度为某一固
定偶数(不包括最后一段)。
分段后的数据可以进行突发传送。接收端
依靠Sequence和MoreFragments 域对数据进行去分段
分布控制方式(DCF):多个STA争用无线信道,即所谓CSMA/CA方式(不同于CSMA/CD) 点控制方式(PCF): AP作为控制中心,控制所有STA对信道的使用。AP就是所谓Point coordinator, PCF是基于DCF的。主要用于实时业务,在802.11中是可选的。随机避退时间
BackoffTime = Random()×aSlotTime
Random()--返回在[0, CW]之间均匀分布的整数
aSlotTime--物理层特性决定的CW的最小单位或称CW的切片
CW--contention window。在[aCMin,aCMax] 之间取值。第一次发送时值为aCMin,以
后每重传一次倍增,达到aCMax后维持aCMax。成功发送后复位到aCMin。
检测到信道忙,则延迟(defer)
检测到空闲且经过一个IFS,再进行
避退(Backoff)。避退时间过后如果
信道空闲,就开始发送帧
信标帧(Beacons)
电脑驱动可不可以备份
用户态(user-mode)和内核态(kernel-mode)。
1)用户态(user-mode)。
在用户态下进行网络数据包的拦截有三种方法:WinsockLayeredServiceProvider(LSP)、Windows2000包过滤接口、替换系统自带的WINSOCK动态连接库。在用户态下
进行数据包拦截最致命的缺点就是只能在Winsock层次上进行,而对于网络协议栈中底层协议的数据包无法进行处理。因此,这些方法并不适合个人防火墙。
2)内核态(kernel-mode)。
a)TDI过滤驱动程序(TDIFilterDriver)。当应用程序要发送或接收网络数据包的时候,都是通过与协议驱动所提供的接口来进行的。协议驱动提供了一套系统预定义的标准接口来和应用程序之间进行交互。因此,只需要开发一个过滤驱动来截获这些交互的接口,就可以实现网络数据包的拦截。在Windows2000/NT下,ip,tcp,udp是在一个驱动程序里实现的,叫做tcp.sys,这个驱动程序创建了5个设备:DeviceRawIp,DeviceUdp,DeviceTcp,DeviceIp,DeviceMULTICAST。应用程序所有的网络数据操作都是通过这些设备进行的。因此,我们只需要开发一个过滤驱动来截获这些交互的接口,就可以实现网络数据包的拦截。另外,TDI层的网络数据拦截还可以得到操作网络数据包的进程详细信息,这也是个人防火墙的一个重要功能。但是,TDI传输驱动程序有一个缺陷,TDIFilterdriver属于Upperdriver,位于TcpIP.sys之上,这就意味着由TcpIP.sys接收并处理的数据包不会传送到上层,从而无法过滤某些接收的数据包,例如ICMP包。ICMP的应答包直接由TcpIP.sys生成并回应,而上面的过滤驱动程序全然不知。另外,该方法需要在系统核心层编写驱动程序,需要编写人员对Windows操作核心层的工作机制非常熟悉,同时,驱动程序对代码质量要求非常高,稍有不慎就会使系统崩溃,
b)Win2kFilter-HookDriver。这是从Windows2000开始系统所提供的一种驱动程序,该驱动程序主要是利用Ipfiltdrv.sys所提供的功能来拦截网络数据包。Filter-HookDriver的结构非常简单,易于实现。但是正因为其结构过于简单,并且依赖于Ipfiltdrv.sys,Microsoft并不推荐使用Filter-HookDriver。
c)NDISHookDriver。该方法在Windows2000/xp下是非公开的,因此这种方法对平台的依赖性比较大,需要在程序中判断不同的操作系统版本而使用不同的方法。
d)NDIS中间层驱动程序(NDISIntermediateDriver)。NDIS(NetworkDriverInterfaceSpecification)是Microsoft和3Com公司开发的网络驱动程序接口规范的简称,它支持如下三种类型的网络驱动程序:微端口驱动程序、中间层驱动程序(IntermediateDriver)和协议驱动程序。其中中间层驱动介于协议层驱动和小端口驱动之间,其功能非常强大,可以提供多种服务,能够截获所有的网络数据包(以太帧),过滤微端口驱动程序,实现特定的协议或其他诸如数据包加密、认证等功能。综上所述,在NDIS中间层进行网络数据包截获的方法结构规范,功能强大,该技术极其适合个人防火墙所用。
中间层驱动程序(NDIS)的内部结构
NDIS支持3种驱动:微端口驱动,中间层驱动和协议驱动。
1) 微端口驱动。就是网卡驱动,它负责管理网卡,包括通
过网卡发送和接受数据,它也为上层驱动提供接口。
2) 中间层驱动。它通常位于微端口驱动和传输协议驱动之间,是基于链路层和网络层之间的驱动,由于中间层驱动在驱动层次中的中间层位置,它必须与其上层的协议和下层的微端口驱动通信,并且导出两种协议的函数。虽然中间层驱动导出MINIPORTXX函数,但它并不真正的管理物理网卡,而是导出一个或者多个虚拟适配器,上层协议可以绑定到上面。对于协议驱动来说,中间层导出的虚拟适配器看起来像一个物理网卡,当它向这个虚拟适配器发送封包或者请求时,中间层驱动将这些封包和请求传播到下层微端口驱动;当下层微端口驱动向上指示接收封包或者状态时,中间层驱动向上到绑定虚拟适配器上的协议驱动。中间层驱动的主要作用就是过滤封包,其优点是能够截获所有的网络数据包。
3) 协议驱动,即网络协议。它位于NDIS体系的最高层,经常用作实现传输协议堆栈的传输驱动中的最底层驱动。传输协议驱动申请封包,从发送应用程序将数据复制到封包中,通过调用NDIS函数将这些封包发送到下层驱动。协议驱动也是提供了一个协议接口来接收来自下层驱动的封包。传输协议驱动将收到的封包传递给相应的客户应用程序。在下层,协议驱动与中间层微端口驱动交互。协议驱动调用NDISXX函数发送封包,读取和设置下层驱动维护的信息,使用操作系统服务。协议驱动也要导出一系列的入口点,NDIS调用它来指示封包的接受,指示下层驱动的状态,或者是和其他协议驱动的通信。
中间层内部的工作流程
1) 中间层对数据包的管理
中间层驱动程序从高层驱动程序接收数据包描述符,并在网络上发送,该包描述符与一个或多个链式数据缓冲区相关联。中间层驱动程序能够对数据进行重新打包,并使用新的数据包描述符进行数据传输,也可以直接将数据包传递给低层驱动程序,如果驱动程序下边界面向无连接,可调用NdisSend或NdisSendPackets函数完成该功能,如果驱动程序下边界是面向连接的,可调用NdisCoSendPackets函数完成此项功能。中间层驱动程序也可以进行一些操作改变链式缓冲区的内容,或者调整内入数据包相对于其他发送任务的发送次序或发送定时。但是,即使中间层驱动程序只是向下层传递上层引入的数据报,例如,仅仅只是对数据包进行计数,也必须分配新的数据包描述符,并且要管理部分或者全部新的包结构。
每一个中间层驱动程序都必须分配自己的包描述符来代替高层的数据包描述符。如果中间层驱动程序要把数据包从一种格式转化为另一种格式,也必须分配缓冲区描述符来映射用于复制转配数据的缓冲区,该缓冲区由中间层驱动程序进行分配。如果有与复制的包描述符相关的OOB数据,那么可以将这些数据复制到与包描述符(中间层驱动程序分配的)相关的新OOB数据块,其过程是,首先,用NDIS_OOB_DATA_FROM_PACKET宏获取OOB数据区的指针,然后,调用disMoveMemory将其内容移入与新包描述符相关的OOB数据区。该驱动程序也能够用NDIS_GET_PACKET_XXX或NDIS_SET_PACKET_XXX宏从与老的包描述符相关的OOB数据区中,读取相关的内容,并写入与新包描述符相关的OOB数据区。
包描述符通过调用以下NDIS函数进行分配
a)调用NdisAllocatePacketPool或者NdisAllocatePacketPoolEx,为固定尺寸包描述符(由呼叫器指定数量)分配并初始化一组非可分页池。
b)调用NdisAllocatePacket函数,从NdisAllocatePacketPool(Ex)已经分配的池中分配包描述符。根据中间层驱动程序目的的不同,驱动程序能够对引入包描述符连接的缓冲区进行重新打包。例如,中间层驱动程序可以在接下来的情况下分配包缓冲池、对引入包数据重新打包.如果中间层驱动程序从高层协议驱动程序接收到的数据缓冲区,比低层介质能够发送的单个缓冲区更大,那么中间层驱动程序必须将引入的数据缓冲分割成更小的、满足低层发送要求的数据缓冲。中间层驱动程序在将发送任务转交低层驱动程序之前,可以通过压缩或加密数据方式来改变内入数据包的长度。调用以下NDIS函数分配上面所要求的缓冲区:
NdisAllocateBufferPool获取用于分配缓冲区描述符的句柄;
NdisAllocateMemory或NdisAllocateMemoryWithTag分配缓冲区;
c)调用NdisAllocateBuffer分配和设置缓冲区描述符,映射由NdisAllocateMemory(WithTag)分配的缓冲区,并链接到NdisAllocatePacket分配的包描述符上。驱动程序可以通过调用NdisChainBufferAtBack或NdisChainBufferAtFront函数,将缓冲区描述符和包描述符进行链接。调用NdisAllocateMemory(WithTag)返回的虚拟地址和缓冲区长度,将被传递给NdisAllocateBuffer函数来初始化其所映射的缓冲区描述符。符合典型要求的包描述符能够在驱动程序初始化时根据要求进行分配,也可以通过ProtocolBindAdapter函数调用来实现。如果必要或者出于性能方面的考虑,中间层驱动程序开发者可以在初始化阶段,分配一定数量的包描述符和由缓冲区描述符映射的缓冲区,这样,就为ProtocolReceive复制内入数据(将向高层驱动程序指示)预先分配了,也为MiniportSend或MiniportSendPackets向相邻低层驱动程序传递引入的发送数据包,准备了可用的描述符和缓冲区。如果在中间层驱动程序复制接收/发送数据到一个或多个缓冲区时,最末的一个缓冲的实际数据长度比缓冲区的长度小,那么,中间层驱动程序将调用NdisAdjustBufferLength把该缓冲区描述符调节到数据的实际长度。当该包返回到中间层驱动程序时,应再次调用该函数将其长度调节到完整缓冲区的实际尺寸。
2)下边界面向无连接的中间层驱动程序的工作流程
通过ProtocolReceivePacket函数,从低层NIC驱动程序以完整数据包形式接收内入数据,该数据包由NDIS_PACKET类型的包描述符指定,也能够通过将内入数据指示给ProtocolReceive函数,并将数据复制到中间层驱动程序提供的数据包中。下边界面向连接的中间层驱动程序总是用ProtocolCoReceivePacket函数,从低层NIC驱动程序接收数据作为一个完整的数据包。
在如下情况下,中间层驱动程序能够保持对接收数据包的所有权:当下边界面向无连接的中间层驱动程序向ProtocolReceivePacket函数指示完整数据包时,当下边界面向连接的中间层驱动程序向ProtocolCoReceivePacket函数指示数据包时,其中DIS_PACKET_OOB_DATA的Status成员设置为除NDIS_STATUS_RESOURCES以外的任何值。在这些情况下,中间层驱动程序能够保持对该包描述符和其所描述的的所有权,直到所接收数据处理完毕,并调用NdisReturnPackets函数将这些返还给低层驱动程序为止。如果ProtocolReceivePacket向高层驱动程序传递其所接收的,那么至少应该用中间层驱动程序已经分配的包描述符替代引入包描述符。根据中间层驱动程序目的的不同,当其从低层驱动程序接收完整数据包时,将有几种不同的包管理策略。例如,以下是几种可能的包管理策略:复制缓冲区内容到中间层驱动程序分配的缓冲区中,该缓冲区被映射并链接到一个新的包描述符,向低层驱动程序返回该输入包描述符,然后可以向高层驱动程序指示新的数据包;创建新的包描述符,将缓冲区(与被指示包描述符相关联)链接到新的包描述符,然后将新的包描述符指示给高层驱动程序。当高层驱动程序返回包描述符时,中间层驱动程序必须拆除缓冲区与包描述符间的链接,并将这些缓冲区链接到最初从低层驱动程序接收到的包描述符,最后向低层驱动程序返还最初的包描述符及其所描述的。即使下边界面向无连接的中间层驱动程序支持ProtocolReceivePacket函数,它也提供ProtocolReceive函数。当低层驱动程序不释放包描述符所指示的所有权时,NDIS将调用ProtocolReceive函数,当这类情况出现时,中间层驱动程序必须复制所接收的数据到它自己的缓冲区中。对于下边界面向连接的中间层驱动程序,当低层驱动程序不释放包描述符所指示的所有权时,则将数据包的NDIS_PACKET_OOB_DATA的Status成员设为NDIS_STATUS_RESOURCES,然后驱动程序的ProtocolCoReceivePacket函数必须将接收到数据复制到自己的缓冲区中
5) 中间层驱动过滤数据包的原理
NDIS中间层驱动程序在NDIS中起着转发上层驱动程序送来的数据包,并将其向下层驱动程序发送的接口功能。当中间层驱动程序从下层驱动程序接收到数据包时,它要么调用NdisMXxxIndicateReceive函数,要么调用NdisMindicateReceivePacket函数向上层指示该数据包中间层驱动程序通过调用NDIS打开和建立一个对低层NIC驱动程序或者NDIS中间层驱动程序的绑定。中间层驱动程序提供MiniportSetInformation和MiniportQueryInformation函数来处理高层驱动程序的设置和查询请求,某些情况下,可能还要将这些请求向低层NDIS驱动程序进行传递,如果其下边界是面向无连接的可通过调用NidsRequest实现这一功能,如果其下边界是面向连接的则通过调用NidsCoRequest实现该功能。中间层驱动程序通过调用NDIS提供的函数向网络低层NDIS驱动程序发送数据包。例如,下边界面向无连接的中间层驱动程序必须调用NdisSend或NdisSendPackets来发送数据包或者包数组,而在下边界面向连接的情况下就必须调用NdisCoSendPackets来发送包数组数据包。如果中间层驱动程序是基于非NDISNIC驱动程序的,那么在调用中间层驱动程序的MiniportSend或Miniport(Co)SendPackets函数之后,发送接口对NDIS将是不透明的。NDIS提供了一组隐藏低层操作系统细节的NdisXxx函数和宏。例如,中间层驱动程序可以调用NdisMInitializeTimer来创建同步时钟,可以调用NdisInitializeListHead创建链表。中间层驱动程序使用符合NDIS标准的函数,来提高其在支持Win32接口的微软操作系统上的可移植性。
在防火墙的设计中,最核心的部分应该是数据包的过滤。
其他的功能都是建立在数据包过滤的基础之上,如:入侵检测功能和邮件检测功能都是建立在数据包过滤的基础之上。数据包过滤中主要是IP包头的分析,例如:在以太网中,得到的数据报大致是如下结构,以太帧头14个字节,放在PUCHAR结构数组的第0个元素到第13个元素中,其中前六个字节是目的MAC地址,然后六个字节源MAC地址,然后两个字节是协议类型,通常的协议类型有0x080x00->IP,0x080x06->ARP,0x080x35->RARP,所以,可以通过数组的第12个元素和第13个元素来判断协议类型。过滤规则就是在这个基础之上建立。如果要过滤特定协议,只要在相应的字节读取数据,判断是否符合要过滤的规则就可以了,当然实际的过滤规则要复杂的多的多,比如对指定的端口指定的IP的过滤。
Win + R 组合键,打开运行,输入?powershell?命令,确定或回车,打开Windows PowerShell(建议使用管理权限创建此任务);
管理员:Windows?PowerShell窗口中,输入?dism /online /export-driver /destination:[备份路径]?,例如将驱动备份到D盘AAA(该文件夹历闭需要先新建好)文件夹中,则可以输入并回车执行以下命令?dism /online /export-driver /destination:D:\AAA
提示正在导出,这样就可棚芹以导出电脑所有驱动了,看到操作成功完成,就可以关闭管理员:Windows PowerShell窗口
AAA文件夹中,保存了导出的所有驱动;
管理员:Windows?PowerShell窗口中,输入并回车执行以下命令,即可进行还原:肢和裂Dism /online /Add-Driver /Driver:D:\AAA /Recurse
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。