WinDBG 调试命令大全

Posted 墨鱼菜鸡 苹果园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WinDBG 调试命令大全相关的知识,希望对你有一定的参考价值。

转载收藏于:http://www.cnblogs.com/kekec/archive/2012/12/02/2798020.html

 

 #调试命令窗口

 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#使用gflags.exe工具(在windbg所在目录下),让某个进程启动时,拉取windbg进行调试

如下截图:当名称为captcomm.exe的进程启动时,拉起windbg调试

也可通过脚本命令来实现:

复制代码
// 运行captcomm.exe时,启动windbg调试
reg add "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\captcomm.exe" /v Debugger /t REG_SZ /d "C:\\Program Files\\Debugging Tools for Windows (x86)\\windbg.exe" /f
// 解除启动时windbg调试
reg delete "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\captcomm.exe" /f

// 64位系统上,也可以设置以下注册表节点
reg add "HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\captcomm.exe" /v Debugger /t REG_SZ /d "C:\\Program Files\\Debugging Tools for Windows (x86)\\windbg.exe" /f
// 解除启动时windbg调试
reg delete "HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\captcomm.exe" /f

// 测试发现:HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options和HKLM\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options指向的是同一数据,修改其中任何一个都可以
复制代码

安全软件可能会禁止修改注册表的Image File Execution项:

-- 对于360安全卫士,在“设置”中去掉开启360自我保护”的勾选来关闭

-- 对于McAfee,需要禁止IPS(Intrusion Prevension Systems)。

-- 然而,电脑管家,则不会对该键值的注册表修改进行阻止。

 

#重要说明

(1) windbg命令分为标准命令元命令扩展命令

标准命令提供最基本的调试功能,不区分大小写。如:bp g dt dv k等
元命令提供标准命令没有提供的功能,也内建在调试引擎中,以.开头。如.sympath .reload等
扩展命令用于扩展某一方面的调试功能,实现在动态加载的扩展模块中,以!开头。如!analyze等

(2) 进入调试状态时,直接回车可重复执行上一条命令;按上下方向键可以浏览和选择以前输入过的命令

(3) 神奇的Tab键,进行命令补全;ESC清除当前命令输入框中的文本

(4) 选择Command窗口中的内容,然后右击进行复制

(5) 使用;作为分隔符,可以在同一行输入多条命令

(6) 上图红色框中的“0:000”。0为当前调试会话的进程号000为调试会话的线程号

(7) 当命令提示符显示*BUSY*时,即使命令输入框可以输入命令,但输入的命令不会立即被执行,要等windbg空闲时才能执行。

     可使用Ctrl + Break来终止一个长时间未完成的命令

(8) 一次可以执行多条命令,命令间用分号;分隔 【:bp main;bp `view.cpp:120`】,一次打2个断点

(9)按Ctrl + Alt + V开启/关闭verbose Output(详细输出模式)

(10) 为了保证windbg流畅运行,在调试时,尽量不要开启Watch、Locals、Registers、Call Stack、Processes and Threads窗口,直接用command来获取信息

#启动调试

windbg -I  // 将windbg设置成默认调试器

windbg "notepad.exe" arguments  // 使用windbg启动调试notepad.exe

windbg -p 4200  // 将windbg附加到一个正在运行的pid为4200的进程上

windbg -pn "notepad.exe"  // 将windbg附加到一个正在运行的名为notepad.exe的进程上

windbg -p 4200 -c "sxd av;sxi c0000005;sxi c0000008;g" // 将windbg附加到一个正在运行的pid为4200的进程上,附加成功后,执行sxd av;sxi c0000005;sxi c0000008;g命令

windbg –z "c:\\mydumpfile.dmp" // 调试mydumpfile.dmp文件

.opendump "c:\\mydumpfile.dmp"  // 调试mydumpfile.dmp文件

windbg -y d:\\mySymbols // 指示symbol路径

windbg -srcpath d:\\Src  // 指示源文件路径

windbg -i  d:\\myApp  //指示exe、dll等可执行模块路径

.attach 0n4220  // 4220为十进制pid,使用该命令附加调试时,必须先存在一个调试会话

.detach   // 分离调试

.restart  // 重启并调试

.kill  // 强制结束当前调试

q  // 结束当前调试会话,回到基础工作空间,并结束调试进程

qd  // 结束当前调试会话,回到基础工作空间,但不结束调试进程

CTRL+ALT+V  // 打开或关闭 Verbose 模式开关,某些命令在此模式下可以给出更多详细信息

.time // 调试会话时间信息

