windbg调试windows环境搭建
2026-01-19 00:53:14 # Tools

前言

刚开始学习二进制安全,尝试搭建windbg调试vmware的windows7 x86环境,学习一些其中的二进制漏洞。

环境所需

windbg直接下载官网的,windows7的镜像[1]en_windows_7_ultimate_with_sp1_x86_dvd_u_677460.iso,激活windows系统的key为:FJGCP-4DFJD-GJY49-VJBQ7-HYRR2

配置环境

使用vmware安装好windows7 x86。然后参考教程[2],打开”虚拟机设置“ —> ”添加“ —> ”串行端口“,配置好命名的管道,然后确认,启动windows。

命名的管道为:\\.\pipe\windows2007_debug

image-20260118213712022

然后重新启动windows7,输入命令:bcdedit /copy {current} /d "Windows 7 Debug"

image-20260118213156840

输出命令msconfig,切换到 Boot (引导) 选项卡。看到两个启动项(如果你刚才执行了 copy 命令),选中 Windows 7 Debug。点击 Advanced options (高级选项)。勾选 Debug (调试)Debug port 选择 COM1Baud rate 选择 115200。点击 OK,再点击 OK。

系统会提示重启,选择 Exit without restart (稍后重启)

image-20260118213343412

此时到我们自己的电脑上,打开windbg,选择attach to kernel,port位置输入我们的\\.\pipe\windows7_debug,然后点击ok。

image-20260118214937565

此时我们再去配置符号表,symbol path:SRV*D:\pwn\symbols*http://msdl.microsoft.com/download/symbols,我把符号放在了D:\pwn\symbols位置。

image-20260118215031119

此时我们去启动虚拟机的windows7。启动windows7的时候选择“Windows 7 Debug”

image-20260118215612446

windbg成功连接。

image-20260118221221146

查看进程!process 0 0

image-20260118221329542

windbg调试的一些命令

这里以断点notepad.exe的进程为例。

首先是bc *,清空所有断点。然后查看进程!process 0 0,我只截取了部分,我在windows7中是打开了notepad.exe的。

image-20260118232718727

查看notepad.exe的进程,!process 0 0 notepad.exe

image-20260118232944069

可以注意到EPROCESS 地址为86ff55a8.process /i 86ff55a8,告诉windbg聚焦在这个进程上。

image-20260118233213817

加载符号(必做),确保windbg可以看懂notepad调用的函数名。使用.reload /f /user

然后就是专门的断点。

1
bp /p <EPROCESS地址> <函数名>

使用bp /p 86ff55a8 user32!GetMessageWbl是查看有哪些断点。

image-20260118233550528

此时回到windows7,把鼠标移动到记事本的窗口范围内,或者在记事本里随便按一个键盘按键。第一次没断下来,又尝试了一下,才断下来的。

image-20260118233828813

下面就是去看寄存器的内容,执行r

image-20260118234349793

EIP (Instruction Pointer):指令寄存器,它指向下一条要执行的指令地址。攻击者(溢出)的核心目标就是篡改 EIP,让 CPU 去执行恶意代码。

ESP (Stack Pointer): 栈顶指针。它指向当前栈的最上方。函数参数和返回地址都这附近。

EAX: 多功能搬运工。通常用于存放函数的返回值

继续多探究一些命令。

du poi(esp + 4)、du poi(esp + 4)

image-20260118234643165

du命令,d:Display(显示内存)、u:Unicode(宽字节)。

esp + 4:指向第1个参数,因为是32位。

esp + 8:指向第2个参数。

poiPointer指针的缩写,就是取地址里的值。

du poi(esp+4)的意思就是,去 esp + 4 的位置拿到一个指针,跳到那个指针指向的内存,并把它作为 Unicode 字符串打印出来。

下面再去断点其它的函数看一看。

bc *清空断点。断点bp /p 86ff55a8 user32!MessageBoxW,这次断点函数user32!MessageBoxW

