この「仲介DLL生成補助ツール」は、EXEファイルとDLLファイルの仲介を行う偽物のDLLを作成、補助するツールです。さらに、任意のDLLのエクスポート関数を列挙することも可能です。当ツールはコンソールプログラムなので、コマンドプロンプトから実行してください。
任意のDLLのエクスポート関数の列挙方法は、コマンドプロンプトから以下のように入力します。listexport.exeはC:\以下に保存されているとします。おなじフォルダに任意のDLL(kernel32.dllなど)をコピーしてください。
C:\>listexport kernel32.dll 序数: 0001 名前: ActivateActCtx 序数: 0002 名前: AddAtomA 序数: 0003 名前: AddAtomW 序数: 0004 名前: AddConsoleAliasA ......(省略)...... 序数: 039D 名前: lstrcpynW 序数: 039E 名前: lstrlen 序数: 039F 名前: lstrlenA 序数: 03A0 名前: lstrlenW C:\>
kernel32.dllを引数として、listexport.exeを実行すると、kernel32.dllのエクスポート関数が標準出力に表示されます。標準出力に表示されるデータをファイルへ書き込みたい場合は、コマンドプロンプトに以下のように入力します。
C:\>listexport kernel32.dll > kernel32exp.txt C:\>
これによりkernel32exp.txtにエクスポート関数が列挙されます。
仲介DLLを作成するためには、実行時に「-file」オプションをつけます。さらに3番目の引数に出力ファイル名を指定することも可能です。指定しなかったらデフォルト名として「dmydll」というファイル名になります。以下に実行例を示します。listexport.exeはC:\以下に保存されているとします。おなじフォルダに任意のDLL(kernel32.dllなど)をコピーしてください。
C:\>listexport -file kernel32.dll lernel32 ソースファイル lernel32.cpp, lernel32.def を生成しました C:\>
実行すると「ソースファイル lernel32.cpp, lernel32.def を生成しました」を表示されます。3番目の引数に「lernel32」を指定したので、生成されたソースファイルは「lernel32.cpp」「lernel32.def」となります。あとは、この2つのファイルをVC++などでビルドするだけで、kernel32.dllとまったく同じエクスポート関数を持ったlernel32.dllを作成することができます。
まず、VC++で「lernel32」という空のDLLプロジェクトを作成します。そして、これら2つのファイルをプロジェクトに追加し、あとはビルドを行うだけです。ただし、VC++.NETに関しては少し違います。VC++.NETはとても不親切で、.defファイルをプロジェクトに追加しても、ビルド時のリンカオプションに.defファイルを追加してくれません。これはバグなんじゃないのかと私は思いますが、とにかくダメなので、VC++.NETに関しては、「ファイル→新しい項目の追加」で新しくlernel32.defファイルを作成して、そこにlistexportで生成されたlernel32.defの内容をコピーしてください。.cppファイルに関しては問題ありませんので、そのままプロジェクトに追加してください。
.defファイルはその性質上「@マーク」を関数名に含んだ関数を扱えません。よって、そのような関数名を持つDLLの仲介を行う場合は、あらかじめ「@」を「*」などに置換しておいてビルドを行い、DLLになった状態で、再度バイナリレベルで「*」を「@」に置換するといった方法をとってください。「crtdll.dll」などがそのようなDLLに該当します。
DLLの仲介を行い任意のAPIの動作を監視、もしくは変更する場合は、生成された.cppファイルを書きかえる必要があります。ここではkernel32.dllの「GetSystemTime」APIの動作を変更する例を用います。まずはlernel32.cppを開きます。そしてコードの次の行を以下のように書きかえます。
//__declspec( naked ) void WINAPI d_GetSystemTime() { _asm{ jmp p_GetSystemTime } }
__declspec(dllexport) VOID WINAPI d_GetSystemTime(LPSYSTEMTIME t);
上の行をコメントアウトして、下の行を追加します。追加する場合はMSDNなどで、あらかじめAPIの定義(引数や戻り値など)を調べておいてください。kernel32.dllに実装されているGetSystemTimeと同じ引数、戻り値を持たなければなりません。
さらに、.cppファイルの最後に実際に動作させたいコードを追加します。
// .cppファイルの最後に追加
__declspec(dllexport) VOID WINAPI d_GetSystemTime(LPSYSTEMTIME t)
{
t->wYear = 1192;
t->wMonth = 5;
t->wDay = 15;
t->wDayOfWeek = 0;
t->wHour = 1;
t->wMinute = 1;
t->wSecond = 1;
t->wMilliseconds = 1000;
}
これで完了です。あとはVC++でビルドし、生成されたDLLが仲介DLLとなります。任意のEXEファイルと同じフォルダにコピーし、EXEファイルをバイナリエディタで開き、「KERNEL32.dll」の部分を「LERNEL32.dll」と変更してください。これによって、EXEファイルはkernel32.dllのAPIを呼び出すときに常に、仲介DLLを介してアクセスすることになります。
kenji@ruffnex.oc.to