.lastevent  // 显示最新的异常信息或事件信息

version  // 显示windbg和已加载的调试器扩展相关的信息

vercommand  // 显示windbg的启动路径及命令行信息

.chain  // 显示已经加载进来的调试器扩展

.extmatch /D /e wow64exts *  // 显示wow64exts调试器扩展中的命令

#获取帮助

?   // 打印出所有标准命令

.help  // 打印出所有元命令

.hh  // 打开windbg的chm帮助文件

.hh bp  // 打开windbg的chm帮助文件bp命令介绍页

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   注:必须勾选上菜单“Debug”-“Source Mode”;另外pdb须与exe、dll等执行模块匹配上

.srcpath+ f:\\src  // 将f:\\src添加到源文件查找路径集合中

.exepath // 查看可执行文件查找路径

.exepath f:\\bin // 将可执行文件查找路径设为:f:\\bin

.exepath+ f:\\bin  // 将f:\\bin添加到可执行文件查找路径集合中

 

#系统信息

vertarget // os信息

!cpuid  // cpu信息

#wow64模式  【x64版windbg调试win32程序】

.load wow64exts  // [!load wow64exts] 加载wow64exts.dll模块  注:!sw就是wow64exts中的命令

.unload wow64exts  // [!unload wow64exts] 卸载wow64exts.dll模块

.effmach  // 查看当前调试mode:x86、x64等

.effmach x86 // 切换到x86栈环境  注:需要先执行.load wow64exts来加载wow64exts.dll模块

.effmach . // 切换回x64

!sw  // [!wow64exts.sw]  在多个mode:x86、x64上进行循环切换  注:如果win32程序在x64的mode下,会看到地址是64位的

!k  // [!wow64exts.k]  打印32位、64位堆栈

!k 5 // [!wow64exts.k 5]  打印32位、64位堆栈,栈帧个数为5

!info // [!wow64exts.info]  输出wow64相关的PEB、TEB和TLS基本信息

!r // [!wow64exts.r]  输出处理器当前上下文信息

!r dumpTest!main  // [!wow64exts.r dumpTest!main]  输出main函数地址的上下文信息

 -- 32位windbg无法打开64位应用程序,会提示如下错误:

 -- 32位windbg无法attach上64位应用程序,会提示如下错误:

 

#符号加载与查看

除了使用ld和.reload命令直接加载符号文件,某些使用符号的命令也可以触发调试器来加载符号,如:栈回溯命令(k*)和反汇编命令(u)等。

值得说明的是,windbg缺省使用的是懒惰式符号加载策略,当它收到模块加载事件时,它通常是不会加载符号的,符号状态显示为deferred(延迟加载)。

.symopt // 显示当前所有符号选项

.symopt+ flags // 添加符号选项

.symopt- flags // 删除符号选项

!sym noisy   // 激活详细符号加载(noisy symbol loading)显示

!sym quiet   // 禁止详细符号加载显示

ld * // 为所有模块加载符号

ld kernel32 // 加载kernel32.dll的符号

.reload // 为所有已加载模块载入符号信息

.reload /i // 重新加载不匹配符号的模块【dmp文件没有对应的pdb时使用

.reload /i TGame.exe // 重新加载不匹配符号的TGame.exe

.reload /f /v // f:强制立即模式(不允许延迟载入)  v:详细模式

.reload /f @"c:\\windows\\System32\\verifier.dll" // 为指定模块加载符号信息

.reload /f TGame.exe // 为TGame.exe加载符号信息

.reload /u TGame.exe // 卸载TGame.exe及其载符号信息

x *! // 列出所有模块对应的符号信息

lm // 列出所有模块(加载和未加载)对应的符号信息

lmv // 列出所有模块(加载和未加载)对应的符号信息

lmvm ntdll  // 查看ntdll.dll的详细信息(注意exe、dll等都不要带后缀名)

!lmi ntdll  // 查看ntdll.dll的详细信息(注意exe、dll等都不要带后缀名)

!dlls -l  // 按照加载顺序(默认项)列出所有加载的模块

!dlls -i  // 按初始化顺序列出所有加载的模块

!dlls -v -c ntdll  // 查看ntdll.dll的详细信息(注意exe、dll等都不要带后缀名)

ln 0x65777588  // 查看地址0x65777588处或附近的符号信息

x ConsoleTest!* // 列出ConsoleTest模块中的所有符号

x ConsoleTest!add* // 列出ConsoleTest模块中的所有add开头的符号

x /t /v ConsoleTest!* // 带数据类型、符号类型和大小信息,列出ConsoleTest模块中的所有符号

