文章是用来记录驱动编程学习过程中遇到的问题和从各个平台收集到的解决方案
一、环境搭建
1. IDE和开发环境
Visual Studio 2019、Windows SDK、Windows WDK //SDK 和 WDK 的版本要一致
2. 环境配置
- 用Visual Studio installer安装spectre缓解库,版本和msvc版本一致
- 新建KMDF项目,将警告忽略,或者调至等级3(虽然有点毛病,后续肯定不能这样,已经出现了问题了,数值运算时的自动有无符号类型转换会警告,原本以为没啥大问题,实际上出了个bug)
- 驱动装载工具:srvinstw,kmdmanager,driverloader,自写加载脚本
- 驱动部署环境:
- win7虚拟机,安装一下vmwaretools方便拖拽等(需要安装微软win7的kb4474419补丁,网上查资料据说是因为更新了SHA2验证,vmware16用的也是新的签名验证方式)
- 开启调试模式,
win+r
,msconfig
中设置或bcdedit -debug on
bcdedit -set loadoptions disable_integrity_check
bcdedit -set testsigning on
- 组策略管理器-》管理模板-》系统-》驱动安装-》签名-》 启用&忽略,使得的能够安装为签名的.sys
- 安装未签名的驱动文件需要将F2->F8->Disable Driver Signature Enforcement设置,来关闭windows不能安装和启动为签名的驱动服务的设置
3. 编译和测试
- release模式(忘记了debug模式出的小问题,貌似是编译过程中选平台的时候???)、64位
- 将.sys文件复制到目标测试机中
- 下载DbgView、sysinstw,前面的用来捕捉驱动的输出,后者用来安装驱动
- Visual Studio默认目标平台为win10,要设置为win7,能够兼容大多数平台;平台选成desktop即可。不这么设置可能会由于目标平台不兼容导致蓝屏或编译报错。
- wow问题,64位驱动只能用64系统来测试。wow机制是仅运行在用户模式下的机制,为的是32位应用程序能够在64位系统中运行,从底层将32位dll中的函数的调用重定向到64版本的dll。
4. 部署
5. Windbg双机调试配置
-
在虚拟机配置中:1)添加一个串行端口;2)勾选使用命名管道,名称设置为
\\.\pipe\管道名
,该端是服务器,另一端是应用程序;3)勾选轮询时主动放弃CPU。 -
在测试机(我用的是win7)中:
win+R
—>msconfig
—>引导选项中,开启调试端口,调试端口设置为第一个串行口(如果默认添加了虚拟机的设备,在虚拟机配置中添加的串行端口不是第一个了,所以选COM2或之后的,视情况而定,如果把打印机之类的串行端口设备移除了的话,选COM1即可)。服务器(宿主机)这一端的命名管道对应的端口要和虚拟机里面的对应上,否则windbg连接的时候会一直显示waiting for reconnect...
-
windbg调试命令和配置启动调试:
- 通过命令行(可以将这些参数加到windbg快捷方式的目标那)
windbg -b -k com:port=\\.\pipe\管道名,baud=115200,pipe
- 通过可视化界面配置
- 通过命令行(可以将这些参数加到windbg快捷方式的目标那)
-
虚拟机和测试集的配置如图:
-
下面记录一下第一次蓝屏调试
- 项目配置上,为了方便调试,项目编译选项为64位的debug版本
- 按照书上面的东西写了个定时器小练习,然后注册驱动运行服务之后,蓝屏报错了
- 卡死后,windbg产生调试信息,报错信息如下:
56行这里是MyTimerSet设置定时器的函数代码,参考《Windows内核安全与驱动开发》里的例子,timer
是一个PMY_TIMER
类型的数据,封装了KTIMER
,KDEFERRED_ROUTINE
,KDPC
,自定义上下文
等数据。后面回到代码看了看,发现是没有为timer申请空间的原因(好滴记得错误。。。),申请空间函数:ExAllocPoolWithTag
,是用来申请一个带标签的内存块,标签长度四个字节,可以设置为助记的四个字符,例如"Tag1"->“1gaT”,文档里的解释是说出现内存问题的时候,好定位是哪一块内存出了问题。记得在模块卸载函数(在DriverEntry入口函数里设置的Unload函数driver->DriverUnload)里面释放空间,内核里面的内存空间不会自动回收(貌似,得在确认一下),释放内存空间函数:ExFreePool
。
-
接着重新编译驱动,放到虚拟机里加载运行调试,发现还是出错,现象是没有蓝屏,鼠标能动,调试端没有报错。因为写的测试驱动是一个定时器,所以怀疑是时间间隔问题,
注意到了这里有个警告,是个可能溢出问题,但是ULONG 类型的msec测试的时候设置为1000,并没有溢出。改成-(10000*msec)发现报了这个错
QuadPart是有符号的,msec是无符号的,所以运算转换的时候出问题了,先对msec显式转换即可。
这里调试端没有任何消息,因此windbg也得另外设置,
ed nt!Kd_default_mask 8
,就能打印dbgprint
输出的信息。