WinDbg 动态调试(Windows 用户态 + 内核)

SkillDev tools

WinDbg 调试(Windows 用户态+内核)。触发词:WinDbg、windbg、内核调试、kd、!analyze

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the WinDbg 动态调试(Windows 用户态 + 内核) skill

What this skill tells your AI

The instructions your AI receives, as published by dslsdzc/rev-skills in .claude/skills/re-windbg/SKILL.md and read by ahel’s review.

何时使用 / 何时不用

  • 用:Windows 用户态进程调试(启动/附加、断点、单步、寄存器);崩溃/异常分析(!analyze -v);内核调试(双机/VM/本地 kd);驱动与内核模块分析(配合 [[re-kernel]]);崩溃 dump(minidump/full dump)分析
  • 用:时间旅行调试(TTD)——ttd.exe 录制 .run 轨迹后任意回放,适合「复现一次慢慢查」的校验/解密逻辑(见 [[commands]] TTD 节)
  • 不用:Linux 目标(走 [[re-gdb]]);macOS 目标([[re-lldb]]);只需轻量 GUI 调试([[re-x64dbg]] 更快)
  • 不用:只做静态分析/反编译([[re-ida]] / [[re-ghidra]] / [[re-binaryninja]]);无需与运行态互动的纯静态流程不需要调试器
  • 不用:WSL 内跨边界 attach Windows 进程([[re-analyze/platform-tips]] WSL 分支:跨边界走 Windows 侧工具)

工具准备

参考 [[re-analyze/platform-tips]] Windows 分支——attach 需要管理员权限;调试属动态执行,默认沙箱内进行([[re-analyze/platform-tips]] 最高原则)。

WinDbg(微软商店版 / Windows SDK / WDK)

  • 商店版(新 UI WinDbg):winget install Microsoft.WinDbg(或 Microsoft Store 搜索 "WinDbg")
  • 经典版:Windows SDK 安装器勾选 "Debugging Tools for Windows";choco install windbg
  • WDK(含内核调试工具 kd.exe/kdnet.exe):winget install Microsoft.WindowsWDK 或 Visual Studio 安装器勾选 WDK
  • 验证: 打开 WinDbg,File > Open Executable 加载任意 exe 能停在初始断点;命令窗口 ver 输出版本号
  • 版本差异: 商店版(WinDbg 1.x,Chromium UI)与经典版(WinDbg 10.0.x)命令兼容,UI 与附加流程不同;dump 分析两者通用(见 [[gotchas]])

Windows 符号(Windows SDK 符号 / 公共符号服务器)

  • 符号路径: .sympath srv*C:\symbols*https://msdl.microsoft.com/download/symbols(或设环境变量 _NT_SYMBOL_PATH
  • 内核模块符号: 内核调试下 .reload /f nt(强制从符号服务器拉取)
  • 验证: !analyze -v 输出中出现函数名而非 +0x1a 裸偏移

双机/虚拟机内核调试环境

  • 目标机(被调试): bcdedit /debug on + bcdedit /dbgsettings serial debugport:1 baudrate:115200(串口)或 bcdedit /dbgsettings net hostip:<宿主机IP> port:50000 key:<kdnet.exe生成的key>(NET 网卡,Windows 10+ 推荐)
  • VM 场景: VMware/Hyper-V 给目标 VM 添加串口设备(Named Pipe \\.\pipe\com_1 / -vmconnect),宿主 WinDbg File > Kernel Debug > COM 填管道名
  • 本地内核调试(仅测试机,需测试签名): bcdedit /set testsigning on 重启后,WinDbg File > Kernel Debug > Local
  • 验证: 目标机重启停在 "Waiting to reconnect" 或进入调试等待后,宿主 WinDbg 附加成功、gCtrl+Break 能中断、lm 列出模块

