DLL 内にある関数が DLL をアンロードすることは可能ですか? DLLが使用されていないことを確認してから、DLLのファイルに書き込むことができるように、これを行う必要があります。
4 に答える
私が理解しているように、それは実行可能であり、時々実行することを意味します(たとえば、CreateRemoteThread およびその他のメソッドによる dll インジェクションの場合)。そう、
FreeLibraryAndExitThread(hModule, 0)
正確にそれを行います。
一方、呼び出し
FreeLibrary(hModule)
ここでは行いません - MSDN から: 「FreeLibrary と ExitThread を別々に呼び出すと、競合状態が発生します。ライブラリは、ExitThread が呼び出される前にアンロードされる可能性があります。」備考として、ExitThread は、スレッド関数から戻るだけでなく、簿記も行います。
これはすべて、ロードされた Dll 内からLoadLibraryを呼び出すことによって、またはロードされた Dll 内から次の関数を呼び出すことによって、あなたの Dll が hModule 自体を取得したことを前提としています。
GetModuleHandleEx
(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)DllMain,
&hModule
)
これにより、Dll の参照カウントがインクリメントされるため、後でそのハンドルを使用してライブラリを解放し、ライブラリが実際にアンロードされた場合、最後の参照があったことがわかります。
代わりに、Dll の参照カウントのインクリメントをスキップして、 DLL_PROCESS_ATTACH中にDllMain
への引数から hModule を取得する場合は、 FreeLibraryAndExitThreadを呼び出すべきではありません。これは、Dll をロードしたコードがまだそれを使用しており、このモジュール ハンドルを実際に管理する必要がないためです。
dllがそれを仕事にしたときにこれを使用してください:
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, &__ImageBase, 0, NULL);
// terminate if dll run in a separate thread ExitThread(0);
// or just return out the dll
そして、__ImageBaseはdllのPEヘッダー構造です。
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
私はそれがうまくいくとは思わない。コードが無効になったメモリ位置で実行されるため、外部からハンドルを使用してFreeLibraryを呼び出す(LoadLibraryはDLLの外部の領域から呼び出されます)。
これが可能だとしても、それは悪いデザインのようなにおいがします。たぶんあなたはいくつかのアップデーターなどを作りたいでしょう。あなたが期待する結果が何であるかをもう少し説明してください。それ自体の中からDLLをアンロードすることは行く方法ではありません。
プロセスにロードされたDLLをDLL自体のコードから安全にアンロード/マップ解除できるかどうかを尋ねる場合、答えはノーです。これを行うための安全な方法は実際にはありません。
このように考えてください。DLLのアンロードは、FreeLibrary()を使用して参照カウントをデクリメントすることによって行われます。もちろん問題は、DLLの参照カウントがゼロに達すると、モジュールのマップが解除されることです。これは、FreeLibrary()を呼び出したDLLのコードがなくなったことを意味します。
これを行うことができたとしても、DLLからエクスポートされた関数を実行している他のスレッドがないことを確認する必要があります。