DLL выгружается сама
Возможно ли для функции, которая находится внутри DLL, выгружать DLL? Мне нужно сделать это, чтобы убедиться, что DLL не используется, а затем записать в файл DLL.
4 ответа
Я не думаю, что это сработает. Вызов FreeLibrary с дескриптором извне (LoadLibrary был бы вызван из области за пределами DLL), так как код выполняется в области памяти, которая больше не будет действительной.
Даже если это возможно, он пахнет как плохой дизайн. Может быть, вы хотите сделать некоторые обновления или тому подобное. Объясните немного больше, какой результат вы ожидаете. Выгрузка DLL изнутри сама по себе - это не тот путь.
Насколько я понимаю, это МОЖЕТ быть сделано и ДОЛЖНО иногда выполняться (например, в случае внедрения dll с помощью CreateRemoteThread и других методов). Так,
FreeLibraryAndExitThread(hModule, 0)
будет делать именно это.
С другой стороны, звонит
FreeLibrary(hModule)
не будет здесь - из MSDN: "Если бы они вызывали FreeLibrary и ExitThread по отдельности, было бы условие гонки. Библиотека может быть выгружена до вызова ExitThread". В качестве примечания, ExitThread выполняет некоторую бухгалтерию, помимо простого возврата из функции потока.
Все это предполагает, что Ваша Dll получила сам hModule, вызвав LoadLibrary из загруженной Dll, или, вернее, вызвав из загруженной Dll следующую функцию:
GetModuleHandleEx
(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)DllMain,
&hModule
)
Это увеличивает счетчик ссылок Dll, так что вы знаете, что если вы позже освободите библиотеку, используя этот дескриптор, и если библиотека действительно выгружена, то у вас будет последняя ссылка на нее.
Если вместо этого вы пропустите увеличение счетчика ссылок Dll и получите hModule только из аргумента DllMain во время DLL_PROCESS_ATTACH, то вам не следует вызывать 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 - это структура PE вашего заголовка:
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
Если вы спросили, можете ли вы безопасно выгрузить / разархивировать DLL, загруженную в процесс, из кода в самой DLL, ответ будет отрицательным - на самом деле безопасного способа сделать это не существует.
Подумайте об этом следующим образом: выгрузка DLL выполняется путем уменьшения количества ссылок с помощью FreeLibrary(). Проблема, конечно же, состоит в том, что как только счетчик ссылок DLL достигает нуля, модуль не отображается. Это означает, что код в DLL, который вызвал FreeLibrary (), исчез.
Даже если бы вы могли сделать это, вам все равно нужно убедиться, что нет других потоков, выполняющих какие-либо экспортируемые функции из DLL.