Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.138.141.202] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Добрый день/вечер.
У меня есть две функции: void __fastcall recvx_food(int This, void *Src, int len, int flags); и recvx = (recvx_f)GetProcAddress(hWS2_32, "recv"); Как мне записать в память по адресу функции recvx в ноль (в самое начало) 0хE9 (jmp) а по смещению +1 записать адрес функции recvx_food? И как и куда можно сохранить первые 5 байт, чтоб потом удобно и быстро восстановить функцию recvx? Спасибо! |
Сообщ.
#2
,
|
|
|
Я как-то двояко понял вопрос, и на оба варианта ответ отрицателен. Так что может быть и третий вариант. Итак:
А) если вы хотите, чтобы при вызове recvx(...) управление ушло куда надо и там вызвался переход на ..._food, то можете, конечно, записать: *((char*)recvx) = 0xE9, и далее нужное, но вам DEP (запись данных в код) запретить должен сие. Б) если же вы хотите, чтобы при вызове recvx(...) сразу шло исполнение jmp куда_надо, то тоже не выйдет, ибо переменную положат, скажем, в EAX и будет вызвано call [EAX], т.е. не то, что хотелось. В) ??? |
Сообщ.
#3
,
|
|
|
Цитата Славян @ но вам DEP (запись данных в код) запретить должен сие. я заюзал VirtualProtectEx Если оба варианта не подходят, то как хукнуть ws2_32 recv? Как его хукают обычно? Я бы сплайсингом хотел... Никак? Цитата *((char*)recvx) = 0xE9, и далее нужное Я вот и спросил - как далее то? Я синтаксис Си плохо знаю... *((char+1*)recvx) или *((char*)[1]recvx) или как?)) |
Сообщ.
#4
,
|
|
|
Да, вам нужен вариант А.
Почти как у вас: ((char*)recvx)[1] = первый байт, и т.д. Или сразу адрес: *((DWORD*)(((char*)recvx)+1)) = 0xAaBbCcDd; |
Сообщ.
#5
,
|
|
|
Славян Спасибо.
А получится сплайсингом функцию хукнуть если у нее в конце джамп? Мне же после работы оригинала надо снова хук ставить, а управление уплыло неизвестно куда... Перехватить получилось, а если восстанавливать хук после вызова оригинала - ловлю крит. Видимо из за джампа в конце ws2_32 recv. Не хукают сплайсингом функции с джампом? Или я кривой? |
Сообщ.
#6
,
|
|
|
Цитата Rzonex @ А получится сплайсингом функцию хукнуть если у нее в конце джамп? Через таблицу импорта попробуй. |
Сообщ.
#7
,
|
|
|
А как ее найти? Именно адрес начала таблицы? Я читал описание РЕ, но нифига не понял. Шерстил длл, так то на практике видел что она в памяти представляет, но не нашел...
Я если честно, то уже хукнул, очень оригинально) Суть моего метода такая: 1) обрабатываем оригинальную функцию виртуал-протектом. 2) делаем AllockMem и резервируем буфер байт на 20. 3) пишем в начало нашего буфера (смещение 0х00) CALL функция_обработчик 4) копируем в наш буфер со смещением 0х05 первые 5 байт оригинальной функции 5) пишем в буфер со смещением 0х10 джамп на ( оригинальную функцию +0х05 ) 6) пишем в начало оригинальной функции джамп на наш буфер. Вуаля, как только основной поток вызывает оригинальную функцию - он попадает на наш джамп и летит по адресу нашего буфера, в буфере он сразу же летит на наш обработчик хука, там мы делаем свои дела и ретурном возвращаемся в буфер, далее выполняем инструкции оригинальной функции (которые мы скопировали) и джампимся в оригинал + 0х05. Профит, салют, аплодисменты Это я сам так придумал хукать по нубски) А если честно, то язык на котором программирую, не поддерживает ассемблерные вставки, приходится вот так изголяться. Таблицу экспорта в тыщу раз было бы легче похукать. И еще я не восстанавливал ни указатель на стек, ни регистры, ни сам стек после обработчика своего, оно (вот чудо) и так заработало. |
Сообщ.
#8
,
|
|
|
Цитата Rzonex @ А как ее найти? Именно адрес начала таблицы? Я читал описание РЕ, но нифига не понял. ... 4) копируем в наш буфер со смещением 0х05 первые 5 байт оригинальной функции 5) пишем в буфер со смещением 0х10 джамп на ( оригинальную функцию +0х05 ) 6) пишем в начало оригинальной функции джамп на наш буфер. ... далее выполняем инструкции оригинальной функции (которые мы скопировали) и джампимся в оригинал + 0х05. в этой теме почти полный исходник. Там же есть ссылка на статью в Сети. У Рихтера в книге есть пример. --- А откуда ты знаешь, что 5 байт кратны целому числу команд ? Чтобы с гарантией эти мероприятия делать, надо буквально дизассемблер иметь в перехватчике. |
Сообщ.
#9
,
|
|
|
Цитата ЫукпШ @ А откуда ты знаешь, что 5 байт кратны целому числу команд ? OllyDbg юзаю. Я же не пытаюсь сделать что-то универсальное, для этого моих познаний еще маловато. |
Сообщ.
#10
,
|
|
|
Сделал читалку РЕ файлов, в начальный адрес добавил адрес нужной dll в памяти $10000000, вот что получил:
========================================= Process ID : 4816 Base addr : 00000000h PE signature : 00004550h Processor type : 0000014Ch Section count : 00000005h Date of create : 1386212911 Addr export table : 000DC4F0h Size of export table : 104080 Addr import table : 000D6D8Ch Size of import table : 420 Прибавил к адресам таблиц адрес dll, получилось адрес таблицы экспорта: 100DC4F0. Перешел по адресу попал на vftable, но там же должны идти адреса функций, а там явно какой то вменяемый asm код, а не адреса... Это разве оно? |
Сообщ.
#11
,
|
|
|
Цитата Rzonex @ Сделал читалку РЕ файлов, в начальный адрес добавил адрес нужной dll в памяти $10000000, вот что получил: Прибавил к адресам таблиц адрес dll, получилось адрес таблицы экспорта: 100DC4F0. Перешел по адресу попал на vftable, но там же должны идти адреса функций, а там явно какой то вменяемый asm код, а не адреса... Наверное, мы не поняли друг друга. 1. Менять надо адрес в таблице импорта исполнительного модуля (любого - .exe или .dll) одного по выбору или у всех сразу. В PE файле есть таблица с адресами. Для вызова функции делается что-то вроде: call [addr] - т.е. вызов по содержимому указанной переменной в памяти. 2. Как это сделать подробно написано в широко известной книге Рихтера. У него же в книге подробный исходник. Мой опус по ссылке - это исходник Рихтера с добавкой, необходимой для систем после Win2000. 3. Запускаем подопытный процесс с внедрённой своей dll. Внедряем как нравится. Можно внешним стартёром, можно утилитой "iidking" вставить ссылку на свою dll в таблицу импорта подсудимого файла. Если наше приложение, цепляем dll обычным образом. Для начала и отладки инструмента можно сделать именно так. 4. Из уведомления DLL_PROCESS_ATTACH перехватываем указанный API. Фактически, в таблицу импорта впишем адрес процедуры перехватчика, а из неё вызовем нужную процедуру самым обычным образом. В результате получим процедуру-посредника. --- Это устойчиво работает для любых виндусов и для x64 версий тоже. Без ассемблера, реверсных исследований. Надо только знать прототип желаемой функции и всё. --- Вот, кстати, внешний стартёр для инжекта своей dll в процесс. Который я сам написал: dllInjector |
Сообщ.
#12
,
|
|
|
Цитата ЫукпШ @ Наверное, мы не поняли друг друга. Addr import table : 000D6D8Ch Size of import table : 420 Оно? Делал по описанию РЕ файла - Структура EXE заголовка Я читал что и экспорт можно патчить? А какая разница? Просто он тут маленького размера, я решил что быстрее найду нужное в экспорте Цитата Без ассемблера, реверсных исследований. А чем мой способ плох? Я же нашел адреса таблиц, это же они? Притом это делается довольно просто - находим адрес нужной библиотеки, считываем пару адресов в памяти и получаем нужный адрес. Внутри процесса это совсем просто сделать - LoadLibraryA, GetProcAddress, и прыгаем по смещениям читаем адреса... Притом без всяких библиотек. |
Сообщ.
#13
,
|
|
|
Нашел все адреса экспортируемых функций, и их адреса в таблице экспорта.
Все данные нашел путем парсинга PE формата. Внутри процесса такую операцию можно сделать вообще не используя WinApi. Это профит, я КОРОЛЬ!!! (Король аськи!!!) Насколько я понял - если патчить ипморт, то нужно патчить все таблицы импорта во всех модулях, искать импортируется ли туда эта функция и менять адрес. Это сложновато выглядит. А если сама длл использует свою экспортируемую функцию? Тогда хук не сработает и надо патчить экспорт? Одно не понимаю - все адреса функций в экспорте внутренние для самой длл, то есть смещение у них от начала длл задано. Я к ним специально адрес длл прибавлял, чтоб получить глобальный адрес. Что будет, если я локальный адрес какой-нить функции заменю глобальным адресом своей хук функции? По идее мне и сам хук нужно размещать внутри этой длл, но MemAlloc мне там память же не выделит? Хотя можно 5 байт пустых найти в самой длл и сделать обертку - разместить там джамп на сам обработчик. ЫукпШ подскажи куда копать??? |
Сообщ.
#14
,
|
|
|
Цитата Rzonex @ Насколько я понял - если патчить ипморт, то нужно патчить все таблицы импорта во всех модулях, искать импортируется ли туда эта функция и менять адрес. Это сложновато выглядит. Это зависит от того, чего именно ты желаешь добиться. И ничего сложного тут нет. Это потребует 2-3 строчки исходника. Допустим, ты написал функцию перехвата: // pModName - имя модуля, в котором перехватываем API в импорте // pDllNames - имя dll, в которой перехваченный API // pApiName - имя перехваченной функции // pRoutine - адрес функции подмены // BOOL WINAPI HookApi ( const char* pModName, const char* pDllName, const char* pApiName, void* pRoutine ); А дальше составляешь массив параметров для неё. И запускаешь в цикле. Парой строк подменишь всё, что нужно. |
Сообщ.
#15
,
|
|
|
ЫукпШ Я хукаю функцию в модуле Engine.dll и эта функция юзается там же, этим же модулем. Импорт я не смотрел, но очень сильно подозреваю, что этой функции там нет. Что делать?
|