天天看点

win7 x64部署和串口调试虚拟驱动toaster

    WDK7600自带的toaster驱动是个很好的学习驱动的案例,从总线驱动到App层,Class-install/Co-install都有涉及。本文主要涉及驱动部署和调试。

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 
end      

1.2将这段代码保存为softbp.asm。然后用wdk自带的ml64编译,注意仅编译生成obj文件:

ml64 /c softbp.asm      

1.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.obj      

1.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:1      

2.1.2 复制一个开机选项, 以进入OS的debug模式

bcdedit /copy {current} /d DebugEnty      

2.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      

最后上一张效果图,然后重启机器准备调试:

win7 x64部署和串口调试虚拟驱动toaster
win7 x64部署和串口调试虚拟驱动toaster

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

win7 x64部署和串口调试虚拟驱动toaster

(注,在等待虚拟机启动期间,经常出现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设备,就能多次进入这些函数