Windows调试技巧:从Hello到I Love C++

代码

#include <windows.h>

int wWinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow){

MessageBox(NULL, L"hello",L"hello word",MB_ICONINFORMATION | MB_CANCELTRYCONTINUE );

return 0;

}

Xdbg

找到helloword

转内存地址7FF66BF89BC8这个位置

修改字符串(编辑)

进行调试按下f9(继续执行)

完成

Xdbg快捷键

调试控制

  1. F2 :开始/停止调试·
  2. F3 :单步执行
  3. F7 :进入函数调用
  4. F8 :跳过函数调用
  5. F9 :继续执行
  6. F12 :暂停/继续执行

断点

  1. F5 :添加/删除断点
  2. ctrl + F5 :添加/删除硬件断点
  3. F6 :添加/删除条件断点
  4. F9 :启用/禁用断点
  5. ctrl + F9 :启用/禁用所有断点

寄存器

  1. CtrI + R: 打开/关闭寄存器窗囗
  2. ctrl + G :蜀啭到指定地址
  3. F2/F4/F6 :在寄存器窗囗中修改寄存器的值

内存·

  1. CtrI + M :打开/关闭内存窗囗·
  2. ctrl + E :打开/关闭表达式窗口·
  3. CtrI + F: 查找指定字节序列
  4. CtrI + Shift + F :查找指定指令序列
  5. ctrl + D :将内存中的数据以十六进制形式导出到文件中

动态分析·

  1. 打开/关闭汇编窗囗· Ctrl + A
  2. 打开/关闭堆栈窗囗· Ctrl + B
  3. 打开/关闭 CPU 窗口· Ctrl + C
  4. 打开/关闭日志窗囗· Ctrl + L

其他

  1. CtrI + F2 :打开/关闭工具栏
  2. CtrI + F10 :打开/关闭菜单栏
  3. CtrI + Q: 退出× 64dbg

Windbg

输入命令u显示反汇编代码

@$exentry是执行入口代码

默认是入口

逆一下winmain

uf WinMain

发现disassembly不正确

分析代码找到helloword地址(0x140009bc8)

修改数据

eza 0x140009bc8 "i love c/c++!"

并且查看

运行就可以

一定要记得.create

成功

Windbg快捷键

https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debuggercmds/commands

流程控制相关命令

  1. g // Go 让程序跑起来

  2. p // 单步步进(F10)

  3. p 2 // 单步步进2次

  4. pa 0x7c801b0b // 单步布进执行到 7c801b0b 地址处停下

  5. pc // 单步步进执行到下一个函数调用处停下

  6. q // 结束调试会话(会结束进程,但不会退出 windbg)

  7. qd // 脱离调试会话(不会结束进程,也不会退出 windbg)

  8. .restart // 重启目标进程

  9. .reboot // 重启调试系统(内核调试中使用)

内存读写相关命令

  1. db // 按字节显示(1字节)

  2. dw // 按单字显示(2字节)

  3. dd // 按双字显示(4字节)

  4. dq // 按四字显示(8字节)

  5. da // 按 ASCll 字符显示(1字节)

  6. du // 按 UNICODE 字节显示(2字节)

  7. df // 按单精度浮点数显示(4字节)

  8. dD // 按双精度浮点数显示(8字节)

  9. eb // 按字节写入(1字节)

  10. ew // 按单字写入(2字节)

  11. ed // 按双字写入(4字节)

  12. eq // 按四字写入(8字节)

  13. ea // 按 ASCll 字符写入(1字节,不会自动在结尾填充 '\0' 字符)

  14. eu // 按 UNICODE 字符写入(2字节,不会自动在结尾填充 '\0' 字符)

  15. ef // 按单精度浮点数写入(4字节)

  16. eD // 按双精度浮点数写入(8字节)

  17. eza // 按 ASCll 字符写入(1字节,会自动在结尾填充 '\0' 字符)

  18. ezu // 按 UNICODE 字符写入(2字节,会自动在结尾填充 '\0' 字符)

  19. !db // 将物理地址按字节显示(1字节),其他内存操作命令同理

  20. dds // 按双字(4字节)显示给定范围内的内存内容(此内存被假定为符号表中的一系列地址,相应的符号也会显示)

  21. dqs // 按四字(8字节)显示给定范围内的内存内容(此内存被假定为符号表中的一系列地址,相应的符号也会显示)

  22. dt _eprocess // 查看 EPROCESS 结构体成员

  23. dt _eprocess 0x510 // 从地址 0x510 处按照结构体 EPROCESS 对数据进行解析

  24. dt ntdll!* // 显示ntdll里的所有类型信息

  25. dt ntdll!_peb* // *是通配符;显示 ntdll 模块中所有peb打头的结构体名称;

  26. r // 显示所有寄存器信息及发生 core 所在的指令

  27. r eax, gdtr // 显示eax,gdtr寄存器信息

  28. r eax=5, edx=6 // 对寄存器eax赋值为5,edx赋值为6

  29. !pte 0x80b99000 // 查看当前进程(一般为系统进程)中虚拟地址的页表和页目录信息

  30. !vtop 33a3f000 0x80b99000 // 查看指定页目录基址(cr3)中虚拟地址的页表和页目录信息