x kernel32!*LoadLib* // 列出kernel32模块中所有含LoadLib字样的符号

!itoldyouso mono D:\\mySymbols\\mono.pdb  // 查看mono.dll与D:\\mySymbols\\mono.pdb符号是否匹配上

0:000> !itoldyouso mono D:\\mySymbols\\mono.pdb

mono.dll
Timestamp: 559AAA60
SizeOfImage: 230000
pdb: C:\\buildslave\\mono-runtime-and-classlibs\\build\\builds\\embedruntimes\\win32\\mono.pdb
pdb sig: 728334C1-72C3-4A51-B310-C44087FC4B2E
age: 1

mono.pdb
pdb sig: 728334C1-72C3-4A51-B310-C44087FC4B2E
age: 1

MATCH: mono.pdb and mono.dll

-------------------------------------------------------------------------

使用windbg提供的symchk.exe工具来查找模块的pdb

symchk.exe Paladins.exe /v /s .\\  //在当前目录查找Paladins.exe的pdb,/s后面指定搜索路径  带上/v会输出详细的log

如果匹配上,会显示如下log:

[SYMCHK] [ 0x00000000 - 0x001f0001 ] Checked "G:\\TGame\\symbols\\ClientPackaging\\Paladins.exe"

SYMCHK: FAILED files = 0
SYMCHK: PASSED + IGNORED files = 1

没有匹配上,则显示log为:

SYMCHK: Paladins.exe         FAILED  - ShippingPC-ChaosGameTencent.pdb mismatched or not found

SYMCHK: FAILED files = 1
SYMCHK: PASSED + IGNORED files = 0

 

#进程

|   // 列出调试进程

|*  // 列出调试进程

|N  // 参看序数为N的调试进程

|Ns // 切换序数为N的进程为当前调试进程

!dml_proc  // 显示当前进程信息 

#线程

~   // 列出线程

~*  // 所有线程

~* k // 所有线程堆栈信息

~* r // 所有线程寄存器信息

~.  // 查看当前线程

~0s // 查看主线程

~# // 查看导致当前事件或异常的线程

~N  // 查看序数为N的线程

~~[n]  // 查看线程ID为n的线程  n为16进制

~Ns   // 切换序数为N的线程为当前调试线程

~~[n]s  // 切换线程ID为n的线程为当前调试线程  n为16进制

~N f  // 冻结序数为N的线程

~N u // 解冻序数为N的线程

~N n  // Suspend序数为N的线程

~N m // Resume序数为N的线程

~* e !gle // 显示所有线程最后的一个错误信息  e后可以为任意windbg命令

.ttime  // 查看当前线程时间信息

!runaway  //显示当前进程的所有线程用户态时间信息

!runaway f  //显示当前进程的所有线程用户态、内核态、存活时间信息

!locks // 显示死锁

!cs  // 列出CriticalSection(临界段)的详细信息

 

#断点

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 MyDll+0x1032  // 在模块MyDll.dll偏移0x1032处放置一个断点

bp `ConsoleTest.cpp:36`  // 在ConsoleTest.cpp的36行处放置一个断点

bp main // 在main函数的起始处放置一个断点

bp @$exentry  // 在进程的入口放置一个断点

bp CSecondLoader::CSecondLoader  // 在CSecondLoader的构造函数处放置一个断点

bp TestCommon! CTest::add  // 在TestCommon.dll的Test.cpp文件的CTest::add()函数起始处放置一个断点

bp `ConsoleTest.cpp:40` ".if (poi(pVar)>5) {}; {g}" // ".if (Condition) {Optional Commands}; {g}"    条件断点 pVar指针指向的值>5,执行空语句;),断住  否则继续执行

bp `ConsoleTest.cpp:40` "j (poi(pVar)>5) \' \'\'g\'" // "j (Condition) \'Optional Commands\'; \'g\'"    j为条件表示式:条件断点 pVar指针指向的值>5,执行空语句;,断住  否则继续执行

注:Condition表达式语法默认的是MASM表达式语法。使用复杂C++表达式时我们需要用@@c++()将表达式包围住;如:"j @@c++(*pVar>5) \' \'; \'g\'"

---------------------------------

x表示的一个地址
hi(x) 高16 bits
low(x) 低16 bits
by(x) 返回第一个byte
wo(x) 返回第一个word
dwo(x) 返回第一个dword
qwo(x) 返回第一个4 word(Quad-word)
poi(x) 返回第一个指针所指向的值

---------------------------------

