1.先说说调试的准备工作。一般调试驱动都是在虚拟机中进行的,这里也不例外,用windbg+vmware双击联调。通常开发阶段,Wdm驱动以inf形式安装并加载,加载后依次执行DriverEntry,AddDevice并响应IRP_MJ_PNP&IRP_MN_START事件。安装的同时,pnp管理器会复制文件及改写注册表,待下次重启,驱动在系统重启阶段会加载运行驱动。因此,在DriverEntry时加入断点尤为重要,要不然将错过这些函数的调试时机。在x86时代,加入口断点无非是代码中插入 asm int 3.但是,这么美好的时代已经过去了,x64驱动不支持嵌入汇编。取而代之,必须通过编写一个asm文件,在源码中以调用外部函数的形式,共5步来实现。
1.1第一步实现int 3的汇编代码形如:
.code asm_int3 proc int 3 ret asm_int3 endp end1.2将这段代码保存为softbp.asm。然后用wdk自带的ml64编译,注意仅编译生成obj文件:
ml64 /c softbp.asm1.3接着是在C文件中调用这个函数,如在wdm/bus/busenum.c的DriverEntry处加入断点
extern void asm_int3(); //<-------------外部函数声明 NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) /*++ Routine Description: Initialize the driver dispatch table. Arguments: DriverObject - pointer to the driver object RegistryPath - pointer to a unicode string representing the path, to driver-specific key in the registry. Return Value: NT Status Code --*/ { asm_int3(); //<--------------外部函数调用 Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Driver Entry \n")); // // Save the RegistryPath for WMI.1.4修改sources文件,添加对softbp.obj的链接:
原本sources文件中TARGETLIBS的值为
TARGETLIBS= $(DDK_LIB_PATH)\wdmsec.lib \ $(DDK_LIB_PATH)\ntstrsafe.lib修改为:
TARGETLIBS= $(DDK_LIB_PATH)\wdmsec.lib \ $(DDK_LIB_PATH)\ntstrsafe.lib \ softbp.obj1.5运行build -ceZ编译链接整个toaster工程。
2.得到驱动文件后就是部署阶段。win7 x64的部署也是够磨人的:bcdedit增加启动项(再次怀念xp的好,修改boot.ini就够了),禁用驱动签名,最后安装驱动。以下的步骤都在虚拟机中进行
2.1增加启动项:
2.1.1 以administrator权限下进入cmd,运行bcdedit命令设置端口COM1为调试端口, baudrate为115200(我已将虚拟机的打印机移除,打印机可耻的占用着COM1,并将串口的名字改为COM1)
bcdedit /dbgsettings serial baudrate:115200 debugport:12.1.2 复制一个开机选项, 以进入OS的debug模式
bcdedit /copy {current} /d DebugEnty2.1.3 接着增加一个新的选项到引导菜单
bcdedit /displayorder {current} {6426f429-17fc-11e6-bf64-ad656b9740aa}{6426f429-17fc-11e6-bf64-ad656b9740aa}是2.1.2运行结束后生成的id值
2.1.4 激活前面生成的debug项
bcdedit /debug {6426f429-17fc-11e6-bf64-ad656b9740aa} on最后上一张效果图,然后重启机器准备调试:
3.windbg链接。
开始串口连接前,要设置调试符号和windbg启动参数,我直接写了个脚本setenv.bat完成这两步,以后双击运行即可:
;set _NT_SYMBOL_PATH=SRV*C:\sym;用于设置调试符号的路径 set _NT_SYMBOL_PATH=SRV*C:\sym; ;我的winbdg装在下列位置,后面的参数是串口调试参数 "D:\WinDDK\7600.16385.1\Debuggers\windbg.exe" -b -k com:pipe,port=\\.\pipe\com_1,baud=115200,pipe系统重启后双击setenv.bat,在虚拟机中选择DebugEntry 按F8进入高级启动项,然后选择Disable Driver Signature Enforcement
(注,在等待虚拟机启动期间,经常出现windbg闪退,这时再双击setenv.bat即可。)
4.部署toaster
进入win7后,在控制面板中没有硬件向导的一席之地!需要通过在开始菜单-运行中输入hdwwiz.exe来打开。真是何其不易。ms出于安全目的,希望我们通过driver store安装受信得驱动,倒给开发驱动的找了一堆破事。安装toaster的步骤不再叙述,参照wdk中xp下安装方式在hdwwiz.exe中设置即可。
安装的末尾,也就是进入DriverEntry,由于我们在代码中设置了int3断点,因此windbg会获得执行权。这时可以追加并验证toaster的调试符号,因为此时驱动已经加载到内存中,因此设置断点不会报类似code not set之类的错误,而且符号也能正确加载。
追加toaster调试符号 kd> .sympath+ C:\toaster\wdm\bus\objchk_win7_amd64\amd64 Symbol search path is: SRV*C:\sym;C:\toaster\wdm\bus\objchk_win7_amd64\amd64 检验符号是否加载 kd> lm m busenum* start end module name fffff880`0392e000 fffff880`0393e000 busenum (private pdb symbols) c:\toaster\wdm\bus\objchk_win7_amd64\amd64\BusEnum.pdb 验证符号是否和sys版本一致 kd> !itoldyouso busenum c:\toaster\wdm\bus\objchk_win7_amd64\amd64\busenum.sys busenum.sys Timestamp: 57333596 SizeOfImage: 10000 pdb: c:\toaster\wdm\bus\objchk_win7_amd64\amd64\BusEnum.pdb pdb sig: A8748D1B-8C93-4855-BBC7-4D773CADC3B0 age: 1 Loaded pdb is c:\toaster\wdm\bus\objchk_win7_amd64\amd64\BusEnum.pdb BusEnum.pdb pdb sig: A8748D1B-8C93-4855-BBC7-4D773CADC3B0 age: 1 MATCH: BusEnum.pdb and busenum.sys 验证当前执行的位置是不是在busenum中 kd> ln $ip (fffff880`039301a0) busenum!asm_int3 | (fffff880`039301c0) busenum!__security_check_cookie Exact matches:待一切验证完毕,就可以在AddDevice 等函数入口下断点。等下次系统在启动阶段时,会在这些断点处停下。
如果想多次进入DriverEntry/AddDevice函数,可以在设备管理器中找到toaster设备,然后右键disable/enable设备,就能多次进入这些函数