TTD(时间旅行调试,Windows 10 1903+)

  • 录制: ttd.exe -out C:\traces target.exe(或 -attach <pid> 附加录制;-monitor <进程名> 监控启动)
  • 打开: WinDbg File > Open.run 轨迹文件(或 Open Trace File
  • 验证: ttd.exe -help 有输出;录一段后用 WinDbg 打开,!tt 能跳到任意位置、g- 能往回跑(详见 [[commands]] TTD 节)

操作步骤

  1. 附加/启动用户态目标

    • 启动: File > Open Executable 选目标 exe,停在初始断点(ntdll 加载完成处)
    • 附加: File > Attach to Process 按 PID/进程名选目标(管理员权限启动 WinDbg 才能附加高权限进程)
    • 命令行: windbg -p <pid> / windbg 目标.exe-g 跳过初始断点直接运行
  2. 断点 / 单步 / 寄存器

    • 符号断点: bp kernel32!CreateFileW;地址断点: bp 0x401000bl 列表、bd/be 禁用/启用、bc * 清空
    • 未加载模块的符号用 bu(unresolved,模块加载后自动绑定)——目标 DLL 按需加载时 bu 是正解
    • 命令断点: bp 地址 "r rax; k; gc"——命中时打印现场后自动继续,日志式观察不打断流程
    • 单步: g 继续、p 步过、t 步入、gu 执行到当前函数返回
    • 寄存器: r 全部、r rax 查看、r eax=0 修改(绕过校验常用)
    • 内存/反汇编: u 0x401000 反汇编、dd/db 读内存、dps rsp 看栈内容
    • 搜索: s -d 0x0 L?10000000 0xdeadbeef(值)、s -a 0x0 L?10000000 "text"(ASCII 串)——找硬编码常量/密钥用
    • 符号搜索: x 模块!*关键字*(如 x kernel32!*Virtual*)——不确定精确符号名时模糊匹配
  3. 异常分析 !analyze -v

    • 目标崩溃停下后: !analyze -v → 读 EXCEPTION_CODEFAULTING_IPSTACK_TEXTPROCESS_NAME
    • 内核蓝屏对应 bugcheck 码(BUGCHECK_CODE,如 0xD1 驱动访问无效内存)——先记码再往下查,常见码含义要能对上故障方向
    • 现场恢复: 从 STACK_TEXTEXCEPTION_RECORD 地址 .exr <addr>(异常记录),再取 CONTEXT 地址 .cxr <addr> 恢复寄存器现场,之后 k 出真实调用栈(栈损坏时唯一可靠的栈回溯方式)
    • dump 现场更简单: 打开 dump 后直接 .ecxr(自动用异常上下文设寄存器现场)→ k——minidump 分析标准开局
    • dump 分析: File > Open Crash Dump 打开 .dmp(用户态用 .dump /ma 生成;内核蓝屏用 %SystemRoot%\Minidump\*.dmp 或完全 dump),同样 !analyze -v 出 bugcheck 码与故障模块
  4. 内核调试(双机 / VM / 本地 kd)

    • 目标机配置见「工具准备」;配置后重启,宿主 File > Kernel Debug 按所用传输(COM/NET)连接
    • VM 管道串口流程: 目标 VM 加串口 Named Pipe → 目标机 bcdedit /dbgsettings serial → 宿主 File > Kernel Debug > COM 填管道名(\\.\pipe\com_1)→ 目标机重启等连
    • 连接后: g 让目标继续跑;Ctrl+Break 随时中断回调试器;!process 0 0 确认会话活着
    • 本地调试: bcdedit /set testsigning on 重启后 File > Kernel Debug > Local(仅测试机,不影响生产机的用法)
  5. 扩展命令

    • !process 0 0(全部进程列表)、!process <EPROCESS> 1(单进程详情+线程);.process /p <EPROCESS> 切到目标进程上下文后再 k/!thread
    • !teb(当前线程 TEB)、!peb(当前进程 PEB——命令行、加载模块、环境块)
    • lm(模块列表,行尾 (deferred)=符号未加载、(no symbols)=无符号)、lmv m <模块>(版本+路径)、lmi <模块>(镜像头)
    • kv(带符号完整栈回溯,驱动分析常用)、!analyze -v 后按 STACK_TEXT 逐帧核对
    • 驱动专项: lmv m 驱动名 拿基址 → .reload /f 驱动名 加载符号 → 深挖转 [[re-kernel]]
  6. TTD 回放(校验/解密逻辑慢查)

    ttd.exe -out C:\traces target.exe     # 录制
    WinDbg 打开 .run → g- / t- / p-       # 往回跑
    !tt 50                                 # 跳到轨迹 50% 处
    !tt 7213:36                            # 跳指定位置(事件序号:步数)
    
    • 断点前移/后移: !tt br 在某寄存器值变化处停;!tt bm 在内存访问处停
    • 首次打开轨迹先 !tt.index 建索引(之后打开跳过);回放中途也可断点 bp(在轨迹上工作)
    • 查询 API: dx @$cursession.TTD.Calls("模块!函数") 统计调用次数/参数(如 ...Calls("ntdll!mem*")
    • TTD 限制: 需管理员运行、用户态专用、轨迹文件很大(数 GB)、回放只读不能写内存(见 [[gotchas]])
  7. 伪寄存器与脚本化(简单自动化)

    • 伪寄存器: r $t0 = 0 起临时变量;$$ > <文件> 把命令输出重定向到文件(如 $$ > c:\log.txt
    • 条件执行: .if (rax==0) { ... } .else { ... }——配合 gc 做断点内逻辑
    • !runaway 看线程 CPU 时间(找忙等/死循环线程);!locks 查锁状态(挂起排查)

跨域联合

  • [[re-binary-core]]:工作流第 6 步 Windows 调试器(用户态+内核)
  • [[re-kernel]]:内核调试与驱动/rootkit 运行时验证固定调用本技能
  • [[re-anti-analysis]]:反调试对抗(内核级检测点)、脱壳后验证
  • [[re-malware]]:恶意样本崩溃 dump 分析与内核组件
  • [[re-cracking]]:授权校验崩溃定位(!analyze -v 快速找崩溃原因)
  • 与 [[re-x64dbg]] 互补:轻量 GUI 断点调试用 x64dbg,内核/异常现场恢复/轨迹回放用 WinDbg

常见坑与陷阱

  • 符号未配置 → 全是裸偏移无函数名:现象——lm 行尾 (no symbols)k 输出 ntdll!+0x1a;原因——符号路径为空或没 _NT_SYMBOL_PATH;对策——.sympath srv*C:\symbols*https://msdl.microsoft.com/download/symbols.reload /f,内核模块同理(先确认符号服务器可达)
  • 内核调试配置错 → 目标机蓝屏死等或连不上:现象——目标机重启后停在 debug 等待或直接进系统未中断;原因——bcdedit 传输类型/端口与宿主不一致,或物理机单机本地调试受限(PatchGuard);对策——用 VM 串口管道最稳(两边都对 \\.\pipe\com_1),bcdedit /dbgsettings 重查配置,物理机场景优先 KDNET
  • 32/64 位命令与寄存器差异:现象——64 位目标下 r eax 改错值、!teb 字段对不上;原因——x64 上下文用 rax/rbx...(低 32 位是 eax 等)、wow64 目标线程栈在 x86 层;对策——先确认目标位数,wow64 场景 .load wow64exts + !wow64exts.sw 切到 x86 上下文
  • 栈损坏时 k 是假象:现象——调用栈乱(地址不像代码);原因——栈指针被破坏/内存踩踏,常规回溯不可信;对策——用 .exr 拿异常记录、.cxr 恢复 CONTEXT 后再 k,必要时 !analyze -vSTACK_TEXT 里直接取现场
  • 蓝屏 dump 打不开:现象——Open Crash Dump 报格式错;原因——minidump 不完整(磁盘满)或用的 32 位 WinDbg 读 64 位 dump;对策——目标机确认内核页交换文件(crash dump 需要 pagefile)足够大,改用同位数 WinDbg
  • RPC 调用统一入口 NdrStubCall3(svchost 功能逆向):现象——要拦/分析某个系统功能(如 Toast 通知),不知道它经什么通道进 svchost;原因——功能实现经 RPC 到 svchost 进程,入口难找;对策——Process Monitor 看目标进程加载 rpcrt4.dll + RpcView 确认 RPC 目标进程;所有 RPC 服务端 stub 统一走 rpcrt4 的 NdrStubCall3(x64;NdrStubCall2 是旧版 x86,ReactOS/Wine 源码可印证)——在其下断 kvn 看调用来源;筛选目标调用:第三参数(r8)指向 RPC_MESSAGE(+0x1C 是 ProcNum 方法编号、+0x28 是接口描述指针 RpcInterfaceInformation → RPC_SERVER_INTERFACE 的 InterfaceId 在 +0x04);opnum 由 MIDL 按方法声明顺序从 0 编号(如 PostNotification3 排第 0x29 位 → opnum=0x29),ObjectStublessClientN 中 rax=N 即 ProcNum;坑:NdrStubCall3 处理 svchost 内所有 RPC 接口,必须按 InterfaceId + ProcNum 双重筛选,只拦目标方法(拦错会把 Edge 等其他功能搞挂)
  • TTD 限制、版本差异与符号服务器细节见 [[gotchas]]

Signals

GitHub stars
57
Forks
8
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
re-windbg
Source
github.com/dslsdzc/rev-skills