Правильно ли я понимаю, что если я хочу в загружаемой dll перехватить вызов некой функции из kernel32.dll до вызова DLLMain, то у меня есть три пути:
1) Сплайсинг самой функции из kernel32.dll
2) Запуск процесса в режиме отладки и ожидание WaitForDebugEvent с LOAD_DLL_DEBUG_EVENT и последующая модификация IAT таблицы.
3) Написание своего загрузчика dll, в котором будет модифицироваться IAT таблица.
Здравствуйте, Aniskin, Вы писали:
A>Правильно ли я понимаю, что если я хочу в загружаемой dll перехватить вызов некой функции из kernel32.dll до вызова DLLMain, то у меня есть три пути:
A>1) Сплайсинг самой функции из kernel32.dll A>2) Запуск процесса в режиме отладки и ожидание WaitForDebugEvent с LOAD_DLL_DEBUG_EVENT и последующая модификация IAT таблицы. A>3) Написание своего загрузчика dll, в котором будет модифицироваться IAT таблица.
Для ценителей:
4.a) LdrRegisterDllNotification + сплайсинг DllMain + модификация IAT из хука на DLLMain
Для рисковых ценителей:
4.b) LdrRegisterDllNotification + патч EntryPoint в соответствующей LDR_DATA_TABLE_ENTRY + модификация IAT из хука на DLLMain
ЗЫ А может все-таки в отдельном процессе запустить тот архиватор?
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
O>ЗЫ А может все-таки в отдельном процессе запустить тот архиватор?
Для ситуации, в которой мне понадобилось произвести перехват api до вызова DLLMain, "тот архиватор" уже в отдельном процессе, точнее в отдельном COM сервере.
Здравствуйте, Aniskin, Вы писали:
A>Правильно ли я понимаю, что если я хочу в загружаемой dll перехватить вызов некой функции из kernel32.dll до вызова DLLMain, то у меня есть три пути:
что за dll? как она грузится? что за функция из кернел32? зачем это вам вообще?
я думаю если знать ситуацию ближе, то и вариантов куда больше будет
Здравствуйте, rumit7, Вы писали:
R>я думаю если знать ситуацию ближе, то и вариантов куда больше будет
Есть у меня широко известный в узких кругах проект TC4Shell. Суть проекта — работа с разными архивами в Проводнике, как с простыми папками. Сам проект по сути представляет собой враппер над различными сторонними dll, такими как 7z.dll и unrar.dll. Дополнительно реализована возможность подключения WCX плагинов от TotalCommander. Все это чудесненько работает.
Решил я добавить поддержку плагинов от FAR. И добавил. И снова все чудесненько работает, включая эмуляцию FAR dialog api. Но есть один момент. Поскольку сам FAR и его плагины работают в консоли, то мне нужно перехватывать и эмулировать слой API, работающий с консолью. Я это сделал, но обнаружил, что отдельные плагины вызывают консольное API в DLLMain. Например, плагин NetBox, вызывает CreateFile('CONIN$') и сохраняет полученный хендл в своих закромах, который затем использует (в частности) при вызове Peek/ReadConsoleInput. Но поскольку в Проводнике консоли нет, то CreateFile возвращает INVALID_HANDLE_VALUE, и мне в перехваченную Peek/ReadConsoleInput также приходит INVALID_HANDLE_VALUE. Я в данный момент делаю так: если мне пришел INVALID_HANDLE_VALUE, то считаю, что это мой правильный хендл, и соответственно обрабатываю его. Но как то это не красиво. Вот и хочу попробовать перехватывать API не после LoadLibrary, а до вызова DLLMain.
А перехватываю я очень много. CreateFileAW/CloseHandle и практически все из списка. Как то так.
Остается после вызова оригинальной NtMapViewOfSection узнать имя замапленной секции, и если это нужная длл, то "делаем нехорошие дела дальше".
Но принцип такой-же как и указанно выше
A>но обнаружил, что отдельные плагины вызывают консольное API в DLLMain.
Ну если "тот архивтаор" правда в отдельном процессе, то не проще ли дать ему консольку на руки при помощи AllocConsole? Ее кстати даже не обязательно делать видимой, можно спрятать ее окно или ваще запускать процесс на неинтерактивном десктопе, а если хочется значть что он там такое рисует — периодически вычитывать содержимое консольки ReadConsoleOutput()-ом
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Aniskin, Вы писали:
A>1) Сплайсинг самой функции из kernel32.dll A>2) Запуск процесса в режиме отладки и ожидание WaitForDebugEvent с LOAD_DLL_DEBUG_EVENT и последующая модификация IAT таблицы. A>3) Написание своего загрузчика dll, в котором будет модифицироваться IAT таблица.
Здравствуйте, ononim, Вы писали:
O>не проще ли дать ему консольку на руки при помощи AllocConsole? Ее кстати даже не обязательно делать видимой, можно спрятать ее окно
Если вызывать AllocConsole, а затем прятать окно консоли, то окно мигает. Не красиво.
O>или ваще запускать процесс на неинтерактивном десктопе,
Я использую COM сервера (простота реализации, удобство вызова callback функций из сервера в клиентское приложение), т.е. процесс запускается не мной, а COM подсистемой.
O>если хочется знать что он там такое рисует — периодически вычитывать содержимое консольки ReadConsoleOutput()-ом
Для корректного UI мне нужен именно перехват функций.
Здравствуйте, Aniskin, Вы писали:
A>Здравствуйте, ononim, Вы писали:
O>>не проще ли дать ему консольку на руки при помощи AllocConsole? Ее кстати даже не обязательно делать видимой, можно спрятать ее окно A>Если вызывать AllocConsole, а затем прятать окно консоли, то окно мигает. Не красиво.
Ну кончено не красиво, можно сделать и красиво. При создании процесса можно передать свои хендлы для ввода-вывода через структуру STARTUPINFO. Там обычные пайпы передаются. Никакого окна не будет.
O>>или ваще запускать процесс на неинтерактивном десктопе, A>Я использую COM сервера (простота реализации, удобство вызова callback функций из сервера в клиентское приложение), т.е. процесс запускается не мной, а COM подсистемой.
Можно, чтобы процесс был COM-сервисом, правда инсталляция (регистрация) такого сервиса требует админа (но только регистрация).
Здравствуйте, Denwer, Вы писали:
A>>Если вызывать AllocConsole, а затем прятать окно консоли, то окно мигает. Не красиво.
D>Ну кончено не красиво, можно сделать и красиво. При создании процесса можно передать свои хендлы для ввода-вывода через структуру STARTUPINFO. Там обычные пайпы передаются. Никакого окна не будет.
Спасибо за совет, но как я уже писал, мне не нужна консоль как таковая. Мне нужен именно перехват функций.
Здравствуйте, Alexander G, Вы писали:
AG>Можно, чтобы процесс был COM-сервисом, правда инсталляция (регистрация) такого сервиса требует админа (но только регистрация).
An object written as a service is installed for use by COM by establishing a LocalService value under its AppID key and performing a standard service installation.
(Я вообще вручную этого никогда не делал, с ATL ведь как, Wizard, ATL Project, в Application Settings выбираешь Service — и всё работает).