FreeLibrary hook

Тема в разделе "WASM.WIN32", создана пользователем virooz, 24 ноя 2011.

  1. virooz

    virooz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    5
    Мне необходимо перехватить LoadLibrary/FreeLibrary в приложениях, чтобы отслеживать подгружаемые библиотеки.
    Вызываю SetWindowsHookEx чтобы mydll подгрузить ко всем процессам, стандартной заменой первых 5 байт перехватываю функции.
    Внутри перехватчиков new_LoadLibrary/new_FreeLibrary выполняем нужные мне действия, и вызываем реальные LoadLibrary/FreeLibrary.

    Проблема:
    Во время UnhookWindowsHookEx наступает момент, когда FreeLibrary освобождает mydll, то есть библиотеку где хранится функция-перехватчик. Происходит следующее:
    По возврату из реальной Freelibrary, естестно, получаем AV.

    На delphi в кратце все это выглядит вот так:
    Код (Text):
    1. function new_FreeLibrary(hLibHandle: Cardinal): LongBool; stdcall;
    2. begin
    3.   if UnHookCodeHook(@priFreeLibrary) then begin
    4.     if hLibHandle <> HInstance then begin //выгружаем чужую dll
    5.  
    6.       ...      
    7.  
    8.       Result := FreeLibrary(hLibHandle);
    9.       SetCodeHook(rfFreeLibrary, @new_FreeLibrary, @priFreeLibrary);
    10.     end
    11.     else begin //если выгружаем сами себя (так получится т.к. FreeLibrary перехвачена в этой библиотеке которую здесь пытаемся выгрузить)
    12.  
    13.       ...
    14.       Result := FreeLibrary(hLibHandle); //После удачной отработки FreeLibrary, по ret вернемся сюда, но тут уже ничего не будет!
    15.     end;
    16.   end;
    17. end;
    Как я понимаю, во время mydll.new_FreeLibrary можно сохранить адрес возврата, а в последующем DLLMain вернуться на него, но я далек от манипуляций с EIP/ESP и вообще от асма. Как это делается?

    Другими словами надо чтобы библиотека правильно выгрузила сама себя, и исполнение вернуть в точку, откуда вызывалась new_FreeLibrary

    Вероятно вообще подход неправильный?
     
  2. XshStasX

    XshStasX New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2008
    Сообщения:
    991
    Что - то я не понял.. почему не сделать Result := TRUE; в случаии когда тебя хотят выгрузить ?
    А вообще лучше перехватывай в место LoadLibrary - LoadLibraryExW или LdrLoadLibrary.
    И вообще ты что снимаешь и потом снова ставишь хук ?? если так то твой код может приводить к глюкам в многопоточных приложениях.
     
  3. virooz

    virooz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    5
    1. Если вернуть из new_FreeLibrary TRUE - то библиотека не выгрузится, а я подчеркнул в вопросе: хочу чтобы она выгрузилась по всем правилам, то есть реальную FreeLibrary все-таки необходимо вызывать (либо освобождать библиотеку другим способом? каким тогда?)
    2. Я перехватываю LoadLibraryExW, уровень LdrLoadDll мне попросту не нужен для моей задачи
    3. На тему перехвата в многопоточных приложениях на wasm куча статей, сделаю что-нибудь потом, сейчас вопрос в другом
     
  4. XshStasX

    XshStasX New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2008
    Сообщения:
    991
    Вообще не могу понять что ты хочешь?
    адрес возврата куда ты хочешь сохранить ?

    Тебе нужно оставить твои хуки после того как mydll выгрузилась ??

    Если проблема в этом:
    Так в mydll.DLLMain сними хук.
     
  5. virooz

    virooz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    5
    1. Адрес откуда была вызвана new_FreeLibrary, может это значение какого-то из стековых регистров, не знаю, плохо разбираюсь в архитектуре, поэтому сюда и пишу
    2. Какой хук снять? Хук на функцию уже снят в этот момент, а снятие хука установленного SetWindowsHook все равно вызовет FreeLibrary
     
  6. XshStasX

    XshStasX New Member

    Публикаций:
    0
    Регистрация:
    9 авг 2008
    Сообщения:
    991
    Внимательно вчитался в пост и кажется понял тебя.

    Самый простой вариант.

    // снять все хуки которые ставить mydll
    Код (Text):
    1. Result := TRUE;
    2. CreateThread(... FreeLibrary, hLibHandle,..);
    3. // нужно как можно быстрее выйти из new_FreeLibrary
    Можно подкорректировать стек если дельфи использует фреймы при генерации кода то
    будет примерно так:
    Код (Text):
    1. mov esp,ebp
    2. pop ebp
    3. jmp [FreeLibrary]
    В этом методе могут быть проблемы иногда из того что не восстанавливаются регистры.
    Могу ошибаться но примерно так.
     
  7. TrashGen

    TrashGen ТрещГен

    Публикаций:
    0
    Регистрация:
    15 мар 2011
    Сообщения:
    1.186
    Адрес:
    подполье
    ;Как то так (проца экспортируемая из длл, которую выгружают собственно)
    FreeDll: ;hInst:dword
    jmp FreeLibrary
     
  8. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    virooz
    если я правильно понял суть проблемы, то можно сделать так:
    в качестве функции-обработчика нужно поставить следующее:
    Код (Text):
    1. mov eax,hLibHandle;переданный параметр FreeLibrary
    2. cmp hMod,eax;hMod - база загрузки вашей dll
    3. jne new_FreeLibrary
    4. push priFreeLibrary;ну если stdcall
    5. call UnHookCodeHook
    6. jmp FreeLibrary
     
  9. virooz

    virooz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    5
    Все три предложенных варианта основываются на вызове jmp вместо call, логично, насколько я понимаю стек вызовов будет тогда именно таким как мне хотелось, то есть после реальной FreeLibrary будет прыгать обратно в точку вызова new_FreeLibrary. Задумка qwe8013 больше всего похожа на правду, попробую на днях, всем спасибо!