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的终端命令大全