Windows软件调试初探-WinDBG命令入门
Windows软件调试初探-WinDBG命令入门
碎碎念
标准命令有:
- 控制调试目标执行,包括回复运行
g、跟踪执行t、单步执行p、追踪监视wt。 - 观察和修改通用寄存器
r,读写MSRrdmsr/wrmsr,设置寄存器显示掩码rm。 - 读写I/O端口
ib/iw/id、ob/ow/od。 - 观察、编辑和搜索内存数据的
d系列、e系列、s系列。观察栈k系列。 - 设置和维护断点
bp/ba,管理断点bl/bc/bd/be。 - 显示和控制线程
~,显示进程|。 - 评估表达式
?,评估C++表达式??。 - 汇编与反汇编
a/u。 - 显示段选择子
dg。 - 执行命令文件
$。 - 设置调试事件处理方式
sx系列,启用/禁止静默模式sq,设置内核选项so,设置符号后缀ss。 - 显示调试器和调试目标版本
version,显示调试目标所在系统信息vertarget。 - 检查符号
x。 - 控制和显示源程序
ls系列。 - 加载调试符号
ld,搜索相邻符号ln,显示模块列表lm。 - 结束调试会话
q,结束远程调试qq,结束调试会话并分离调试目标qd。 - 标准命令帮助
?。
元命令以点开始,有:
- 显示和设置调试会话的调试器选项,如符号选项
.symopt、符号路径.sympath/.symfix、源程序文件.srcpath/.srcnoise/.srcfix、扩展命令模块路径.extpath、匹配扩展命令.extmatch、可执行文件.exepath、反汇编选项.asm、控制表达式评估其.expr等。 - 控制调试会话或调试目标,如重新开始调试会话
.restart、放弃用户态调试目标进程.abandon、创建新进程.create、附加到存在进程.attach、打开转储文件.opendump,分离调试目标.detach、终止进程.kill等。 - 管理扩展命令模块,如加载模块
.load、卸载.unload/.unloadall、显示已加载模块.chain等。 - 管理调试器日志文件,如显示信息
.logfile、打开.logopen、追加.logappend、关闭.logclose。 - 远程调试,如启动服务
.remote、启动调试引擎服务器.server、列出可用服务器.servers、向远程服务器发送文件.send_file、结束远程进程服务器.endpsrv、结束引擎服务器.endsrv。 - 控制调试器,如调试器睡眠
.sleep、唤醒调试器.wake、启动另一个调试器来调试当前调试器.dbgdbg。 - 编写命令程序,如
.if/.else/.elsif/.foreach/.do/.while/.continue/.catch/.break/.continue/.leave/.printf/.block等。 - 显示或转储调试目标数据,如产生转储文件
.dump、原始内存数据写文件.writemem、显示调试会话时间.time、显示线程时间.ttime、显示任务列表.tlist、以不同格式显示数字.formats。 - 元命令帮助
.help。
扩展命令结构!扩展模块名.扩展命令名 参数。加载扩展模块用命令.load 扩展模块或.loadby 扩展模块 已加载程序模块,用.chain列出当前加载的所有扩展模块,用.unload/.unloadall卸载扩展模块,用!扩展模块.help显示某扩展模块的扩展命令。
对于用户态目标,命令提示符格式为“系统序号:进程序号:线程序号”,所有序号从0开始。对于双机内核调试的内核态目标或内核转储文件目标,为“系统序号:处理器序号:kd”。对于本地内核态调试,为“系统序号:处理器序号:lkd”。
直接按回车则重复上一条命令,用Ctrl+Alt+V开启详细输出模式。大部分命令不区分大小写,有些命令的选项区分大小写。默认使用十六进制,可用0x/h、0n、0y来指定十六进制、十进制、二进制等。
串行执行多个命令用分号隔开,注释用$$时到分号结束,用*时整行都被当作注释。
伪寄存器
伪寄存器PR,解析命令时WinDBG调试引擎自动展开:
| 伪寄存器 | 描述 |
|---|---|
$ea |
上一条指令中有效地址 |
$ea2 |
上一条指令中第二个有效地址 |
$exp |
表达式评估器评估的上一条表达式 |
$ra |
当前函数返回地址,如g @$ra与gu效果相同 |
$ip |
指令指针寄存器 |
$eventip |
当前调试事件发生时的指令指针 |
$previp |
上一事件的指令指针 |
$relip |
与当前事件关联的指令指针 |
$scopeip |
当前上下文指令指针 |
$exentry |
当前进程入口地址 |
$retreg |
首要函数返回值寄存器 |
$retreg64 |
同上x64 |
$csp |
帧指针 |
$p |
上一个内存显示d系列命令所打印的第一个值 |
$proc |
当前进程PROCESS结构地址 |
$thread |
当前进程ETHREAD结构地址 |
$peb |
当前进程PEB地址 |
$teb |
当前线程TEB地址 |
$tpid |
拥有当前线程的PID |
$tid |
当前线程ID |
$bpx |
x号断点地址 |
$frame |
当前栈帧序号 |
$dbgtime |
当前时间 |
$callret |
用.call命令调用的上一个函数的返回值,或用.fnret命令设置的返回值 |
$ptrsize |
调试目标所在系统的指针类型宽度 |
$pagesize |
调试目标所在系统的内存页字节数 |
使用方法:
1 | 0:000> ln @$exentry *搜索距离指定地址最近的符号 |
别名
WinDBG自动定义的别名有:
| 别名 | 含义 |
|---|---|
$ntnsym |
NT内核或NTDLL符号名 |
$ntwsym |
64位系统上调试32位目标时NT系统DLL符号名 |
$ntsym |
与当前调试目标的机器模式匹配的NT模块名称 |
$CurrentDumpFile |
转储文件名称 |
$CurrentDumpPath |
转储文件路径 |
$CurrentDumpArchiveFile |
最近加载的CAB文件名称 |
$CurrentDumpArchivePath |
最近加载的CAB文件路径 |
例如:
1 | 0:000> .echo $ntnsym |
上下文
1 | !session |
符号
1 | lm v *详细模块列表 |
未完待续。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 The Blog of Monoceros406!