image-20260119001015571

然后我windows7,点击notepad的Help -> About Notepad,发现翻车了,并没有断下来。可能是”About Notepad“这个窗口使用的并不是user32!MessageBoxW函数。

经过查询发现使用的是shell32!ShellAboutW函数。这次使用bu断点,bu SHELL32!ShellAboutW,此时点击About Notepad,端下来了。

image-20260119004216960

再查看寄存器的内容。

image-20260119004308422

eu poi(esp+8) "hacker by x2n"编辑寄存器中的内容。eu(edit unicode),可以看到内容已经被修改了。

image-20260119004131707

为什么刚才使用bp没有断下点,使用了bu就可以断下来?

(1)绑定对象的区别

  • bp (Break Point) 绑定的是“虚拟内存地址”
    • 当你输入 bp 0x77123456bp shell32!ShellAboutW 时,调试器会立即解析出该符号当前对应的线性虚拟地址,并记录这个固定的数值。
    • 它不关心这个地址属于哪个模块,它只认这个数值。
  • bu (Break Unresolved) 绑定的是“符号名称”
    • 当你输入 bu shell32!ShellAboutW 时,调试器记录的是字符串 "shell32!ShellAboutW" 以及它在模块内的偏移量。
    • 它不记录具体的绝对地址。

(2)生效机制与时机的区别

  • bp:立即写入 (Immediate Write)
    • 执行命令瞬间,WinDbg 必须能够访问该内存地址。
    • 调试器会尝试立即将该地址处的指令字节修改为 0xCC (INT 3)。
    • 限制:如果此时模块未加载,或当前进程上下文(页表)中该地址未映射,命令会直接失败或写入错误的物理内存。
  • bu:延迟解析 (Deferred Resolution)
    • 执行命令时,不需要模块已加载。
    • WinDbg 会挂钩系统的“模块加载事件”。每当有一个 DLL 或驱动被加载时,调试器会检查其名称是否匹配。
    • 一旦匹配(例如 shell32.dll 被加载),调试器会根据**(当前模块基址 + 函数偏移量)**动态计算出真实地址,然后在那个位置写入 0xCC

(3) 对 ASLR (地址空间布局随机化) 的处理

  • bp:不支持 ASLR
    • 如果是硬编码的地址断点,一旦程序重启,操作系统通过 ASLR 机制将 DLL 加载到了新的基地址,原来的地址(如 0x77123456)可能变成了无效内存或别人的代码。bp 断点因此失效。
  • bu:原生支持 ASLR
    • 当程序重启,DLL 加载到新地址(例如从 0x77000000 变到了 0x66000000),WinDbg 会收到通知,重新计算函数的最新地址,并自动在新的位置下断点。

(4)持久性 (Persistence)

  • bp:通常只在当前调试会话有效。一旦进程终止,该地址关联的断点逻辑即被清除(因为地址已无意义)。
  • bu:保存在调试器的工作区(Workspace)中。即使你关闭调试器再打开,或者重启计算机,只要符号匹配,断点依然存在。
特性 bp (地址断点) bu (符号断点)
核心索引 线性虚拟地址 (Virtual Address) 符号名 (Symbol Name) + 偏移
写入时机 命令执行时立即写入 模块加载时动态写入
内存要求 内存必须存在且可写 无需内存存在
ASLR 兼容 否 (重启后地址变化即失效) 是 (自动跟随基址变化)
适用场景 临时调试特定的指令行、汇编地址 调试 API、系统函数、重启后仍需保留的断点

所以总的来说,对于开启了ASLR的windows7 x86系统,最好还是使用bu最可靠。

参考


  1. https://archive.org/details/en_windows_7_ultimate_with_sp1_x86_dvd_u_677460_202006 ↩︎

  2. https://www.youtube.com/watch?v=yQQLIEM6qp8 ↩︎