仲介DLL生成補助ツール

Last modified: 2005/01/16 21:30:01

ダウンロード

この「仲介DLL生成補助ツール」は、EXEファイルとDLLファイルの仲介を行う偽物の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の生成

仲介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
Copyright (C) 2003-2005 Kenji Aiko All Rights Reserved