内存搜索相关命令

可以指定的查找模式有:

-b // 字节(8位)

-w // WORD(16位)

-d // DWORD(32位)

-q // QWORD(64位)

  1. s -b fffff801`87b58a70 L100 cc c2 // 从地址处往后100个字节里查找字节序列为 cc c2 的地址

  2. s -b fffff801`87b58a70 L-100 cc c2 // 从地址处往前查找

  3. s -b fffff801`87b58a70 L100 'k' 'k' // 查找字节序列的 ascall 码为 k k 的地址

  4. s -d fffff801`87b58a70 L100 'H' // 按照双字查找 ascall 码为 H 的地址,结果如下:

(fffff801`87b58a70 00000048 00000000 500c0163 00000000 H.......c..P....)

  1. 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.)

断点相关命令

硬件断点(ba) :break on access,又称为处理器断点、数据访问断点

参数:

  • e(执行):当 CPU 从指定地址检索指令时,会中断到调试器(和软件断点类似,但不需要向目标代码插入断点指令)。
  • r(读取/写入):当 CPU 读取或写入指定地址时,中断到调试器。
  • w(写入):当 CPU 写入指定地址时,中断到调试器。
  • i(I/O):(仅内核模式,仅基于 x86 的系统)访问指定地址处的 I/O 端口时,中断到调试器。
  1. ba r4 0x00401200 // r4 表示在对指定地址开始的 4 字节内存区进行读写操作时中断
  2. ba w4 0x00401200 // w4 表示在对指定地址开始的 4 字节内存区进行写操作时中断
  3. ba i4 0x3f8 // 访问该地址数据时断下,该命令在所有串行端口上添加一个断点,其中包含从 0x3F8 到 0x3FB 的地址
软件断点(bp, bu, bm):
  1. bp(设置软件断点):在指定地址处设置一个断点。如果调试器在设置断点时无法解析断点的地址表达式,则 bp 断点将自动转换为 bu 断点,且使用 bp 命令创建的断点在模块卸载后不再处于活动状态。
  2. bu(设置未解析的断点):在指定地址设置延迟或未解析的断点。bu 命令是在断点地址的符号引用上设置的,并在解析具有引用的模块时激活。
  3. bp main // 在 main 函数开头设置一个软件断点
  4. bp 0x7c801b00 // 在 7c801b00 地址处放置一个软件断点
  5. bp /p EProcess //(仅内核模式)对 EProcess 所对应的进程设置软件断点(其中所有线程都会设置)
  6. bp /t EThread //(仅内核模式)对 EThread 所对应的线程设置软件断点
  7. bu 0x7c801b00 // 设置一个未解析的断点
其他断点命令:
  1. bl // 列出所有断点
  2. bc * // 清除所有断点
  3. be * // 启用所有断点
  4. bd * // 禁用所有断点
  5. bc 1 2 5 // 清除1号、2号、5号断点,其他命令同理

反汇编相关命令

  1. u // 反汇编当前 eip 寄存器地址的后8条指令
  2. u main.exe+0x10 L20 // 反汇编 main.exe+0x10 地址后20条指令
  3. ub 000c135d L20 // 查看地址为000c135d指令前的20条指令内容
  4. uf NtOpenProcess // 反汇编 NtOpenProcess 函数
  5. uf demo::add // 反汇编demo类的add函数

堆栈相关命令

  1. k // 显示当前调用堆栈

  2. kn // 带栈编号显示当前调用堆栈

  3. kb // 打印出前3个函数参数的当前调用堆栈

  4. kb 5 // 只显示最上的5层调用堆栈

  5. kv // 在kb的基础上增加了函数调用约定、FPO等信息

  6. kp // 显示每一层函数调用的完整参数,包括参数类型、名字、取值

  7. kd // 打印堆栈的地址

  8. .frame // 显示当前栈帧

  9. .frame n // 显示编号为n的栈帧(n为16进制数)

  10. .frame /r n // 显示编号n的栈帧(n为16进制数) 并显示寄存器变量

  11. .frame /c n // 设置编号n的栈帧为当前栈帧(n为16进制数)

  12. dv // 显示当前栈帧的参数和局部变量

进程线程相关命令

  1. !process -1 1 // 查看当前进程信息
  2. !process 0n<进程PID> 0(e.g. !process 0n4 0) // 获取 PID 为 4 的进程信息
  3. !process 0 0 <进程名>(e.g. !process 0 0 x64.exe) // 获取进程名为 x64 的进程信息
  4. !process 86a7d030 // 显示 EPROCESS 结构地址为 0x86a7d030 的进程关键信息(包括所有线程)
  5. !peb // 显示当前进程的 peb 详细信息
  6. !peb 7ffdf000 // 显示当前进程中位于 0x7ffdf000 处的 PEB 结构(先用 .process 命令切换到目标进程)
  7. !Token e24d8510 // 查看当前进程中位于 0xe24d8510 处的 Token 结构(包含进程的很多与安全有关的信息)
  8. .context // 显示用户态当前进程的上下文/页目录基址(物理地址)
  9. .process // 显示当前进程 EPROCESS
  10. .process /p /i <进程eprocess> // 切换到目标进程的上下文
  11. .process /p /r <进程eprocess> // 切换到目标进程的上下文后重新加载用户模式符号(/r 与 .reload /user 效果相同)
  12. .thread // 显示当前的线程 ETHREAD
  13. .thread 84018d78 // 切换到特定的线程上下文

模块相关命令

  1. lm // 列出所有模块对应的符号信息
  2. lm u // (仅内核模式)仅显示用户模式符号信息
  3. lm k // (仅内核模式)仅显示内核模式符号信息
  4. ld * // 为所有模块加载符号(只为当前进程)
  5. ld kernel32 // 加载 kernel32.dll 的符号(只为当前进程)

符号相关命令

  1. .sympath // 查看当前符号查找路径

  2. .sympath c:\symbols // 将符号查找路径设为:c:\symbols

  3. .sympath SRV*C:\ProgramData\dbg\sym*http://msdl.microsoft.com/download/symbols // 指定符号路径为远程服务器

  4. .sympath+ c:\symbols // 将c:\symbols添加到符号查找路径集合中

  5. .reload // 为所有已加载模块载入符号信息(为所有进程)

  6. .reload /f kernel32.dll // 为指定模块加载符号信息(为所有进程)

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

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

其他常用命令

  1. ed kd_default_mask 0xffffffff // 设置在 windbg 上输出调试信息
  2. dg 10(dg cs) // cs=0010,显示一个段选择子所指向的段描述符的详细信息

( P Si Gr Pr Lo

Sel Base Limit Type l ze an es ng Flags


0010 00000000 ffffffff Data RW Ac 0 Bg Pg P Nl 00000c93

  1. !pte //

  2. .formats 10 // 在当前线程和进程的上下文中计算表达式或符号,并将其以多个数字格式显示

Evaluate expression:

Hex: 00000010

Decimal: 16

Octal: 00000000020

Binary: 00000000 00000000 00000000 00010000

Chars: ....

Time: Thu Jan 1 08:00:16 1970

Float: low 2.24208e-044 high 0

Double: 7.90505e-323

  1. ? 0y0000101110 // ? 命令计算并显示表达式的值,0y 表示后面跟着二进制

(Evaluate expression: 46 = 0000002e)

  1. ? 0t123 // 计算八进制

(Evaluate expression: 83 = 00000053)

  1. ? 123 // 计算十进制

(Evaluate expression: 291 = 00000123)

  1. ? 0x4d // 计算十六进制

(Evaluate expression: 77 = 0000004d)

  1. !idt -a // 列出 IDT 中的所有项

  2. !idt 3 // 显示中断向量表中 3 号向量对应的服务例程和地址

  3. .thread // 显示当前线程的 ETHREAD 结构地址

  4. !thread 873e9500 // 以简洁的方式显示 873e9500 地址的 ETHREAD 结构

  5. !teb // 显示当前线程的 TEB 结构地址

  6. !apc // 显示系统中所有进程的所有 APC

  7. !apc proc ffffc10f`8fe5a080 // 显示 EPROCESS 为 ffffc10f`8fe5a080 的进程的所有 APC

  8. !pcr // 获取当前 CPU 的 KPCR 结构地址

  9. dt nt!_KPCR fffff803077dc000 -y IRQL // 获取地址为 fffff803077dc000 的 KPCR 结构中的请求级别

  10. dt ntdll!_Teb 0000003c`99f0e000 -y DbgSsReserved // 以递归方式显示特定地址的 Teb 结构中的 DbgSsReserved 字段

  11. !dpcs // 获取当前 CPU 的 DPC 队列

  12. dt _KDPC 0xffffe009aa42738 // 获取地址为 0xffffe009aa42738 的 DPC 队列

  13. !alpc /lpp ffffc48d86b00640 // 列出 EPROCESS 为 ffffc48d86b00640 的进程的所有 LPC 端口

  14. !alpc /p ffffc48d8895de20 // 观察指定地址 LPC 端口的详情

  15. !alpc /m ffffa480730b6890 // 观察特定 LPC 端口中特定消息的详情

  16. x nt!Dbg* // 查看 nt 模块中以 Dbg 开头的所有函数

  17. !handle 0 // 列出当前进程中所有句柄

  18. !handle 句柄地址 // 查看句柄的类型

  19. !hanlde 0 6 Mutant // 只显示互斥类型的对象

  20. !object 对象地址 // 查看对象类型

  21. ln eip // 列出与 eip 值最近的符号

  22. !address 0013073c // 显示特定地址内存信息

Onlydbg

智能搜索找到了hello world

跳转至

相关推荐
2301_805962933 小时前
ESP32模组烧录失败排查解决方法
单片机·嵌入式硬件
时空自由民.4 小时前
RGB Image Sensor 和 RGB LCD Scren 的HSYNC和VSYNC的区别,以及ESP32 RGB LCD外设工作原理介绍
单片机
RFID舜识物联网4 小时前
耐高温RFID技术如何解决汽车涂装车间管理难题?
大数据·人工智能·嵌入式硬件·物联网·安全·信息与通信
笨笨饿5 小时前
#55_NE595脉冲电路
stm32·单片机·硬件工程
2301_805962935 小时前
ESP32之esptool.py 常用快捷命令
stm32·单片机·嵌入式硬件
NULL指向我5 小时前
TMS320F28379D笔记1:主控-从核双核架构认识
笔记·单片机
sweetone5 小时前
用一个电阻及一段胶带修复 VORWERK (福维克) THERMOMIX(美善品) TM5-1食品料理机 不工作故障
经验分享·单片机·嵌入式硬件
星宇笔记5 小时前
我做了一个本地网页版嵌入式调试工具:支持 Serial / TCP / UDP、实时曲线、HEX 发送
单片机·嵌入式硬件·网络协议·tcp/ip·udp·开源软件
时空自由民.5 小时前
显示屏关键参数
单片机