cdb/Windbgの使い方のメモ

よく使いそうなものの覚書。

シンボルサーバの指定

環境変数を用いて指定しておくとよい。

>set _NT_SYMBOL_PATH=srv*C:\Symbols*http://msdl.microsoft.com/download/symbols

デバッグ情報付きでコンパイル

コンパイルオプションとして/Ziを付ける。

>cd /Zi hello.c

実行ファイルを指定して起動

>cdb hello.exe

主要なコマンドの一覧を表示

0:000> ?

各種情報の表示

レジスタ

0:000> r

メモリ内容

dcはdword+ascii形式で表示、dpsはポインタ配列とみなし対応するシンボルと合わせて表示。

0:000> dc esp
0:000> dps esp

ディスアセンブル結果

引数としてシンボル名を使う場合は、[module]![symbol]の形で指定する。 poi()オペレータを使うことで、ポインタが指す先のアドレスを扱うことができる(gdbにおける*addrに対応)。

0:000> u eip
0:000> u kernel32!VirtualProtectStub
0:000> u poi(kernel32!_imp__VirtualProtect)

スタックトレース

kvを使うと第3引数までの値も合わせて表示できる。

0:000> k
0:000> kv

すべてのスレッドのスタックトレースを表示するには次のようにする。

0:000> ~* k

構造体情報

-rオプションで深さを指定できる。

0:000> dt _PEB 7ffde000 -r2

ロードされているモジュール

0:000> lm

PEヘッダ情報

0:000> !dh -f 00400000

メモリの保護属性

0:000> !vprot esp

ヒープエントリ

0:000> !heap -x 007B7218
Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
-----------------------------------------------------------------------------
007b7210  007b7218  00780000  00780000      1008        88         8  busy

上の結果から、0x007b7218から0x1008バイトの領域が確保されており、末尾の8バイトは未使用、freeされていない状態(busy)であることがわかる。

セグメントのベースアドレス

0:000> dg fs
                                  P Si Gr Pr Lo
Sel    Base     Limit     Type    l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0053 7ffdd000 00000fff Data RW Ac 3 Bg By P  Nl 000004f3

fs:[0h]にはThread Environment Block(TEB)が配置されており、ここからProcess Environment Block(PEB)を含む各種情報をたどることができる。

0:000> dt _TEB 7ffdd000 -r2

実行関連

順にgdbにおけるcontinuenexti(関数の中に入らない)、stepi(関数の中に入る)、finish(リターンするまで進める)に対応する。

0:000> g
0:000> p
0:000> t
0:000> gu

ブレークポイント関連

順に設定、表示、削除。

0:000> bp kernel32!VirtualProtectStub
0:000> bl
0:000> bc

レジスタの書き換え

0:000> r eax=41414141
0:000> r eax=ebx+4

メモリ内容の検索

下記のように指定するとアドレス0から0x80000000バイトを検索する。 -bオプションでバイト列、-aオプションでASCII文字列を指定する。

0:000> s -b 0 L?80000000 c9 c3
0:000> s -a 0 L?80000000 MZ

終了

0:000> q

関連リンク