您的位置:首页 > 其它

利用vmware+windbg调试驱动

2009-08-21 14:14 323 查看
首先下载最新的windbg,然后下载symbols

 在windbg的快捷方式的“目标”处填上 "D:/Program
Files/Debugging Tools for Windows/windbg.exe" -y C:/ -b -k
com:port=//./pipe/com_1,baud=115200,pipe

设置vmware虚拟机,虚拟一个串口,把主机,虚拟机的波特率都设置为115200

先打开虚拟机,在boot.ini里加上
multi(0)disk(0)rdisk(0)partition(1)/WINDOWS="Microsoft Windows XP
Professional" /debug /debugport=com1 /baudrate=115200

然后选择调试运行,虚拟机会停止,等待windbg发出 g 命令。

打开windbg,出现断点提示,输入 g,虚拟机继续运行。

在需要调试的驱动工程选项里,选择linker,进入debugging,选中generate debug info,在generate program database里输入 $(TargetDir)$(TargetName).pdb,然后编译工程。

把驱动和应用程序考到虚拟机,

进入windbg,输入 bu driverName!DriverEntry, 其中driverName是驱动的名字,DriverEntry是需要中断的函数名,这样如果驱动运行,就会在DriverEntry处停止。

启动驱动,虚拟机会停止,windbg会自动响应,打开这个驱动的源码文件,并且停止在DriverEntry处。这时,可以单步运行调试。

几种添加断点的命令:

? 普通断点

最简单的设置断点的方法就是通过bp (“Breakpoint”)命令。例如:

bp MyDriver!xyz

bp f89adeaa

第一行,这个断点设在模块中的一个名字(<module>!<name>);第二行,它被设置在一个给出的地址。当运行到其中一个断点时,操作系统就会挂起,并且把控制权交给WinDbg。(你可以在“寻找名字”看看如何为第二个命令取得地址。)

注意:第一个命令的语法假定操作系统已经加载该模块,以及在symbol文件或者外部名定义有足够可用信息关于识别xyz。如果不能在模块中找到xyz,调试器会这么告诉你这些。

? 延迟断点

说到驱动程序没有被加载,你最初的哪个断点,使用bu(见上述开始调试示例驱动)设置的是一个“可延迟的”断点。Bu命令的参数是一个模块及它里面的名字,例如:

bu sioctl!SioctlDeviceControl

? 另外一个设置一般断点的方法是通过source窗口。当你中断于DriverEntry,将光标移动到需要停止的代码,按下F9,这样驱动就会在这停止。

你可以使用bl (“Breakpoint List”)查看所有已设置的断点:每个断点都有一个号码并且显示出断点状态,“e”是“enabled”,而“d”是“disabled”。

当程序停止时,可以使用dv 查看一个已知变量(Irp是查看的变量。):

kd> dv Irp,显示 Irp = 0xff70fbc0,该响应的意思是,Irp 变量包含0xFF70FBC0。该响应基于变量内容,而不是地址。你可以确认它:

kd> ?? Irp

struct _IRP * 0xff70fbc0

?? 总是以C++ 为基础

kd> ? Irp

Evaluate expression: -141181880 = f795bc48

这表示变量Irp 位于0XF795BC48。你可以通过使用dd (详见 dd 命令)显示内存数据,确认该变量真的包含数据0xFF70FBC0。

kd> dd f795bc48 l1

f795bc48  ff70fbc0

以及内存指向这里:

kd> dd 0xff70fbc0

ff70fbc0  00940006 00000000 00000070 ff660c30

ff70fbd0  ff70fbd0 ff70fbd0 00000000 00000000

ff70fbe0  01010001 04000000 0006fdc0 00000000

ff70fbf0  00000000 00000000 00000000 04008f20

ff70fc00  00000000 00000000 00000000 00000000

ff70fc10  ff73f4d8 00000000 00000000 00000000

ff70fc20  ff70fc30 ffb05b90 00000000 00000000

ff70fc30  0005000e 00000064 0000003c 9c402408

查看象IRP这样的变量,

kd> dt Irp

Local var @ 0xf795bc48 Type _IRP*

0xff70fbc0

   +0x000 Type             : 6

   +0x002 Size             : 0x94

   +0x004 MdlAddress       : (null)

   +0x008 Flags            : 0x70

   +0x00c AssociatedIrp    : __unnamed

   +0x010 ThreadListEntry  : _LIST_ENTRY [ 0xff70fbd0 - 0xff70fbd0 ]

   +0x018 IoStatus         : _IO_STATUS_BLOCK

   +0x020 RequestorMode    : 1 ''

   +0x021 PendingReturned  : 0 ''

   +0x022 StackCount       : 1 ''

   +0x023 CurrentLocation  : 1 ''

   +0x024 Cancel           : 0 ''

   +0x025 CancelIrql       : 0 ''

   +0x026 ApcEnvironment   : 0 ''

   +0x027 AllocationFlags  : 0x4 ''

   +0x028 UserIosb         : 0x0006fdc0

   +0x02c UserEvent        : (null)

   +0x030 Overlay          : __unnamed

   +0x038 CancelRoutine    : (null)

   +0x03c UserBuffer       : 0x04008f20

         +0x040 Tail             : __unnamed

? 在当前例程中显示一个变量(当前的“scope”),使用dv

kd> dv

   DeviceObject = 0x82361348

            Irp = 0xff70fbc0

   outBufLength = 0x64

         buffer = 0x00000000 ""

          irpSp = 0xff70fc30

           data = 0xf886b0c0 "This String is from Device Driver !!!"

       ntStatus = 0

            mdl = 0x00000000

    inBufLength = 0x3c

        datalen = 0x26

         outBuf = 0x00000030 ""

          inBuf = 0xff660c30 "This String is from User Application; using METHOD_BUFFERED"

这是一个参数变量列表以及一些在断点位置已知的变量。“已知”是一个重要的限定词。例如如果一个变量优化成一个寄存器,它将不会被显示,尽管可以反汇编它(View=>Disassembly 打开反汇编窗口)并且检查寄存器。

如果只关心一个变量,你可以:

kd> dv outBufLength

   outBufLength = 0x64

显示结构体内的某个值 kd> ?? irp->type

 

显示当前线程的错误值:!gle会显示当前线程的上一个错误值和状态值。!error命令可以解码HRESULT。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息