WinDBGを使ってnotepad.exeをデバッグする
モチベーション
Windowsアプリケーションのプロセスにデバッガをアタッチしてその動きを追いたい
前提条件
- コンピュータの仕組みやバイナリ関連の基礎を身に付けていること
※ 自信がない場合は本記事下部のおまけを参考にする。
WinDBGをつかってメモ帳をデバッグしてみる
Windowsで使えるデバッガは色々あり、OllyDebugなんかはUIがユーザフレンドリで使いやすく多くのユーザに使われている。一方で、WinGDBはユーザビリティが良いとは言えないものの、Microsoft公式のデバッガであり、64bitアプリケーションのデバッグにも使える。今回は、WinGDBをつかってメモ帳のデバッグを行う。
環境準備
Windows環境を用意する
modern.IEから評価用Windowsをダウンロードして仮想化ツール、Virtualboxで起動する。IE8 on Win7、VirtualBoxを選択してインストールする。
WinDBGをインストールする
Microsoft Download CenterからWinDBGをダウンロードする。WinDBGはMicrosoft Windows SDKの中の1つのコンポーネントとして含まれており、SDKのインストーラでDebugging Toolsだけを選択すればWinDGBのみをインストールできる。また、cmd.exeからWinDBGを実行できるように以下の環境変数を設定する。
- 環境変数名:PATH(既存のPATHの末尾に値を追加)
- 値:
C:\Program Files\Debugging Tools for Windows(x86)\
シンボルファイルのインストールとパスの設定
シンボルファイルとはソースコード、行番号、変数名、データ型などのプログラムの情報を格納しているファイルであり、デバッグに必要な情報(シンボル)が含まれたファイルのこと。拡張子はpdb(Program DataBase files)。デバッガとシンボルファイルリンクさせることで、デバッグでより詳細な情報を確認できる。インストールはWindows シンボル パッケージのダウンロードから行う。
また、都度WinDBGでパスの設定をするのは面倒なので、Use the Microsoft Symbol Server to obtain debug symbol filesを参考に環境変数にシンボルへのパスを設定する。
- 環境変数名:
_NT_SYMBOL_PATH
- 値:
SRV*c:\Symbols*http://msdl.microsoft.com/download/symbols
WinDBGでメモ帳をデバッグする
プロセスにデバッガをアタッチする
まずはnotepad.exeにWinDBGをアタッチする。
notepade.exe
を起動するwindbg.exe
を起動する- WinDBGのウィンドウから
File > Attach to a Process > notepad.exe
よりプロセスにデバッガをアタッチする
プロセスにデバッガをアタッチするとはじめはエントリポイントでブレーク状態になる。プロセスを動かしたいときはg
を入力してブレーク状態を解放する。また、デバッガでプロセスの情報を確認したい場合は、WinDBGのBreakボタンをクリックする。この繰り返しがライブデバッグの基本的な流れとなる。
notepadに入力した文字列がメモリのどこに格納されているか確認する
notepadに入力した文字列はファイルに保存しないとデータとしては残らないと思われがちがだが、実際にはキーボードから入力した瞬間からメモリに展開される。これを確認するには、notepadeに”hello”という文字列を入力した後に以下のコマンドを実行する。
0:001> s -u 0 L?80000000/2 "hello" 0037f3e0 0068 0065 006c 006c 006f 0000 0000 0000 h.e.l.l.o.......
notepadeが読み込まれているメモリを確認する
プログラムが展開されているメモリをかくにんするにはlmf
コマンドを使う。特に、特定のプロセスのみを指定したい場合は以下のように、lmf m プロセス名
とする。
0:001> lmf m notepad start end module name 00ea0000 00ed0000 notepad C:\Windows\system32\notepad.exe
レジスタの値を確認する
現在のレジスタの値を確認するにはr
コマンドを実行する。
0:001> r eax=7ffdd000 ebx=00000000 ecx=00000000 edx=777ff1d3 esi=00000000 edi=00000000 eip=77794108 esp=0083f904 ebp=0083f930 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!DbgBreakPoint: 77794108 cc int 3 0:001> r eax eax=7ffdd000
メモリの中身を確認する
ダブルワードでメモリを確認するにはdd
、ASCIIで確認するにはda
コマンドを使う。
0:001> dd 0037f3e4 006c006c 0000006f 00000000 00000000 0037f3f4 00000000 00000000 00000000 00000000 0037f404 00000000 00000000 00000000 00000000 0037f414 00000000 00000000 00000000 00000000 0037f424 00110004 0835ad16 08004ae7 00000000 0037f434 00000000 2935ad37 0c004aef 74793e54 0037f444 0007019a 00000000 00000000 00000000 0037f454 00000000 00000000 00000000 00000000 0:001> da 0037f3e0 0037f3e0 "h"
コールスタックを確認する
現在トレースしている場所を確認するにはt
コマンドを使う。
0:001> t eax=7ffdd000 ebx=00000000 ecx=00000000 edx=777ff1d3 esi=00000000 edi=00000000 eip=77794109 esp=0083f904 ebp=0083f930 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!DbgBreakPoint+0x1: 77794109 c3 ret
また、コールスタックを確認する場合はK
を入力する。
0:001> K ChildEBP RetAddr 0083f900 777ff20f ntdll!DbgBreakPoint+0x1 0083f930 7666ee1c ntdll!DbgUiRemoteBreakin+0x3c 0083f93c 777c37eb kernel32!BaseThreadInitThunk+0xe 0083f97c 777c37be ntdll!__RtlUserThreadStart+0x70 0083f994 00000000 ntdll!_RtlUserThreadStart+0x1b
ディスアセンブルする
ディスアセンブル結果を出力するにはu "アドレス"
とする。アドレスを指定しない場合はeipが指すアドレスからディスアセンブル結果を表示する。
ntdll!DbgBreakPoint+0x1: 77794109 c3 ret 7779410a 90 nop 7779410b 90 nop ntdll!RtlInitString: 7779410c 57 push edi 7779410d 8b7c240c mov edi,dword ptr [esp+0Ch] 77794111 8b542408 mov edx,dword ptr [esp+8] 77794115 c70200000000 mov dword ptr [edx],0 7779411b 897a04 mov dword ptr [edx+4],edi
おまけ:最低限のバイナリ関連の知識を身に付ける
いきなりWinDBGを触っても良いが、バイナリ関連の基礎を身に付けた上でWinDBGでのデバッグにつなげて行きたい。色々読んだが、以下だけ実施すればとりあえずOK。あとは実践形式で学習していく。
Step1:レジスタ周辺の用語に慣れる
はじめは用語もわからないのでスタックやレジスタに纏わる単語を理解する。
- わかりやすいコンピュータ技術情報:スタック領域
- わかりやすいコンピュータ技術情報:スタックでPOP、PUSHを扱うためのESPの説明
- わかりやすいコンピュータ技術情報:関数を呼出す瞬間に何が行なわれるのか(retの役割)
- わかりやすいコンピュータ技術情報:スタック領域の構成、ebpとespから見たバッファーオーバーフローの原理
Step2:バイナリ周りの体系的な知識を養う書籍
用語になれた所で体系的に基礎を身につけるためにバイナリ周辺知識について体系的にまとめている書籍を幾つか読む。Hacking: 美しき策謀 第2版 ―脆弱性攻撃の理論と実際はLinuxを対象にバイナリ関連の知識を身に付けられる。時間が無い時は2章だけ読む。デバッガによるx86プログラム解析入門【x64対応版】はWindowsが対象。
- コンピュータはなぜ動くのか 知っておきたいハードウエア&ソフトウエアの基礎知識
- Hacking: 美しき策謀 第2版 ―脆弱性攻撃の理論と実際
- デバッガによるx86プログラム解析入門【x64対応版】
参考
WinDBG Tutorial
- Open Security Research: Getting Started with windbg - Part 1
- Open Security Research: Getting Started with windbg - Part 2
- Getting Started with windbg (User-Mode) (Windows Debuggers)
- A word for windbg
- Hooked on Mnemonics Worked for Me: “Hello World” For windbg
- Beginning windbg - how to search for a string and return memory location