re-windbg について
re-windbgは、Windowsのユーザーモードとカーネルのリバースエンジニアリング向けWinDbgワークフローです。クラッシュダンプ、カーネルデバッグ、TTDトレース再生に加え、ブレークポイント、レジスター、例外の分析手順を扱います。
主な機能
- 01ユーザーモードの起動、アタッチ、ブレークポイント
- 02クラッシュダンプと例外の分析
- 03ローカル、VM、二台構成でのカーネルデバッグ
- 04TTDトレースの記録と再生
- 05シンボル、レジスター、メモリーの確認
活用シーン
- 01Windowsプロセスのクラッシュ原因の特定
- 02minidumpやカーネルクラッシュダンプの分析
- 03ドライバーとカーネルモジュールの実行状態の確認
- 04トレース再生による検証・復号ロジックの調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ dslsdzc/ rev-skills --skill re-windbgインストール後、Claude Code で/re-windbgを入力して読み込まれたか確認します。
同梱ファイルreferences/commands.mdreferences/gotchas.md
詳細
WinDbg の動的デバッグ(Windows ユーザーモード+カーネル)
使用する場合/使用しない場合
- 使用する:Windows ユーザーモードプロセスのデバッグ(起動/アタッチ、ブレークポイント、ステップ実行、レジスター);クラッシュ/例外の分析(
!analyze -v);カーネルデバッグ(2 台構成/VM/ローカル kd);ドライバーとカーネルモジュールの分析([[re-kernel]] と併用);クラッシュダンプ(ミニダンプ/フルダンプ)の分析 - 使用する:タイムトラベルデバッグ(TTD)——
ttd.exeで .run トレースを記録して任意の位置から再生できます。「一度再現して、じっくり調べる」のに適した検証/復号ロジックに向いています([[commands]] の TTD 節を参照) - 使用しない:Linux のターゲット([[re-gdb]] を使用);macOS のターゲット([[re-lldb]]);軽量な GUI デバッグのみが必要な場合([[re-x64dbg]] のほうが高速です)
- 使用しない:静的解析/逆コンパイルのみを行う場合([[re-ida]]/[[re-ghidra]]/[[re-binaryninja]]);実行中のプロセスとやり取りしない純粋な静的ワークフローでは、デバッガーは不要です
- 使用しない:WSL 内から境界を越えて Windows プロセスにアタッチする場合([[re-analyze/platform-tips]] の WSL 分岐:境界を越える場合は Windows 側のツールを使用します)
ツールの準備
[[re-analyze/platform-tips]] の Windows 分岐を参照してください——アタッチには管理者権限が必要です。デバッグは動的実行にあたるため、デフォルトでサンドボックス内で行います([[re-analyze/platform-tips]] の最優先原則)。
WinDbg(Microsoft Store 版/Windows SDK/WDK)
- Store 版(新しい 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を実行すると、バージョン番号が出力されます - バージョンによる違い:Store 版(WinDbg 1.x、Chromium UI)とクラシック版(WinDbg 10.0.x)はコマンドに互換性がありますが、UI とアタッチ手順は異なります。ダンプ分析はどちらでも同じように行えます([[gotchas]] を参照)
Windows シンボル(Windows SDK シンボル/パブリックシンボルサーバー)
- シンボルパス:
.sympath srv*C:\symbols*https://msdl.microsoft.com/download/symbols(または環境変数_NT_SYMBOL_PATHを設定します) - カーネルモジュールのシンボル:カーネルデバッグ中に
.reload /f ntを実行します(シンボルサーバーから強制的に取得します) - 確認:
!analyze -vの出力に、+0x1aのようなオフセットではなく関数名が表示されることを確認します
2 台構成/仮想マシンのカーネルデバッグ環境
- ターゲットマシン(デバッグ対象):
bcdedit /debug onとbcdedit /dbgsettings serial debugport:1 baudrate:115200(シリアル)またはbcdedit /dbgsettings net hostip:<宿主機IP> port:50000 key:<kdnet.exe生成的key>(NET NIC、Windows 10+ で推奨)を設定します - VM の場合:ターゲット VM にシリアルデバイス(名前付きパイプ
\\.\pipe\com_1/-vmconnect)を追加し、ホスト側の WinDbg でFile > Kernel Debug > COMを開き、パイプ名を入力します - ローカルカーネルデバッグ(テストマシンのみ。テスト署名が必要):
bcdedit /set testsigning onを実行して再起動した後、WinDbg でFile > Kernel Debug > Localを選択します - 確認:ターゲットマシンの再起動後に "Waiting to reconnect" で停止するか、デバッグ待機状態になったら、ホスト側の WinDbg でアタッチできることを確認します。
gの後にCtrl+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 節を参照)
操作步骤
-
附加/启动用户态目标:
- 启动:
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_NAME - 内核蓝屏对应 bugcheck 码(
BUGCHECK_CODE,如 0xD1 驱动访问无效内存)——先记码再往下查,常见码含义要能对上故障方向 - 现场恢复: 从
STACK_TEXT取EXCEPTION_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 码与故障模块
- 目标崩溃停下后:
-
内核调试(双机 / 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(仅测试机,不影响生产机的用法)
- 目标机配置见「工具准备」;配置后重启,宿主
-
扩展命令:
!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(在轨迹上工作) - 查询 API:
dx @$cursession.TTD.Calls("模块!函数")统计调用次数/参数(如...Calls("ntdll!mem*")) - TTD 限制: 需管理员运行、用户态专用、轨迹文件很大(数 GB)、回放只读不能写内存(见 [[gotchas]])
- 断点前移/后移:
-
伪寄存器与脚本化(简单自动化):
- 伪寄存器:
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を実行します。カーネルモジュールも同様です(まずシンボルサーバーにアクセスできることを確認してください)。 - カーネルデバッグの設定ミス → ターゲットマシンがブルースクリーンのまま応答しない、または接続できない:現象——ターゲットマシンの再起動後、デバッグ待ちで停止するか、中断されずにそのままシステムが起動します。原因——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 -vのSTACK_TEXTから直接、現場の情報を取得してください。 - ブルースクリーンダンプを開けない:現象——
Open Crash Dumpで形式エラーが表示されます。原因——minidump が不完全(ディスク容量不足)か、32 ビット版 WinDbg で 64 ビットのダンプを読み込んでいます。対策——ターゲットマシンでカーネルページファイル(クラッシュダンプには pagefile が必要)が十分なサイズであることを確認し、同じビット数の WinDbg を使用してください。 - RPC 呼び出しの共通入口 NdrStubCall3(svchost の機能をリバースエンジニアリングする場合):現象——Toast 通知などの特定のシステム機能をフック/分析したいが、どの経路を通って svchost に到達するのかわかりません。原因——機能の実装は RPC 経由で svchost プロセスに到達するため、入口を見つけにくいです。対策——Process Monitor で対象プロセスが rpcrt4.dll を読み込んでいることを確認し、RpcView で RPC の接続先プロセスを特定します。すべての RPC サーバースタブは rpcrt4 の NdrStubCall3 を経由します(x64。NdrStubCall2 は旧版の x86 用です。ReactOS/Wine のソースコードで確認できます)。ここにブレークポイントを設定し、
kvnで呼び出し元を確認します。対象の呼び出しを絞り込むには、第 3 引数(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]] を参照してください。
コメント
Markdown 対応