bp `ConsoleTest.cpp:40` "j @eax = 0xa3 \'\'; \'g\'" // j为条件表示式:条件断点 寄存器eax的值为0xa3时断住

bp kernel32!CreateFileA  // 在系统API的CreateFileA函数处放置一个断点

bp kernel32!CreateFileA ".echo;.printf\\"CreateFileA(%ma,%p,%p), ret=\\",poi(esp+4),dwo(esp+8),dwo(esp+c);gu;.printf\\"%N\\",eax;.echo;g" // 不断住进程情况下,打印所有的CreateFileA调用

bp kernel32!CreateFileW ".echo;.printf\\"CreateFileW(%mu,%p,%p), ret=\\",poi(esp+4),dwo(esp+8),dwo(esp+c);kn;g;"  // 不断住进程,打印所有的CreateFileW调用及堆栈信息

bp advapi32!RegOpenKeyExA ".echo;.printf\\"RegOpenKeyExW(%p,\\\\\\"%ma\\\\\\",%N,%N,%p) returned: \\", dwo(esp+4), poi(esp+8), dwo(esp+c), dwo(esp+10), dwo(esp+14);gu;.printf\\"%N\\",eax;.echo;g"  // 不断住进程情况下,打印所有的RegOpenKeyExA调用(打开注册表键值)

---------------------------------

注意:有些函数Symbol Name与导出函数名可能不一致,例如SetWindowPos,这时可以用Dependency查看相应的导出函数地址(Entry Point列):0x00018E5E,然后在windbg菜单“Debug”—〉“Modules...”对话框中获得user32.dll模块起始地址0x77d10000,在两个值相加后的绝对地址处直接设置断点:bp 77d28E5E;也可以通过x user32!*命令列出全部Symbols列表,查找77d28E5E,找到SetWindowPos对应的Symbol Name为“NtUserSetWindowPos”,然后通过符号设置断点:bp user32!NtUserSetWindowPos。通过符号设置断点的好处是当dll代码改变时,不需要修改,windbg会根据符号来自动匹配函数地址。

---------------------------------

bu  // 保存断点,其用法和bp一样

bm add_*  // 匹配add_开头的函数,并在这些函数起始处都打上断点

ba w4 0x0483dfe0 // 当对0483dfe0地址写操作时停下,前面要带上0x,否则会报错

                          // ba [r|w|e] [Size] Addr      [r=read/write, w=write, e=execute], Size=[1|2|4 bytes]

windbg无参脚本

// 当CreateFileW读取UnityLockfile文件时断住进程,在命令输入框输入:$$><d:\\CreateFileWNoArguScript.txt,CreateFileWNoArguScript.txt内容如下:

复制代码
bp kernel32!CreateFileW "
r $t1=poi(esp+4)
as /mu $FileName $t1
.echo
.printf\\"File:%mu\\",$t1
.echo
.block
{
.if($spat(\\"${$FileName}\\",\\"*UnityLockfile\\")) 
{
  .echo \'find...\';
  ad ${/v:$FileName}
}
.else 
{
  .echo no find...
  ad ${/v:$FileName}
  gc
}
}"
复制代码

windbg有参脚本

// 当CreateFileW读取mscorlib.dll文件时断住进程,在命令输入框输入:$$>a<d:\\CreateFileWArguScript.txt mscorlib.dll,CreateFileWArguScript.txt内容如下:

复制代码
bp kernel32!CreateFileW "
r $t1=poi(esp+4)
as /mu $FileName $t1
.echo
.printf\\"File:%mu\\",$t1
.echo
.block
{
.if($spat(\\"${$FileName}\\",\\"*${$arg1}\\")) 
{
  .echo \'find...\';
  ad ${/v:$FileName}
}
.else 
{
  .echo no find...
  ad ${/v:$FileName}
  gc
}
}"
复制代码

 

#调试执行控制

g  // Go(F5)

gH // 执行gH命令强制让调试器返回已经处理了这个异常。【Go with Exception Handled

     // 系统收到这个回复后会停止分发异常(因为调试器声称已经处理了异常),恢复调试目标继续执行,

     //  但由于异常条件仍在,所以还会产生异常,于是再次分发,WinDBG再次中断到命令模式。

gN // 【Go with Exception Not Handled

     // 执行gN命令强制让调试器返回没有处理了这个异常,那么系统会进一步分发该异常,

     // 如果没有其他调试器也不处理,最后系统会弹出程序终止对话框。

VSCode自定义代码片段4——cli的终端命令大全

Windbg入门

WinDbg扩展

Windbg调试命令汇总

WinDbg命令窗口的使用

Windbg调试命令详解