2009年5月26日火曜日

静的にリンクしたDLLのフック

ちょっとはまった。
  1. フック対象のTARGET.DLLのファイル名をORIGINAL.DLLに変更する。
  2. 新しくTARGET.DLLを作り、ORIGINAL.DLLをLoadLibraryとGetProcAddressで元のコードを呼ぶ。
たまたま(!?)、DLLからは関数だけをEXPORTする村に住んでいるので、この手順でいけるだろうと思っていたのだが甘かった。

「ORIGINAL.DLLがEXPORTする関数を呼び出すデストラクタ」をもつオブジェクトをグローバル変数としてインスタンス化してあって、そのデストラクタが呼ばれる前にORIGINAL.DLLが解放されていた。

参考: Why are DLLs unloaded in the "wrong" order? (なぜDLLは意図しない順序でアンロードされるのか?)

解決策を探している間にみつけたMemoryModuleも面白そうだったけれど、
依存関係情報を与えるためには解決策は静的リンクにするしかなさそうだ・・・

TARGET.DLLから名前を変えられてしまったORIGINAL.DLLのインポートライブラリは、モジュール定義ファイルから簡単に生成できる。

LIB /DEF:ORIGINAL.def /MACHINE:X86 /out:ORIGINAL.lib

あとは、ORIGINAL.libを静的リンクした新しいTARGET.DLLを作ればよい。
しかし、ORIGINAL.libに含まれる関数を、新しいTARGET.DLLにも定義しなければ意味がないのに、定義してしまうと今度は名前が衝突してリンカが文句を言うだろう。その前にコンパイラが混乱するか・・。

なので、結論は

TARGET.DLL → ALIAS.DLL → ORIGINAL.DLL

このように静的リンクすること。

・・・かも-.-;

target.c
#include "alias.h"

#pragma comment(lib, "alias")

int target_function_name()
{
return alias_function_name();
}
alias.c
#include "target.h"

#pragma comment(lib, "original")

int alias_function_name()
{
return target_function_name();
}

0 件のコメント:

コメントを投稿