executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
re-windbgWinDbg 调试(Windows 用户态+内核)。触发词:WinDbg、windbg、内核调试、kd、!analyze
Independent GitHub snapshot · Automated classification · Original documentation governs
!analyze -v);内核调试(双机/VM/本地 kd);驱动与内核模块分析(配合 [[re-kernel]]);崩溃 dump(minidump/full dump)分析ttd.exe 录制 .run 轨迹后任意回放,适合「复现一次慢慢查」的校验/解密逻辑(见 [[commands]] TTD 节)参考 [[re-analyze/platform-tips]] Windows 分支——attach 需要管理员权限;调试属动态执行,默认沙箱内进行([[re-analyze/platform-tips]] 最高原则)。
winget install Microsoft.WinDbg(或 Microsoft Store 搜索 "WinDbg")choco install windbgwinget install Microsoft.WindowsWDK 或 Visual Studio 安装器勾选 WDKFile > Open Executable 加载任意 exe 能停在初始断点;命令窗口 ver 输出版本号.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+ 推荐)\\.\pipe\com_1 / -vmconnect),宿主 WinDbg File > Kernel Debug > COM 填管道名bcdedit /set testsigning on 重启后,WinDbg File > Kernel Debug > Localg 后 Ctrl+Break 能中断、lm 列出模块ttd.exe -out C:\traces target.exe(或 -attach <pid> 附加录制;-monitor <进程名> 监控启动)File > Open 选 .run 轨迹文件(或 Open Trace File)ttd.exe -help 有输出;录一段后用 WinDbg 打开,!tt 能跳到任意位置、g- 能往回跑(详见 [[commands]] TTD 节)附加/启动用户态目标:
File > Open Executable 选目标 exe,停在初始断点(ntdll 加载完成处)File > Attach to Process 按 PID/进程名选目标(管理员权限启动 WinDbg 才能附加高权限进程)windbg -p <pid> / windbg 目标.exe;-g 跳过初始断点直接运行断点 / 单步 / 寄存器:
bp kernel32!CreateFileW;地址断点: bp 0x401000;bl 列表、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*)——不确定精确符号名时模糊匹配异常分析 !analyze -v:
!analyze -v → 读 EXCEPTION_CODE、FAULTING_IP、STACK_TEXT、PROCESS_NAMEBUGCHECK_CODE,如 0xD1 驱动访问无效内存)——先记码再往下查,常见码含义要能对上故障方向STACK_TEXT 取 EXCEPTION_RECORD 地址 .exr <addr>(异常记录),再取 CONTEXT 地址 .cxr <addr> 恢复寄存器现场,之后 k 出真实调用栈(栈损坏时唯一可靠的栈回溯方式).ecxr(自动用异常上下文设寄存器现场)→ k——minidump 分析标准开局File > Open Crash Dump 打开 .dmp(用户态用 .dump /ma 生成;内核蓝屏用 %SystemRoot%\Minidump\*.dmp 或完全 dump),同样 !analyze -v 出 bugcheck 码与故障模块内核调试(双机 / VM / 本地 kd):
File > Kernel Debug 按所用传输(COM/NET)连接bcdedit /dbgsettings serial → 宿主 File > Kernel Debug > COM 填管道名(\\.\pipe\com_1)→ 目标机重启等连g 让目标继续跑;Ctrl+Break 随时中断回调试器;!process 0 0 确认会话活着bcdedit /set testsigning on 重启后 File > Kernel Debug > Local(仅测试机,不影响生产机的用法)扩展命令:
!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]]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(在轨迹上工作)dx @$cursession.TTD.Calls("模块!函数") 统计调用次数/参数(如 ...Calls("ntdll!mem*"))伪寄存器与脚本化(简单自动化):
r $t0 = 0 起临时变量;$ > <文件> 把命令输出重定向到文件(如 $ > c:\log.txt).if (rax==0) { ... } .else { ... }——配合 gc 做断点内逻辑!runaway 看线程 CPU 时间(找忙等/死循环线程);!locks 查锁状态(挂起排查)!analyze -v 快速找崩溃原因)lm 行尾 (no symbols),k 输出 ntdll!+0x1a;原因——符号路径为空或没 _NT_SYMBOL_PATH;对策——.sympath srv*C:\symbols*https://msdl.microsoft.com/download/symbols 后 .reload /f,内核模块同理(先确认符号服务器可达)\\.\pipe\com_1),bcdedit /dbgsettings 重查配置,物理机场景优先 KDNETr eax 改错值、!teb 字段对不上;原因——x64 上下文用 rax/rbx...(低 32 位是 eax 等)、wow64 目标线程栈在 x86 层;对策——先确认目标位数,wow64 场景 .load wow64exts + !wow64exts.sw 切到 x86 上下文k 是假象:现象——调用栈乱(地址不像代码);原因——栈指针被破坏/内存踩踏,常规回溯不可信;对策——用 .exr 拿异常记录、.cxr 恢复 CONTEXT 后再 k,必要时 !analyze -v 的 STACK_TEXT 里直接取现场Open Crash Dump 报格式错;原因——minidump 不完整(磁盘满)或用的 32 位 WinDbg 读 64 位 dump;对策——目标机确认内核页交换文件(crash dump 需要 pagefile)足够大,改用同位数 WinDbgkvn 看调用来源;筛选目标调用:第三参数(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 等其他功能搞挂)