windbg 调试
#调试命令窗口
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#重要说明
(1) windbg命令分为标准命令,元命令和扩展命令。
标准命令提供最基本的调试功能,不区分大小写。如:bp g dt dv k等
元命令提供标准命令没有提供的功能,也内建在调试引擎中,以.开头。如.sympath .reload等
扩展命令用于扩展某一方面的调试功能,实现在动态加载的扩展模块中,以!开头。如!analyze等
(2) 进入调试状态时,直接回车可重复执行上一条命令;按上下方向键可以浏览和选择以前输入过的命令
(3) 神奇的Tab键,进行命令补全;ESC清除当前命令输入框中的文本
(4) 使用;作为分隔符,可以在同一行输入多条命令
(5) 上图红色框中的“0:000”。【0为当前调试会话的进程号;000为调试会话的线程号】
(6) 当命令提示符显示*BUSY*时,即使命令输入框可以输入命令,但输入的命令不会立即被执行,要等windbg空闲时才能执行。
可使用Ctrl + Break来终止一个长时间未完成的命令
#启动调试
windbg "notepad.exe" arguments // 使用windbg启动调试notepad.exe
windbg -p 4200 // 将windbg附加到一个正在运行的pid为4200的进程上
windbg -pn "notepad.exe" // 将windbg附加到一个正在运行的名为notepad.exe的进程上
windbg –z "c:\mydumpfile.dmp" // 调试mydumpfile.dmp文件
.attach 0n4220 // 4220为十进制pid,使用该命令附加调试时,必须先存在一个调试会话
.detach // 分离调试
.restart // 重启并调试
.kill // 强制结束当前调试
q // 退出windbg
#获取帮助
? // 打印出所有标准命令
.help // 打印出所有元命令
.hh // 打开windbg的chm帮助文件
command /? // 打印命令command具体参数用法
#注释符
* // 注释整行
$$ // 注释(遇到分号结束)
#配置调试环境
.sympath // 查看当前符号查找路径
.sympath c:\symbols // 将符号查找路径设为:c:\symbols
.sympath+ c:\symbols // 将c:\symbols添加到符号查找路径集合中
.symfix // 将符号查找路径设为:SRV*WinDbg安装目录\Sym*http://msdl.microsoft.com/download/symbols
.symfix f:\symbols // 将符号查找路径设为:SRV*f:\symbols*http://msdl.microsoft.com/download/symbols
.symfix+ f:\symbols // 将SRV*f:\symbols*http://msdl.microsoft.com/download/symbols添加到符号查找路径集合中
.srcpath // 查看当前源文件查找路径
.srcpath f:\src // 将源文件查找路径设为:f:\src
.srcpath+ f:\src // 将f:\src添加到源文件查找路径集合中
.exepath // 查看可执行文件查找路径
.exepath f:\bin // 将可执行文件查找路径设为:f:\bin
.exepath+ f:\bin // 将f:\bin添加到可执行文件查找路径集合中
#符号加载与查看
除了使用ld和.reload命令直接加载符号文件,某些使用符号的命令也可以触发调试器来加载符号,如:栈回溯命令(k*)和反汇编命令(u)等。
值得说明的是,windbg缺省使用的是懒惰式符号加载策略,当它收到模块加载事件时,它通常是不会加载符号的,符号状态显示为deferred(延迟加载)。
.symopt // 显示当前所有符号选项
.symopt+ flags // 添加符号选项
.symopt- flags // 删除符号选项
ld * // 为所有模块加载符号
ld kernel32 // 加载kernel32.dll的符号
.reload // 为所有模块加载符号信息
.reload /f /v // f:强制立即模式 v:详细模式
.reload /f @"c:\windows\System32\verifier.dll" // 为指定模块加载符号信息
x *! // 列出所有模块对应的符号信息
lm // 列出所有模块对应的符号信息
x ConsoleTest!* // 列出ConsoleTest模块中的所有符号
x ConsoleTest!add* // 列出ConsoleTest模块中的所有add开头的符号
x /t /v ConsoleTest!* // 带数据类型、符号类型和大小信息,列出ConsoleTest模块中的所有符号
x kernel32!*LoadLib* // 列出kernel32模块中所有含LoadLib字样的符号
u // 反编译
#进程与线程
| // 列出调试进程
|* // 列出调试进程
|N // 参看序数为N的调试进程
|Ns // 切换序数为N的进程为当前调试进程
~ // 列出线程
~* // 所有线程
~* k // 所有线程堆栈信息
~* r // 所有线程寄存器信息
~. // 查看当前线程
~# // 查看导致当前事件或异常的线程
~N // 查看序数为N的线程
~~[n] // 查看线程ID为n的线程
~Ns // 切换序数为N的线程为当前调试线程
~N f // 冻结序数为N的线程
~N u // 解冻序数为N的线程
~N n // Suspend序数为N的线程
~N m // Resume序数为N的线程
#断点
bl // 列出所有断点
bc * // 清除所有断点
bc 1 // 清除1号断点
bc 1 2 5 // 清除1号、2号、5号断点
be * // 启用所有断点
be 1 // 启用1号断点
be 1 2 5 // 启用1号、2号、5号断点
bd * // 禁用所有断点
bd 1 // 禁用1号断点
bd 1 2 5 // 禁用1号、2号、5号断点
bp 7c801b00 // 在7c801b00地址处放置一个断点
bp `ConsoleTest.cpp:36` // 在ConsoleTest.cpp的36行处放置一个断点
bp main // 在main函数的起始处放置一个断点
bp CSecondLoader::CSecondLoader // 在CSecondLoader的构造函数处放置一个断点
bp `ConsoleTest.cpp:40` "j (poi(MyVar)>5) ''; 'g'" // 条件断点 MyVar>5,执行空语句(;),断住 否则继续执行
bp `ConsoleTest.cpp:40` "j @eax = 0xa3 ''; 'g'" // 条件断点 寄存器eax的值为0xa3时断住
bu // 保存断点,其用法和bp一样
bm add_* // 匹配add_开头的函数,并在这些函数起始处都打上断点
ba w4 0483dfe0 // 当对0483dfe0地址写操作时停下
// ba [r|w|e] [Size] Addr [r=read/write, w=write, e=execute], Size=[1|2|4 bytes]
#调试执行控制
g // Go(F5)
gH // 执行gH命令强制让调试器返回已经处理了这个异常。【Go with Exception Handled】
// 系统收到这个回复后会停止分发异常(因为调试器声称已经处理了异常),恢复调试目标继续执行,
// 但由于异常条件仍在,所以还会产生异常,于是再次分发,WinDBG再次中断到命令模式。
gN // 【Go with Exception Not Handled】
// 执行gN命令强制让调试器返回没有处理了这个异常,那么系统会进一步分发该异常,
// 如果没有其他调试器也不处理,最后系统会弹出程序终止对话框。
gu // 执行到当前函数完成时停下 【Go Up】
p // 单步执行(F10) 【Step】
p 2 // 2为步进数目
pc // 执行到下一个函数调用处停下 【Step to Next Call】
pa 7c801b0b // 执行到7c801b0b地址处停下 【Step to Adress】
t // Step into(F11) 【Trace】
tc // 执行到下一个进入点处停下 【Trace to Next Call】
ta 7c801b12 // 执行到7c801b12地址处停下 【Trace to Adress】
# 查看变量
dt nRet // 查看变量nRet的类型与值
dv // 显示当前函数内所有局部变量,函数参数
dv n* // 显示当前函数内n开头的所有局部变量,函数参数
dv /t /i /V /a|/n|/z
/*****************************************
更加详细地显示当前函数内所有局部变量,函数参数信息
i = type (local, global, parameter)
t = data type
V = memory address or register location
-----------------------
a = sort by Addr, n = sort by name, z = sort by size
*****************************************/
#调用堆栈
k // 显示当前调用堆栈
kn // 带栈编号显示当前调用堆栈
kb // 打印出前3个函数参数的当前调用堆栈
kb 5 // 只显示最上的5层调用堆栈
.frame // 显示当前栈帧
.frame n // 设置编号n的栈帧为当前栈帧
.frame /r n // 设置编号n的栈帧为当前栈帧 并显示寄存器变量
!uniqstack // 显示所有线程的调用堆栈
#寄存器
r // 显示所有寄存器信息
r eax, edx // 显示eax,edx寄存器信息
r eax=5, edx=6 // 对寄存器eax赋值为5,edx赋值为6
#内存
da /c 5 7c801e02 // 从7c801e02内存处开始,显示5个ascii字符
/*****************************************
d[a| u| b| w| W| d| c| q| f| D] [/c 列数] [地址]
a = ascii chars
u = Unicode chars
b = byte + ascii
w = word (2b)
W = word (2b) + ascii
d = dword (4b)
c = dword (4b) + ascii
q = qword (8b)
f = floating point (single precision - 4b)
D = floating point (double precision - 8b)
*****************************************/
dyb /c 3 7c801e02 // 从7c801e02内存处开始,显示3个byte及二进制
/*****************************************
dy[b | d] .. // b = binary+byte d = binary+dword
*****************************************/
#dump输出
.dump /ma "d:\mydmpfile.dmp" // 将当前调试进程输出Dump文件
#其他元命令
.tlist // 显示所有进程
.cls // 清除屏幕
#其他扩展命令
!analyze -v // 详细显示当前异常信息
!peb // 格式化输出PEB信息(process's environment block)
!gle // 打印当前线程最近的错误信息
!gle -all // 打印所有线程的最近的错误信息
!error 897// 显示错误码为897的详细描述信息
#帮助
中文在线帮助:http://www.dbgtech.net/windbghelp/index.html
windbg cmd: http://www.slideshare.net/kewuc/windbg-cmds 【下载】
dt命令显示局部变量、全局变量或数据类型的信息。它也可以仅显示数据类型。即结构和联合(union)的信息。
0: kd> dt _PEB
- nt!_PEB
- +0x000 InheritedAddressSpace : UChar
- +0x001 ReadImageFileExecOptions : UChar
- +0x002 BeingDebugged : UChar
- +0x003 SpareBool : UChar
- +0x004 Mutant : Ptr32 Void
- +0x008 ImageBaseAddress : Ptr32 Void
- +0x00c Ldr : Ptr32 _PEB_LDR_DATA
- +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
- [...]
dt查看特定地址的eprocess结构内容
- 0: kd> dt _EPROCESS 8055d0c0
- ntdll!_EPROCESS
- +0x000 Pcb : _KPROCESS
- [...]
- +0x160 PhysicalVadList : _LIST_ENTRY [ 0x8055d220 - 0x8055d220 ]
- +0x168 PageDirectoryPte : _HARDWARE_PTE_X86
- +0x168 Filler : 0
- +0x170 Session : (null)
- +0x174 ImageFileName : [16] "Idle"
- +0x184 JobLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
- +0x18c LockedPagesList : (null)
- +0x190 ThreadListHead : _LIST_ENTRY [ 0x8055d250 - 0x8055d250 ]
- +0x198 SecurityPort : (null)
- [...]
dt通配符显示模块结构名称
kd> dt ntdll!_peb*
ntdll!_PEB
ntdll!_PEB_LDR_DATA
ntdll!_PEB_FREE_BLOCK
d*命令显示给定范围内存的内容。
d, da, db, dc, dd, dD, df, dp, dq, du, dw, dW, dyb, dyd (Display Memory)
如果省略掉Range ,命令将会从上一条内存查看命令结束的位置开始。这使得可以连续的进行内存查看。
d这种显示的格式和最近一次d*命令的格式相同。如果之前没有使用过d*命令,d 和db 的效果相同。
注意d重复前一个以d开头的命令。包括dda、ddp、ddu、dpa、dpp、dpu、dqa、dqp、dqu、dds、dps、dqs、ds、dS、dg、dl、dt和dv,以及本页中的显示命令。如果在d之后的参数不适当,可能会产生错误。
- 7c92120e cc c3 8b ff cc c3 8b ff-8b 44 24 04 cc c2 04 00 .........D$.....
- 7c92121e 64 a1 18 00 00 00 c3 57-8b 7c 24 0c 8b 54 24 08 d......W.|$..T$.
- 7c92122e c7 02 00 00 00 00 89 7a-04 0b ff 74 1e 83 c9 ff .......z...t....
- 7c92123e 33 c0 f2 ae f7 d1 81 f9-ff ff 00 00 76 05 b9 ff 3...........v...
- 7c92124e ff 00 00 66 89 4a 02 49-66 89 0a 5f c2 08 00 57 ...f.J.If.._...W
- 7c92125e 8b 7c 24 0c 8b 54 24 08-c7 02 00 00 00 00 89 7a .|$..T$........z
- 7c92126e 04 0b ff 74 1e 83 c9 ff-33 c0 f2 ae f7 d1 81 f9 ...t....3.......
- 7c92127e ff ff 00 00 76 05 b9 ff-ff 00 00 66 89 4a 02 49 ....v......f.J.I
- 0:001> d
- 7c92128e 66 89 0a 5f c2 08 00 57-8b 7c 24 0c 8b 54 24 08 f.._...W.|$..T$.
- 7c92129e c7 02 00 00 00 00 89 7a-04 0b ff 74 22 83 c9 ff .......z...t"...
- 7c9212ae 33 c0 66 f2 af f7 d1 d1-e1 81 f9 fe ff 00 00 76 3.f............v
- 7c9212be 05 b9 fe ff 00 00 66 89-4a 02 49 49 66 89 0a 5f ......f.J.IIf.._
- 7c9212ce c2 08 00 83 ec 0c dd 14-24 e8 bf cf 00 00 e8 0d ........$.......
- 7c9212de 00 00 00 83 c4 0c c3 8d-54 24 04 e8 6a cf 00 00 ........T$..j...
- 7c9212ee 52 9b d9 3c 24 74 50 66-81 3c 24 7f 02 74 06 d9 R..<$tPf.<$..t..
- 7c9212fe 2d 5c e7 92 7c d9 fe 9b-df e0 9e 7a 1d 83 3d ac -\..|......z..=.
我们可以看出第二个d显示的地址是前面的地址的延续
da:ASCII 字符每行最多48个字符。显示一直继续直到遇到第一个null字节或者到达range 值指定的所有字符都已经显示。所有不可打印字符,如回车和换行都被显示为点号(.)。
- eax=00000009 ebx=00000001 ecx=00000002 edx=00000003 esi=00000004 edi=00000005
- eip=7c92120e esp=00c1ffcc ebp=00c1fff4 iopl=0 nv up ei pl zr na pe nc
- cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000246
- ntdll!DbgBreakPoint:
- 7c92120e cc int 3
- 0:001> da ebp
- 00c1fff4 ""
- 0:001> da
- 00c1fff5 ""
- </SPAN>
这个用来查ASCII字符串好像不错哦,但是应该注意到,这个打印只有ASCII码,没有字节数显示
db:字节值和ASCII字符每个显示行都包含该行第一个字节的地址,后面跟16进制字节值。这些字节值后面会紧跟它们对应的ASCII值。第8和第9个16进制值之间会用连字号(-)分隔。所有不可打印字符,如回车和换行都被显示为点号(.)。
默认的显示个数为128字节。
这个就不写例子了,第一个d给出的就是db的例子
dc:双字值(4字节)和ASCII字符。每个显示行都会显示行中第一个数据的地址,并且每行最多显示8个16进制值以及它们对应的ASCII字符。默认的显示数量为32个DWORD(128字节)。
dd:双字值(4字节) 默认的显示数量为32个DWORD(128字节)。
这两个比对着给个例子:
- 7c92120e ff8bc3cc ff8bc3cc 0424448b 0004c2cc .........D$.....
- 7c92121e 0018a164 57c30000 0c247c8b 0824548b d......W.|$..T$.
- 7c92122e 000002c7 7a890000 74ff0b04 ffc9831e .......z...t....
- 7c92123e aef2c033 f981d1f7 0000ffff ffb90576 3...........v...
- 7c92124e 660000ff 49024a89 5f0a8966 570008c2 ...f.J.If.._...W
- 7c92125e 0c247c8b 0824548b 000002c7 7a890000 .|$..T$........z
- 7c92126e 74ff0b04 ffc9831e aef2c033 f981d1f7 ...t....3.......
- 7c92127e 0000ffff ffb90576 660000ff 49024a89 ....v......f.J.I
- 0:001> dd eip
- 7c92120e ff8bc3cc ff8bc3cc 0424448b 0004c2cc
- 7c92121e 0018a164 57c30000 0c247c8b 0824548b
- 7c92122e 000002c7 7a890000 74ff0b04 ffc9831e
- 7c92123e aef2c033 f981d1f7 0000ffff ffb90576
- 7c92124e 660000ff 49024a89 5f0a8966 570008c2
- 7c92125e 0c247c8b 0824548b 000002c7 7a890000
- 7c92126e 74ff0b04 ffc9831e aef2c033 f981d1f7
- 7c92127e 0000ffff ffb90576 660000ff 49024a89
我们可以发现dd相对来说,少了右边的Asii码字符,所以推荐用dc,不过dd好记,和debug运用相同嘛.
dq:四字值(Quad-word values) (8 bytes)。默认显示数量为16个四字 (128 字节)。
dw:WORD值(2字节)。 每个显示行都会显示行中第一个数据的地址,并且每行最多显示8个16进制值。默认显示数量为64个WORD(128字节)。
dW:WORD值(2字节)和ASCII字符。每个显示行都会显示行中第一个数据的地址,并且每行最多显示8个16进制值。默认显示数量为64个WORD(128字节)。
- 7c92120e ff8bc3cc ff8bc3cc 0424448b 0004c2cc
- 7c92121e 0018a164 57c30000 0c247c8b 0824548b
- 7c92122e 000002c7 7a890000 74ff0b04 ffc9831e
- 7c92123e aef2c033 f981d1f7 0000ffff ffb90576
- 7c92124e 660000ff 49024a89 5f0a8966 570008c2
- 7c92125e 0c247c8b 0824548b 000002c7 7a890000
- 7c92126e 74ff0b04 ffc9831e aef2c033 f981d1f7
- 7c92127e 0000ffff ffb90576 660000ff 49024a89
- 0:001> dw eip
- 7c92120e c3cc ff8b c3cc ff8b 448b 0424 c2cc 0004
- 7c92121e a164 0018 0000 57c3 7c8b 0c24 548b 0824
- 7c92122e 02c7 0000 0000 7a89 0b04 74ff 831e ffc9
- 7c92123e c033 aef2 d1f7 f981 ffff 0000 0576 ffb9
- 7c92124e 00ff 6600 4a89 4902 8966 5f0a 08c2 5700
- 7c92125e 7c8b 0c24 548b 0824 02c7 0000 0000 7a89
- 7c92126e 0b04 74ff 831e ffc9 c033 aef2 d1f7 f981
- 7c92127e ffff 0000 0576 ffb9 00ff 6600 4a89 4902
- 0:001> dW eip
- 7c92120e c3cc ff8b c3cc ff8b 448b 0424 c2cc 0004 .........D$.....
- 7c92121e a164 0018 0000 57c3 7c8b 0c24 548b 0824 d......W.|$..T$.
- 7c92122e 02c7 0000 0000 7a89 0b04 74ff 831e ffc9 .......z...t....
- 7c92123e c033 aef2 d1f7 f981 ffff 0000 0576 ffb9 3...........v...
- 7c92124e 00ff 6600 4a89 4902 8966 5f0a 08c2 5700 ...f.J.If.._...W
- 7c92125e 7c8b 0c24 548b 0824 02c7 0000 0000 7a89 .|$..T$........z
- 7c92126e 0b04 74ff 831e ffc9 c033 aef2 d1f7 f981 ...t....3.......
- 7c92127e ffff 0000 0576 ffb9 00ff 6600 4a89 4902 ....v......f.J.I</SPAN>
dD:双精度浮点数(8字节) 默认的显示数量是15个数字(120字节)。
df:单精度浮点数(4字节) 默认的显示数量是16个数字(64字节)。
dp:指针大小的值。该命令根据目标机的处理器是32位还是64位的,分别等于dd 或dq。默认显示数量为32个DWORD或者16个四字(quad-word) (128 字节)。
du:Unicode字符 。每行最多显示48个字符。显示一直继续直到遇到第一个null字节或者到达range 值指定的所有字符都已经显示。所有不可打印字符,如回车和换行都被显示为点号(.)。
dyb:二进制值和字节的值。默认显示数量为32字节。
dyd:二进制值和双字值(4字节)。默认显示数量为8个DWORD(32字节)。
0:001> dD eip
- 7c92120e -2.43714230651e+306 6.62088185061e-309 5.84873529654e+114
- 7c921226 1.92413942387e-269 1.81520618711e+282 -3.58305289924e+307
- 7c92123e -1.97432319055e+277 -1.75705767106e+307 5.09883096248e+043
- 7c921256 1.20502524006e+111 1.92413942387e-269 1.81520618711e+282
- 7c92126e -3.58305289924e+307 -1.97432319055e+277 -1.75705767106e+307
- 0:001> df eip
- 7c92120e -1.#QNAN -1.#QNAN 1.9309581e-036 4.3722194e-040
- 7c92121e 2.261948e-039 4.2880953e+014 1.2671579e-031 4.9451335e-034
- 7c92122e 9.9632321e-043 3.5567233e+035 1.6165272e+032 -1.#QNAN
- 7c92123e -1.1039027e-010 -8.4258111e+034 9.1834095e-041 -1.#QNAN
- 0:001> dp eip
- 7c92120e ff8bc3cc ff8bc3cc 0424448b 0004c2cc
- 7c92121e 0018a164 57c30000 0c247c8b 0824548b
- 7c92122e 000002c7 7a890000 74ff0b04 ffc9831e
- 7c92123e aef2c033 f981d1f7 0000ffff ffb90576
- 7c92124e 660000ff 49024a89 5f0a8966 570008c2
- 7c92125e 0c247c8b 0824548b 000002c7 7a890000
- 7c92126e 74ff0b04 ffc9831e aef2c033 f981d1f7
- 7c92127e 0000ffff ffb90576 660000ff 49024a89
- 0:001> du eip
- 7c92120e "쏌ヒ쏌ヒ䒋Ф싌.ꅤ."
- 0:001> dyb eip
- 76543210 76543210 76543210 76543210
- -------- -------- -------- --------
- 7c92120e 11001100 11000011 10001011 11111111 cc c3 8b ff
- 7c921212 11001100 11000011 10001011 11111111 cc c3 8b ff
- 7c921216 10001011 01000100 00100100 00000100 8b 44 24 04
- 7c92121a 11001100 11000010 00000100 00000000 cc c2 04 00
- 7c92121e 01100100 10100001 00011000 00000000 64 a1 18 00
- 7c921222 00000000 00000000 11000011 01010111 00 00 c3 57
- 7c921226 10001011 01111100 00100100 00001100 8b 7c 24 0c
- 7c92122a 10001011 01010100 00100100 00001000 8b 54 24 08
- 0:001> dyd eip
- 3 2 1 0
- 10987654 32109876 54321098 76543210
- -------- -------- -------- --------
- 7c92120e 11111111 10001011 11000011 11001100 ff8bc3cc
- 7c921212 11111111 10001011 11000011 11001100 ff8bc3cc
- 7c921216 00000100 00100100 01000100 10001011 0424448b
- 7c92121a 00000000 00000100 11000010 11001100 0004c2cc
- 7c92121e 00000000 00011000 10100001 01100100 0018a164
- 7c921222 01010111 11000011 00000000 00000000 57c30000
- 7c921226 00001100 00100100 01111100 10001011 0c247c8b
- 7c92122a 00001000 00100100 01010100 10001011 0824548b</STRONG></SPAN>