1 小端口驱动其实就是真正的网卡驱动,相对于协议驱动而言,它更贴近物理层
A 现代windows系统提倡的是仅隔离出物理可变部分,其他的部分则给予统一的实现与接口,而要求网卡商开发的网卡驱动,则仅仅剩下被隔离出的少部分,之后部分插在通用的接口(这里的接口指小端口驱动)上即可
B 开发一个适用于物理网卡的小端口驱动一般都是网络芯片厂商的工作,在安全软件领域,小端口驱动技术主要用于虚拟网卡
2 协议驱动下面邻接的必定是NDIS小端口驱动,NDIS小端口驱动上面邻接的必定是NDIS协议驱动,但小端口驱动的下层可以是协议驱动&硬件
3 小端口驱动的运作与编程概述
A 小端口驱动也是先填写一个小端口特征,小端口特征是一个回调函数的指针数组,windows内核在某些时候会调用这些回调函数
B 协议驱动会调用NdisSendPackets进行包的发送,而Windows内核的NDIS子系统则会自动找到该协议绑定的小端口驱动,调用小端口特征中的用于发送数据包的回调函数
C 和实现协议驱动一样,实现小端口驱动就是实现小端口特征中的这些回调函数
4 小端口的初始化
A 初始化全局变量。这些全局变量是在整个驱动中使用的
B 检查版本号
C 生成一个WDF驱动对象
D 初始化包装句柄:NDIS内部会使用这个包装句柄来管理小端口的配置信息,但是小端口驱动的开发者并不需要从这个句柄中获得任何信息,只适用于调用NDIS的内核API
E 填写小端口的特征&并注册小端口(小端口是没有必要去绑定什么东西的)
F 这个驱动需要全局资源一个锁和一个链表。 初始化全局变量。这些全局变量是在整个驱动中使用的
5 小端口驱动的适配器结构
一个小端口驱动可以驱动同一类型芯片的N个网卡。一个事件出现的被某个小端口 驱动的网卡(不一定是物理的)被称为该驱动的一个实例
一个小端口驱动可以是没有任何实例的。但在拥有的情况下,小端口驱动对每个实例要保存一组信息(实例=网卡)(用在driverentry中创建的链表&锁来保存)
// 初始化全局变量。这些全局变量是在整个驱动中使用的
NdisAllocateSpinLock(&GlobalData.Lock);
NdisInitializeListHead(&GlobalData.AdapterList);
6 配置信息的读取
在初始化过程中需要读取配置信息。比如网卡的MAC地址,这些信息都在NICReadRegParameters中实现。向系统读取配置信息时,一个重要的输入参数是在DriverEntry中获得的句柄
7 设置小端口适配器上下文
在协议驱动中,绑定的上下文相当于一个被绑定的网卡,对于小端口驱动来说,同样重要的是一个适配器上下文。适配器上下文是一个指针,这个指针指向的空间就是适配器结构,这个指针必须在MPInitialize中设置好。
比如MPSendPackts(发包的回调)需要用这个指针来选择用哪个网卡来发送数据包
重点:NICInitializeAdapter 这是最关键的一步,就是启动整个网卡 用这个适配器结构做实参Adapter,最后这个适配器会串联到链表中。MPSendPackts(发包的回调)需要用这个指针来选择用哪个网卡来发送数据包
8 书中P393:而windows内核的NDIS子系统则会自动找到该协议绑定的小端口驱动
从上到下顺序如下:
(应用层,相关DLL实现) SOCKET API
(传输层的上层,afd.sys) AFD驱动:(实现SOCKET 的内核函数)与传输层驱动下层tdi.sys不存在形式上的堆叠,但是仍旧可以通过IoCallDrvier()调用传输层驱动的主功能函数(说明tdi.sys也创建了设备),该驱动是SOCKET的内核函数的实现,这些内核函数用协议驱动提供的TDI设备对象的设备名(如tcp)作实参数调用TDI接口来向协议驱动发送格式化后的IRP,如:IRP_MJ_INTERNAL_DEVICE_CONTROL,TDI IOCTL为 TDI_CONNECT
(传输层的下层,tdi.sys) TDI驱动:TDI接口是内核模块tdi.sys提供的一组支持函数(参见windows内核原理与实现的P596页),从而将TDI客户(实现SOCKET 的内核函数)和TDI传输器(协议驱动)联系起来,TDI接口实现了3次握手等传输层的相关功能
(TDIFilter.sys)TDI过滤驱动:这里就是TDI过滤驱动所在的位置,查看设备栈时看到ftcp的附加设备附加在tcp设备上, 过滤向协议驱动发送格式化后的IRP,如:IRP_MJ_INTERNAL_DEVICE_CONTROL,TDI IOCTL为 TDI_CONNECT
(tcpip.sys) 协议驱动:提供TDI设备对象,如tcp&udp,过滤驱动创建的设备对象就附加在这些设备上。当协议驱动响应了TDI接口(处理这些格式化的IRP)则说明它是一个TDI传输器,在处理这些IRP的回调中会通过小端口驱动来发包&收包
(ndisedge.sys)小端口驱动:设ndisdge是最后一个注册的小端口驱动,TCPIP协议驱动会调用它的SendPacketsHandler,而SendPacketsHandler中会向Ndisport发送写请求(之前ndisdge已经将ndisport和非ndisdge的实例绑定)SendPacketsHandler的适配器上下文中保存了协议驱动ndisport的绑定上下文(实现方法是P408页)
(ndisprot.sys)协议驱动:ndissport会通过 非ndisdge的实例的打开上下文中的绑定句柄调用 SendPacketsHandler (这时会调用物理网卡的网卡驱动的SendPacketsHandler)(ndisport的R3测试程序通过适配器名称JUNK来绑定的,某个网卡驱动创建了该网卡名称,这时ndisport就会使用该网卡来发送数据包),而nidsedge在R0层中通过发送IOCTL_NDISPROT_OPEN_DEVICE + 网卡名称来让ndisport绑定一个非ndisdge的小端口驱动的打开上下问,并用这个打开上下文来调用SendPacketsHandler发包,这时就会进入物理网卡的SendPacketsHandler中
(网卡sys) 小端口驱动:协议驱动通过 小端口驱动的发送回调接口 联系小端口驱动,而小端口驱动通过回调驱动的接收回调联系协议驱动。 小端口只有发送回调接口,协议只有接收回调接口 来将协议驱动和小端口驱动连接起来的
协议驱动和小端口驱动的联系:
1 当windows检测到有网卡存在时,就会调用每个注册过的协议的BindAdpaterHandler函数,于是协议驱动就保存了适配器的信息
2 协议驱动通过 小端口驱动的发送回调接口 联系小端口驱动(因为发送时主动的),而小端口驱动通过回调驱动的接收回调联系协议驱动(因为小端口的收包是主动的,通过网卡驱动的中断来收包)。 小端口只有发送回调接口,协议只有接收回调接口 来将协议驱动和小端口驱动连接起来的
http://jiangkai.net/OneNote/Driv ... .files/image001.png" width=779 height=525>
9 小端口只有发送回调接口,协议只有接收回调接口
10 使用ndisprot发送包 (进行到这里了P409)