2009-04-24 [長年日記]
_ Windowsプログラムで生じるAccessViolationなどの例外を検知する方法
先日、Debug Hacks Conferenceに行ってきました。
みんなのDebugノウハウを共有ってのは勉強になっていいですね。(^^)
今日はそれと関係しなくもない話題で書いてみます。(どちらかというとテスト技法か)
しばらく前に業務でセキュリティのことを調べていたときに、
Fuzzingという攻撃手法があることを知りました。
入力をランダムにふって、対象アプリのふるまいを観察して、
AccessViolationなどを起こしているようならそこを攻撃の足がかりにするものです。
そういう攻撃手段があるのであれば、
それを開発者側が使ってあらかじめ防御する手段にすればいいわけです。
リンクの本は日本語で読めるたぶん唯一のFuzzing本で、
FileFuzzというWindows用のOSSFuzzingツールの作者さんらが書いてあります。
この本は大変丁寧に解説されていてオススメなのですが、
FileFuzzに関してはGUI部が数KB以上の入力ファイルに対応してないなど問題が。
そこで、FileFuzzの簡易デバッガ部分(ふるまいを観察。例外が発生したら検知。)と
GUI部分(ランダムにふって入力など)に分けて、足りないところを自作しました。
以降はそのデバッガ部分の話。
コードでいうとFileFuzzパッケージ内の src/crash/crash.c です。
このデバッガ、WindowsAPIを使って対象のプログラムの例外発生を検知してくれるのですが、
C++のコード中で投げられた(プログラマが意図した処理中の)例外も拾ってそこで処理停止してしまいます。
VC++はstd:exceptionはSEH(構造化例外)として扱うので、
この例外の場合は続行する処理を追加するように修正します。
SEHは
WaitForDebugEvent(&dbg, 100)
でとれてくる
dbg.u.Exception.ExceptionRecord.ExceptionCode
の値が 0xE06D7363 になります。
ExceptionCodeで判別してSEHのときは
ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_EXCEPTION_NOT_HANDLED)
を呼んでDBG_EXCEPTION_NOT_HANDLEDを指示してあげると、
通常の例外は続行され、AccessViolationなど有用なものだけを検知できるようになります。
詳しくは修正したcrash.cのリンクか
またはFileFuzzPatch.zipをDLして読んでみてください。
私はVC++2005で動かしました。
FileFuzzの作者さんにメールしたのですがスルーされてしまったので、ここで公開します。
ライセンス通りGPLでどぞー。
英語でもこの話書きたいけど、どこに書こうかな。。。
また、この部分の調査にあたっては同僚のIさんに多々アドバイスいただきました。4q! (^^)