APIフッキング

CEでAPIフックを行い敵キャラとの当たり判定の探索を行います。
矩形(くけい)どうしの当たり判定には、IntersectRectと言うWin32 APIが利用されることが多いです。

IntersectRectは引数で指定した矩形どうしが交わっているか否かを返します。
詳細:MSDN:IntersectRect 関数

CEのメモリビューワで"Ctrl+G"を入力し"Goto Adresss"を開いて、目的のAPI名を入力するとメモリビューで参照することができます。
imageプラグインエラー : ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (APIHook_1.PNG)

ターゲットプロセスにおいて当該APIのアドレスを検索しましょう。
今回、あるオンラインゲームに対して検索をかけた結果、プロセス領域内でアドレス:00D0E96Chがヒットしました。
このゲームはこのアドレスを経由して当該APIを呼び出していると仮定します。

このゲームが当たり判定のためにIntersectRectを利用していると仮定して、このAPIを呼び出しているアドレスがないか調べることにします。
そこで先ほどヒットしたアドレスにフックをしかけて、そこから戻りアドレスを抽出してみましょう。

サンプルスクリプトは以下になります:
[ENABLE]
alloc(HookIntersectRect,128)
label(retAddr)
registersymbol(retAddr)
 
HookIntersectRect:
  push eax
  mov eax,[esp+4]
  mov [retAddr],eax // 戻りアドレスを取得
  pop eax
  jmp IntersectRect
retAddr:
  dd 0
 
00D0E96C:
  dd HookIntersectRect
 
[DISABLE]
00D0E96C:
  dd IntersectRect
 
dealloc(HookIntersectRect)
unregistersymbol(retAddr)

実行結果は以下の通りです。
(スクリプトを実行した後で、チートテーブルに"retAddr"を追加しています。)

フックした後で敵が居るマップに移動すると、推測通り当たり判定のためにIntersectRectを頻繁に呼び出しているアドレス(今回の場合は00667C58h)が分かります。
注意:汎用APIの呼び出しは複数のアドレスから行われる可能性があるため場合によっては関係のない呼び出しをフィルタリングするスクリプトを組む必要があります。

IntersectRectは矩形同士が交差した場合TRUEを返す関数です。
その後に来る"TEST EAX,EAX"という命令は関数からの戻り値の真偽判定やぬるぽチェックでよく現れる命令です。

TEST EAX,EAX命令では、
  • 接触していればTRUEでEAXが0以外となりZFがセットされないので直後の"jne"命令でジャンプします。
  • 接触していなければFALSEでEAXが0となりZFがセットされるので直後の"jne"命令でジャンプしません。
したがって、この条件分岐命令を"nop"命令で潰して常にジャンプしないようにすれば敵との接触を無効化できます。

[ENABLE]
00667C6C:
  nop
  nop
  // db 90 90
 
[DISABLE]
00667C6C:
  jne 00667CBE
 // db 75 50

APIフックを用いればどのような用途にどのようなAPIが用いられるのかさえ分かっていれば、当該処理を割り出すことが可能になります。
また、先の例では戻りアドレスを調べただけでしたが引数の値を調べることでいろいろなオブジェクトの座標を割り出したり、パケットを調べたり...などと言ったことも可能になるでしょう。
最終更新:2014年07月13日 17:06