《Windows内核安全与驱动开发》阅读笔记 -- 索引目录
https://github.com/minglinchen/WinKernelDev/tree/master/comcap
串口过滤
1. 串口过滤思路
每一个串口在 Device\ 文件夹下都有一个对应的设备,每个设备及对应的一个设备栈;
我们自己的驱动来生成过滤设备,然后依次绑定这些设备的设备栈,处理各个设备栈中的IRP请求,这样就实现了设备过滤。
2. 如何来找到对应的设备
其串口设备都是以Serial1,Serial2,Serial3命名的,如下图:
因而内核中又提供 IoGetDeviceObjectPointer 函数,该函数可以通过一个设备名称UnicodeString来获取该设备指针,
这样就很容易来获取相应的设备对象,进行绑定;另外还要了解RtlStringCchPrintfW这个函数,可以格式化输入。
则下面的代码就很好理解,其就是初始化UNICODE字符串进行绑定:
3. 如何来进行绑定设备
经过上面那步,我们已经获取绑定的目标设备,下面就是需要绑定设备了。
内核提供了一个函数 IoAttachDeviceToDeviceStack,该函数可以附着设备,同时IoDetachDevice可以来解除设备的附加;
下面举一个该设备的例子,很好理解:
因此我们可以看到下面代码,很明显就是来绑定设备:
4. 如何来创建过滤设备
上面我们已经讲了如何将过滤设备绑定到目标的设备栈中,现在有一个问题,我们应该如何创建过滤设备。
其实创建设备,我们在之前的通讯都已经反复使用了,这并不复杂,但是设备的各种属性应该如何处理呢?
其实对应的操作很简单,我们设置与过滤目标的属性值相同即可。
1)DeviceType
我们在用IoCreateDevice时要标记设备属性,我们之前在创建设备时一般会设置为UNKNOWN类型,但是现在我们可以使用目标设置的DeviceType,
因此我们可以看到如下代码,这种写法是非常好理解的。
2)Flags
设备中的Flags是一些DO_XXX的参数,我们需要设置的是内存方式(缓冲、直接、MDL)、初始化完成与 DO_POWER_PAGABLE。
3)Characteristics
我们判断其是否设置 FILE_DEVICE_SECURE_OPEN 属性,这些都是默认的。
因此我们可以看到下面初始化代码:
5. IRP处理
我们现在已经绑定了过滤设备,之后所有会发送到Device\Serial0,1,...的消息都会被我们驱动的过滤设备接收到;
其设备接收之后会根据IRP的MajorFunction发送到对应的派发函数,我们现在直接全部绑定一个派发函数,集中处理IRP。
对于IRP的处理,我们有博客:
现在,我们只是简单的处理 IRP_MJ_WRITE , 直接打印过来即可,至于其他的,直接跳过,不修改参数,调用IoCallDriver,
下一个设备会原封不动地处理该参数,这很容易理解。
6. 程序整体代码逻辑的处理
上面我们已经讨论过其单个的实现细节,但是其程序总体是如何设计的呢?
首先,我们默认是绑定Device\Serial0 ~ 31 的,因此需要创建数组,需要创建哪几个数组呢?
依次是 原顶层设备指针、过滤设备指针 , 这里不需要目标的过滤设备指针,因为原来顶层设备指针就可以来代替。
因此我们可以看到两个数组: