Мне необходимо перехватить LoadLibrary/FreeLibrary в приложениях, чтобы отслеживать подгружаемые библиотеки. Вызываю SetWindowsHookEx чтобы mydll подгрузить ко всем процессам, стандартной заменой первых 5 байт перехватываю функции. Внутри перехватчиков new_LoadLibrary/new_FreeLibrary выполняем нужные мне действия, и вызываем реальные LoadLibrary/FreeLibrary. Проблема: Во время UnhookWindowsHookEx наступает момент, когда FreeLibrary освобождает mydll, то есть библиотеку где хранится функция-перехватчик. Происходит следующее: По возврату из реальной Freelibrary, естестно, получаем AV. На delphi в кратце все это выглядит вот так: Код (Text): function new_FreeLibrary(hLibHandle: Cardinal): LongBool; stdcall; begin if UnHookCodeHook(@priFreeLibrary) then begin if hLibHandle <> HInstance then begin //выгружаем чужую dll ... Result := FreeLibrary(hLibHandle); SetCodeHook(rfFreeLibrary, @new_FreeLibrary, @priFreeLibrary); end else begin //если выгружаем сами себя (так получится т.к. FreeLibrary перехвачена в этой библиотеке которую здесь пытаемся выгрузить) ... Result := FreeLibrary(hLibHandle); //После удачной отработки FreeLibrary, по ret вернемся сюда, но тут уже ничего не будет! end; end; end; Как я понимаю, во время mydll.new_FreeLibrary можно сохранить адрес возврата, а в последующем DLLMain вернуться на него, но я далек от манипуляций с EIP/ESP и вообще от асма. Как это делается? Другими словами надо чтобы библиотека правильно выгрузила сама себя, и исполнение вернуть в точку, откуда вызывалась new_FreeLibrary Вероятно вообще подход неправильный?
Что - то я не понял.. почему не сделать Result := TRUE; в случаии когда тебя хотят выгрузить ? А вообще лучше перехватывай в место LoadLibrary - LoadLibraryExW или LdrLoadLibrary. И вообще ты что снимаешь и потом снова ставишь хук ?? если так то твой код может приводить к глюкам в многопоточных приложениях.
1. Если вернуть из new_FreeLibrary TRUE - то библиотека не выгрузится, а я подчеркнул в вопросе: хочу чтобы она выгрузилась по всем правилам, то есть реальную FreeLibrary все-таки необходимо вызывать (либо освобождать библиотеку другим способом? каким тогда?) 2. Я перехватываю LoadLibraryExW, уровень LdrLoadDll мне попросту не нужен для моей задачи 3. На тему перехвата в многопоточных приложениях на wasm куча статей, сделаю что-нибудь потом, сейчас вопрос в другом
Вообще не могу понять что ты хочешь? адрес возврата куда ты хочешь сохранить ? Тебе нужно оставить твои хуки после того как mydll выгрузилась ?? Если проблема в этом: Так в mydll.DLLMain сними хук.
1. Адрес откуда была вызвана new_FreeLibrary, может это значение какого-то из стековых регистров, не знаю, плохо разбираюсь в архитектуре, поэтому сюда и пишу 2. Какой хук снять? Хук на функцию уже снят в этот момент, а снятие хука установленного SetWindowsHook все равно вызовет FreeLibrary
Внимательно вчитался в пост и кажется понял тебя. Самый простой вариант. // снять все хуки которые ставить mydll Код (Text): Result := TRUE; CreateThread(... FreeLibrary, hLibHandle,..); // нужно как можно быстрее выйти из new_FreeLibrary Можно подкорректировать стек если дельфи использует фреймы при генерации кода то будет примерно так: Код (Text): mov esp,ebp pop ebp jmp [FreeLibrary] В этом методе могут быть проблемы иногда из того что не восстанавливаются регистры. Могу ошибаться но примерно так.
;Как то так (проца экспортируемая из длл, которую выгружают собственно) FreeDll: ;hInst:dword jmp FreeLibrary
virooz если я правильно понял суть проблемы, то можно сделать так: в качестве функции-обработчика нужно поставить следующее: Код (Text): mov eax,hLibHandle;переданный параметр FreeLibrary cmp hMod,eax;hMod - база загрузки вашей dll jne new_FreeLibrary push priFreeLibrary;ну если stdcall call UnHookCodeHook jmp FreeLibrary
Все три предложенных варианта основываются на вызове jmp вместо call, логично, насколько я понимаю стек вызовов будет тогда именно таким как мне хотелось, то есть после реальной FreeLibrary будет прыгать обратно в точку вызова new_FreeLibrary. Задумка qwe8013 больше всего похожа на правду, попробую на днях, всем спасибо!