WOW64サービステーブルをWinDbgでみる
WOW64サービステーブルというのは、wow64.dllのなかに実装された関数テーブル。WOW64プロセスがシステムコールを発行したときに、x64システムコールへの変換を行うため透過的に呼び出される。前回までの調査でこいつのシンボル名はwow64!ServiceTablesであることがわかっているので、これを元にWinDbgでテーブルの構造をダンプしてみることにする。
結論としては、SERVICE_DESCRIPTOR_TABLE構造体とほぼ同じ型で、それが4個の配列(sdwhnt32, sdwhwin32, sdwhcon, sdwhbase)になっている。
まず調査するアドレスの構造がよくわからない場合、dcコマンドで16進数とASCII文字列にしてみる(いくつかのWinDbgコマンドは、アドレスを2つ渡すことで、始点と終点を指定できる)。このコマンドはASCIIが出るので、文字列や、視覚的な情報から規則性を見つけやすい。
; なんか規則性があるよね 0:000> dc wow64!ServiceTables wow64!ServiceTables+f0 00000000`7546aa00 754692a0 00000000 00000000 00000000 ..Fu............ 00000000`7546aa10 000003e8 00000000 75469fc0 00000000 ..........Fu.... 00000000`7546aa20 00000000 00000000 00000000 00000000 ................; ____ここまでで1エントリー? 00000000`7546aa30 7541fae0 00000000 00000000 00000000 ..Au............ 00000000`7546aa40 000003e8 00000000 754214b0 00000000 ..........Bu.... 00000000`7546aa50 00000000 00000000 7541e110 00000000 ..........Au....; ____ここまでで1エントリー? 00000000`7546aa60 75421b40 00000000 00000000 00000000 @.Bu............ 00000000`7546aa70 000003e8 00000000 75421e60 00000000 ........`.Bu.... 00000000`7546aa80 00000000 00000000 75421820 00000000 ........ .Bu....; ____ここまでで1エントリー? 00000000`7546aa90 754691e0 00000000 00000000 00000000 ..Fu............ 00000000`7546aaa0 000003e8 00000000 75469258 00000000 ........X.Fu.... 00000000`7546aab0 00000000 00000000 75469160 00000000 ........`.Fu....; ____ここまでで1エントリー? 00000000`7546aac0 00000045 00000000 00000045 00000000 E.......E....... 00000000`7546aad0 0210003e 00000000 7546aae0 00000000 >.........Fu.... 00000000`7546aae0 0044005c 00760065 00630069 005c0065 \.D.e.v.i.c.e.\.; ここからは関係なさそうだ 00000000`7546aaf0 00610048 H.a.
あるいは、d*sコマンドでシンボル名解決を図るのも有効。今回は、x64環境なので dqs(dump qword symbol_name) か dps(dump pointer_size symbol_name)を使うのが妥当。
; ポインタサイズで解釈してシンボル解決を試してみる。 ; なんか出た。 0:000> ds wow64!ServiceTables wow64!ServiceTables+f0 00000000`7546aa00 00000000`754692a0 wow64!sdwhnt32JumpTable 00000000`7546aa08 00000000`00000000 00000000`7546aa10 00000000`000003e8 00000000`7546aa18 00000000`75469fc0 wow64!sdwhnt32Number 00000000`7546aa20 00000000`00000000 00000000`7546aa28 00000000`00000000 ; たぶん、0x30(48)バイト1エントリーだね。区切ってあらわしてるよ。 00000000`7546aa30 00000000`7541fae0 wow64win!sdwhwin32JumpTable 00000000`7546aa38 00000000`00000000 00000000`7546aa40 00000000`000003e8 00000000`7546aa48 00000000`754214b0 wow64win!sdwhwin32Number 00000000`7546aa50 00000000`00000000 00000000`7546aa58 00000000`7541e110 wow64win!sdwhwin32ErrorCase 00000000`7546aa60 00000000`75421b40 wow64win!sdwhconJumpTable 00000000`7546aa68 00000000`00000000 00000000`7546aa70 00000000`000003e8 00000000`7546aa78 00000000`75421e60 wow64win!sdwhconNumber 00000000`7546aa80 00000000`00000000 00000000`7546aa88 00000000`75421820 wow64win!sdwhconErrorCase 00000000`7546aa90 00000000`754691e0 wow64!sdwhbaseJumpTable 00000000`7546aa98 00000000`00000000 00000000`7546aaa0 00000000`000003e8 00000000`7546aaa8 00000000`75469258 wow64!sdwhbaseNumber 00000000`7546aab0 00000000`00000000 00000000`7546aab8 00000000`75469160 wow64!sdwhbaseErrorCase 00000000`7546aac0 00000000`00000045 ; ここから下は関係なさそうだね 00000000`7546aac8 00000000`00000045 00000000`7546aad0 00000000`0210003e 00000000`7546aad8 00000000`7546aae0 wow64!WindirFullObjectNameBuffer 00000000`7546aae0 00760065`0044005c 00000000`7546aae8 005c0065`00630069 00000000`7546aaf0 00640072`00610048
この辺で、構造がわかってきた。面白そうなのでJumpTableフィールドの中身を調べる。
0:000> dps wow64!sdwhbaseJumpTable wow64!sdwhbaseJumpTable+100 00000000`754691e0 00000000`7545abc0 wow64!whNtWow64CsrBasepSoundSentryNotification 00000000`754691e8 00000000`7545ac18 wow64!whNtWow64CsrBasepRefreshIniFileMapping 00000000`754691f0 00000000`7545ad00 wow64!whNtWow64CsrBasepDefineDosDevice 00000000`754691f8 00000000`7545ae8c wow64!whNtWow64CsrBasepCreateProcess 00000000`75469200 00000000`7545b2c8 wow64!whNtWow64CsrBasepExitProcess 00000000`75469208 00000000`7545b320 wow64!whNtWow64CsrBasepSetProcessShutdownParam 00000000`75469210 00000000`7545b380 wow64!whNtWow64CsrBasepGetProcessShutdownParam 00000000`75469218 00000000`7545b3f4 wow64!whNtWow64CsrBasepSetTermsrvAppInstallMode 00000000`75469220 00000000`7545b44c wow64!whNtWow64CsrBasepSetClientTimeZoneInformation 00000000`75469228 00000000`7545b530 wow64!whNtWow64CsrBasepCreateThread 00000000`75469230 00000000`7545b5b0 wow64!whNtWow64CsrBasepCreateActCtx 00000000`75469238 00000000`7545b93c wow64!whNtWow64CsrBaseCheckRunApp 00000000`75469240 00000000`7545bb7c wow64!whNtWow64CsrBaseQueryModuleData 00000000`75469248 00000000`7545bc78 wow64!whNtWow64CsrBasepNlsUpdateCacheCount 00000000`75469250 00000000`7545bcd0 wow64!whNtWow64CsrBasepNlsGetUserInfo 00000000`75469258 04080804`040c0404 ; <- wow64!sdwhbaseNumber 00000000`75469260 0008001c`34040c0c 00000000`75469268 00000000`754691e0 wow64!sdwhbaseJumpTable 00000000`75469270 00000000`00000000 00000000`75469278 00000000`000003e8 00000000`75469280 00000000`75469258 wow64!sdwhbaseNumber 00000000`75469288 00000000`00000000 00000000`75469290 00000000`75469160 wow64!sdwhbaseErrorCase ; ...
どうみても関数テーブルです。すこし通り過ぎたあたりに、再びサービステーブルの構造が現れている(コメントの部分。0x75469268)。
0:000:x86> dt 73829268 sdwhbase
名前は wow64!sdwhbase という。また、関数テーブルの後には wow64!sdwhbaseNumber の中身がある。「これは1バイトの配列だな(キリッ 」というのは勘で。1バイトとして個数を数えると関数テーブルの個数と一致する。
この構造はほかのテーブルに関しても同様なので定義としてはこんな感じになる(ダンプ結果)。
struct WOW64_SERVICE_TABLE { void* JumpTable; // 関数テーブル void* Reserved1; ULONG Size; // テーブルエントリーの最大数 UCHAR* Number; // 関数の引数サイズの配列 void* Reserved2; void* ErrorCase; // (調べたが不明) } wow64!ServiceTables[4]; // こいつらのフィールドは wow64!ServiceTables と同じものを指している。 WOW64_SERVICE_TABLE wow64!sdwhnt32; WOW64_SERVICE_TABLE wow64win!sdwhwin32; WOW64_SERVICE_TABLE wow64win!sdwhcon; WOW64_SERVICE_TABLE wow64!sdwhbase;
それぞれのテーブルは ntoskrl.exe系、win32k.sys系、コンソール系、csrss.exe系 みたい。
こういう遊びをするのならこの本を買ってみるとよいかもです。
Windowsデバッグの極意 ツールを使いこなして、バグハント!
- 作者: Mario Hewardt,Daniel Pravat,長尾高弘
- 出版社/メーカー: アスキー・メディアワークス
- 発売日: 2009/04/28
- メディア: 大型本
- 購入: 4人 クリック: 128回
- この商品を含むブログ (29件) を見る