APIフックについてまとめてみる

現在,Windows上における特定APIのコールをリアルタイムフックしたいと思考中。

Windowsにおいて,APIをフックする方法はいろいろあることが,現時点までの調査で判明した。

  • グローバルフック
  • ラッパーDLL
  • IATフック
  • SSDTフック
  • ローダ改造

このうちグローバルフックはメッセージをフックするものでありAPI自体をフックするものでないので却下。

ラッパーDLLは結構いろいろ使用用途はあるが,kernel32やuser32のような,Windowsの根幹に関わるDLLには適用できないのが欠点(実行ファイルそのもののインポートセクションを書き換えてやればできなくもない)。

IATフックは,実行中のプログラムのインポートセクションを書き換える方法だが,グローバルフックによって書き換え用DLLをアタッチさせると,書き換えが間に合わないことがある。レジストリAppInit_DLLsに登録しても,グローバルフックより若干速くなったくらいで,まだ間に合わないことがある(書き換えコードが悪いのかもしれない。このあたりは検証の必要あり)。

SSDTフックはカーネルモードであり,Windows実行時から起動できるので,リアルタイムフックという点では問題ないが,Windows API と Native API との関連付けが難しい(CreateFile と ZwCreateFile みたいにわかりやすければよいが,そうでないAPIも多い。。。特に途中でSYSCALLを呼ぶものとかどうすれば良いのか。。。)。

で,結局残るのがローダ改造のような気がする。プロセス構造ルーチンとか使用して,プログラムが実行する前にReadVirtualMemoryでインポートセクションを走査し,WriteVirtualMemoryでインポートセクションを書き換える。イメージとしてはこんな感じだが,なぜか今使用しているDDK(正確にはIFSだが)ではRead/WriteVirtualMemoryが使用できない。。。ちゃんとヘッダーに定義してやれば使用できるのかもしれないが。。。このあたりはさらなる検証が必要だ。というより,これくらいしか方法が無さそうな予感。もしくはフィルタドライバあたりで,特定DLLがOpenされたらラッパーDLLに置換するとか。でもこれだと別途オリジナルDLLをロードさせてやらないとラッパーDLLが機能しない。しかもkernel32とかuser32はWindows起動時にすぐOpenとかされていそうで,この方法も難しそう。。。けれど論より証拠,実際にやってみないと分からないし。やってみる価値はあると思う。