windbg 常用调试命令总结
windbg 是 Microsoft 公司免费调试器调试集合中的 GUI 的调试器,支持 Source 和 Assembly 两种模式的调试。Windbg 不仅可以调试应用程序,还可以进行 Kernel Debug。结合 Microsoft 的 Symbol Server,可以获取系统符号文件,便于应用程序和内核的调试。Windbg 支持的平台包括 X86、IA64、AMD64。
那么在我们使用 windbg 的时候,虽然命令纷繁复杂,但是有一些常用的命令是我们需要掌握的,熟练的运用这些命令能给我们调试带来事半功倍的效果,因此我对常用命令进行了一个总结,方便查找。
至于其他更为复杂命令使用,我们可以通过查看官方提供的 windbg 命令手册:
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debuggercmds/commands
1.流程控制相关命令
g // Go 让程序跑起来
p // 单步步进(F10)
p 2 // 单步步进2次
pa 0x7c801b0b // 单步布进执行到 7c801b0b 地址处停下
pc // 单步步进执行到下一个函数调用处停下
q // 结束调试会话
.reboot // 重启调试系统
2.内存读写相关命令
db // 按字节显示(1字节)
dw // 按单字显示(2字节)
dd // 按双字显示(4字节)
dq // 按四字显示(8字节)
da // 按 ASCll 字符显示(1字节)
du // 按 UNICODE 字节显示(2字节)
df // 按单精度浮点数显示(4字节)
dD // 按双精度浮点数显示(8字节)
eb // 按字节写入(1字节)
ew // 按单字写入(2字节)
ed // 按双字写入(4字节)
eq // 按四字写入(8字节)
ea // 按 ASCll 字符写入(1字节,不会自动在结尾填充 '\0' 字符)
eu // 按 UNICODE 字符写入(2字节,不会自动在结尾填充 '\0' 字符)
ef // 按单精度浮点数写入(4字节)
eD // 按双精度浮点数写入(8字节)
eza // 按 ASCll 字符写入(1字节,会自动在结尾填充 '\0' 字符)
ezu // 按 UNICODE 字符写入(2字节,会自动在结尾填充 '\0' 字符)
!db // 将物理地址按字节显示(1字节),其他内存操作命令同理
dds // 按双字(4字节)显示给定范围内的内存内容(此内存被假定为符号表中的一系列地址,相应的符号也会显示)
dqs // 按四字(8字节)显示给定范围内的内存内容(此内存被假定为符号表中的一系列地址,相应的符号也会显示)
dt _eprocess // 查看 EPROCESS 结构体成员
dt _eprocess 0x510 // 从地址 0x510 处按照结构体 EPROCESS 对数据进行解析
dt ntdll!* // 显示ntdll里的所有类型信息
dt ntdll!_peb* // *是通配符;显示 ntdll 模块中所有peb打头的结构体名称;
r // 显示所有寄存器信息及发生 core 所在的指令
r eax, gdtr // 显示eax,gdtr寄存器信息
r eax=5, edx=6 // 对寄存器eax赋值为5,edx赋值为6
3.内存搜索相关命令
可以指定的查找模式有:
-b // 字节(8位)
-w // WORD(16位)
-d // DWORD(32位)
-q // QWORD(64位)
s -b fffff801`87b58a70 L100 cc c2 // 从地址处往后100个字节里查找字节序列为 cc c2 的地址
s -b fffff801`87b58a70 L-100 cc c2 // 从地址处往前查找
s -b fffff801`87b58a70 L100 'k' 'k' // 查找字节序列的 ascall 码为 k k 的地址
s -d fffff801`87b58a70 L100 'H' // 按照双字查找 ascall 码为 H 的地址,结果如下:
(fffff801`87b58a70 00000048 00000000 500c0163 00000000 H.......c..P....)
s -a fffff801`87b58a70 L100 "ntdll" // 查找 ascall 字符串为 "ntdll" 的地址,结果如下:
(fffff801`87b58a70 6e 74 64 6c 6c 5c 6c 64-72 69 6e 69 74 2e 63 00 ntdll\ldrinit.c.)
4.断点相关命令
bp main // 在main函数开头设置一个断点
bp 0x7c801b00 // 在7c801b00地址处放置一个断点
bu 0x7c801b00 // 未解析的断点
ba i4 3f8 //处理器断点(硬件断点,访问该地址数据时断下,该命令在所有串行端口上添加一个断点,其中包含从 0x3F8 到 0x3FB 的地址)
bl // 列出所有断点
bc * // 清除所有断点
be * // 启用所有断点
bd * // 禁用所有断点
bc 1 2 5 // 清除1号、2号、5号断点,其他命令同理
5.反汇编相关命令
u // 反汇编当前 eip 寄存器地址的后8条指令
u main.exe+0x10 L20 // 反汇编 main.exe+0x10 地址后20条指令
ub 000c135d L20 // 查看地址为000c135d指令前的20条指令内容
uf NtOpenProcess // 反汇编 NtOpenProcess 函数
uf demo::add // 反汇编demo类的add函数
6.堆栈相关命令
k // 显示当前调用堆栈
kn // 带栈编号显示当前调用堆栈
kb // 打印出前3个函数参数的当前调用堆栈
kb 5 // 只显示最上的5层调用堆栈
kv // 在kb的基础上增加了函数调用约定、FPO等信息
kp // 显示每一层函数调用的完整参数,包括参数类型、名字、取值
kd // 打印堆栈的地址
.frame // 显示当前栈帧
.frame n // 显示编号为n的栈帧(n为16进制数)
.frame /r n // 显示编号n的栈帧(n为16进制数) 并显示寄存器变量
.frame /c n // 设置编号n的栈帧为当前栈帧(n为16进制数)
7.进程相关命令
!process -1 1 // 查看当前进程信息
!process 0n<进程PID> 0(e.g. !process 0n4 0) // 获取 PID 为 4 的进程信息
!process 0 0 <进程名>(e.g. !process 0 0 x64.exe) // 获取进程名为 x64 的进程信息
.process /p /i <进程eprocess> // 切换到目标进程的上下文
8.模块相关命令
lm // 列出所有模块对应的符号信息
ld * // 为所有模块加载符号
ld kernel32 // 加载 kernel32.dll 的符号
9.符号相关命令
.sympath // 查看当前符号查找路径
.sympath c:\symbols // 将符号查找路径设为:c:\symbols
.sympath+ c:\symbols // 将c:\symbols添加到符号查找路径集合中
.reload // 为所有已加载模块载入符号信息
.reload /f /v // f:强制立即模式(不允许延迟载入) v:详细模式
.reload /f @"c:\windows\System32\verifier.dll" // 为指定模块加载符号信息
10.其他常用命令
ed kd_default_mask 0xffffffff // 设置在 windbg 上输出调试信息