Advanced member
Статус: Не в сети Регистрация: 09.06.2003 Откуда: USSR
Всем приветы Вот решил открыть топик в большей степени чтобы самому понять куда двигаться, а также может и еще кому помогу. Задача следующая. Определить точное кол-во байт подлежащих замене при всовывании своего JMP в тело другой процедуры. (Наверное не совсем понятно описал). Есть такой метод по подсовыванию своего кода в тело любой системной функции , грубо говоря перехват вызова этой функции. Делает с использованием двух функций.
1 - Функция замены
2 - Функция "трамплин"
Кто хочет подробнее узнать об этом, могут дать поиск по гугулу по словам "API HiJack", "api spy".
Ну или вот пара линков сразу
http://www.devx.com/Intel/Article/21023 http://maxcomputing.narod.ru/ahijack.html?lang=ru
Для чего это длается? Ну для того, чтобы отследить как вызывается та или иная функция той или иной программой .
Основная проблема в этом деле это то, что получив адрес функции, мы должны узнать сколько байт можно заменить, минимум нам надо 5 байт, для того, чтобы в тело функци впихнуть свой JMP на свою процедуру, а старые байты, копируются в тело функци трамплина (она пустая) и под конец этих байт вписывается обычных JMP обратно на тело старой функци , но уже с учетом кол-ва замененных байт. Знакомые с асмом поймут о чем идет речь. Так вот, если изначально изветно сколько бай можно заменить (к примеру просто дизассемблировав .dll с нужной функцией), то вроде хорошо, но с другой стороны, завтра выйдет обновление этой .dll а там код функци уже изменен и скажем вместо 5 байт надо 7 менять!
______
И так к чему это я все. Нужен выход из ситуации, а именно. Как же определить сколько байт (минимум 5 ) надо подменить.
Чисто кусок кода из IDA
Member
Статус: Не в сети Регистрация: 12.03.2003 Откуда: Израиль
Тебе тоже привет!
Есть два способа, выбирай наиболее подходящий:
1. Всегда "тырить" 5 байт. Так, например, поступают вирусы.
При передаче управления на исходный код либо восстановить исходные байты насовсем (вирусам большего и не надо), либо трассировать через int 1 (так поступают отладчики).
2. Дизассемблирование на лету. Ввиду того, что тебе не надо разбираться с точной мнемоникой команды, а только знать ее длину, можно обойтись достаточно короткой таблицей: по первым 1-2 байта всегда можно выделить длину всего опкода. (префиксы рассматриваем как отдельный опкод, как это делает, например, Debug в ДОСе)
Еще подумай, возможно тебе достаточно побаловаться с таблицей экспортов DLL-я.
_________________ Более мощный компьютер глючит быстрее и точнее.
Advanced member
Статус: Не в сети Регистрация: 09.06.2003 Откуда: USSR
WhPh 1. Способ не подходит так как мне надо не одноразово к сожалению 2. Вот про это я и говорю, но боюсь что может не хватить простейших операндов, да кто там знает что будет в начале процедуры то?
Цитата:
Еще подумай, возможно тебе достаточно побаловаться с таблицей экспортов DLL-я
К конретном случае, а именно в подмене функции LoadLibraryA (из kernel32) врядли пройдет, так как всегда какой то гад подменяет тело фугкции уже до меня, скорее всего Windows , а может и еще какой гад (не зараза ).
stargaz0r То что есть я тыкал, не все так гладко как кажется. В том то и дело, что мне пришлось столкнуться с тем, что функция уже подменена кем-то и причем нагло прописан JMP и все остальное тело зашито в NOP! Повторюсь это не вирус.
Добавлено спустя 3 минуты, 52 секунды: Да и еще многие вещи там без исходника, на кой они мне?
Advanced member
Статус: Не в сети Регистрация: 09.06.2003 Откуда: USSR
serj_ Думал над ним уже, но может так получится, что после меня еще кто нибудь влезет (а ведь влезут блин!) и тогда цепь нарушится, или наоборот до меня влезли, а потом ушли .
Advanced member
Статус: Не в сети Регистрация: 10.04.2003 Откуда: Москва
Ray Adams, чудак человек, так же работают все обработчики DOS прерываний. Если кто перехватит наглой записью jump в первых байтах, то ты ничего сделать не сможешь ... ну, почти.
Если 'нахальной' перезаписи не будет, то твой обработчик будет запущен. ... или ты хочешь единолично править ресурс?
Кстати, что мешает периодически проверять валидность твоей правки?
Advanced member
Статус: Не в сети Регистрация: 09.06.2003 Откуда: USSR
Цитата:
чудак человек, так же работают все обработчики DOS прерываний.
Ну тут тебе не дос хотя аналогия похожа. Другая проблема, мне нужно будет не подпортить регистры перед тем как вызывать предыдущий код, с этим будет сложновато так как моя процедура на Си, а не на АСМе.
Цитата:
Кстати, что мешает периодически проверять валидность твоей правки?
И чем? Таймером чтоли? Мой .dll инжектируется в любой процесс и больше от меня никак не зависит, сам сообщая мне об определенных событиях. Фиг с ним с перезаписью, мне важно нормально перехватить управление процедурой.
Видимо всеже придется подумать над этим вариантом, но всеже ломает сама суть, не красиво как то , при каждом вызове востанавливать, потом опять заменять
Advanced member
Статус: Не в сети Регистрация: 09.06.2003 Откуда: USSR
Подумал я сейчас , а ведь проблема в этим варианте!
Вот смотрим:
1. Запоминаем 5 байт
2 Заменяем 5 байт на JMP
_____
Идет вызов процедуры, при входе сразу идет JMP к нам, так? Так. Мы все что надо нам сделали, определили параметры и так далее и востанавливаем все обратно, опять делаем JMP и ... тут то и фигня выйдет.
Как же тогда опять пропатчить процедуру, если после ее вызова наша процедура управления не получит ?
Member
Статус: Не в сети Регистрация: 12.03.2003 Откуда: Израиль
Ray Adams Тогда общая идея алгоритма:
Завести таблицу (интеловский мануал рулит!)
Отсечь префиксы (хотя они нечасто под Виндой попадаются)
Проанализировать первый байт опкода. Свериться в таблице по поводу его длины и наличия операндов.
Опкод - он 1 или 2 байта.
Если предусмотрен немедленный операнд, из той же таблицы взять длину операнда.
Если предусмотрен байт с операндами типа регистра, вытащить из другой таблицы длину операндов (может быть от 0 до 8-и байт)
Работы - примерно на день...
_________________ Более мощный компьютер глючит быстрее и точнее.
Advanced member
Статус: Не в сети Регистрация: 10.04.2003 Откуда: Москва
Ray Adams писал(а):
Как же тогда опять пропатчить процедуру, если после ее вызова наша процедура управления не получит?
Читаешь невнимательно. Я сказал 'call' Если хочешь сделать свое 'перед' - делай перед вызовом, если править 'после' - после call. (т.е. можно отфильтровать и входные данные и результат) или call делать нельзя? ....
Последний раз редактировалось serj 21.02.2005 14:20, всего редактировалось 1 раз.
Member
Статус: Не в сети Регистрация: 12.03.2003 Откуда: Израиль
Про второй вариант:
Угу, можно. Обратно патчим следующим образом:
1. Запоминаем где-нибудь адрес возврата функции.
2. Записываем туда какой-то свой адрес, по которому восстановим перехват
3. Уходим туда, куда код собирался возвращаться изначально.
С перехватом некоторых функций возможны глюки. В общем случае - сработает.
Добавлено спустя 2 минуты, 3 секунды: serj_ CALL не сработает: мы же сдвинули стек своим адресом возврата... Функция получит неправильные параметры.
_________________ Более мощный компьютер глючит быстрее и точнее.
Advanced member
Статус: Не в сети Регистрация: 09.06.2003 Откуда: USSR
Цитата:
или call делать нельзя?
Тут уже не сделаеш к сожалению, нарушиться работа малость, но я думаю что если я сам сделаю повторый call, получу обратно все что надо и сам верну результат? Как будто изначально вызывали именно меня! Главное чтобы описание функции полностью совпадало, в таком варианте сработает.
WhPh
Цитата:
Тогда общая идея алгоритма: Завести таблицу (интеловский мануал рулит!)
Видимо можно попробовать, не так уж и много будет там работы, но боюсь нарваться на не только просыте команды но и специфику по MMX/SSE. Кто его там блин знает что будут писать! Хочется универсальности. (зажрался я видимо )
Member
Статус: Не в сети Регистрация: 12.03.2003 Откуда: Израиль
Цитата:
но я думаю что если я сам сделаю повторый call, получу обратно все что надо и сам верну результат?
Можно. Но тогда тебе придется знать кол-во параметров для каждой перехватываемой функции...
А как насчет
Цитата:
1. Запоминаем где-нибудь адрес возврата функции. 2. Записываем туда какой-то свой адрес, по которому восстановим перехват 3. Уходим туда, куда код собирался возвращаться изначально.
???
Вроде бы легче. Только если что-нибудь из серии CreateThread не будет перехватываться.
_________________ Более мощный компьютер глючит быстрее и точнее.
Advanced member
Статус: Не в сети Регистрация: 09.06.2003 Откуда: USSR
Цитата:
Можно. Но тогда тебе придется знать кол-во параметров для каждой перехватываемой функции...
Ну так это обязательное условие при перехвате функции, я же за параметрами и слежу!
Цитата:
Вроде бы легче.
Ну в принципе тоже самое, только наоборот.
Все же если бы получилость четко определить точное кол-во байт не разрывного кода, то вообще проблем небыло бы. Так как все уже отработано, процедуры готовы и пашут давным давно. Но все сейчас делается с готовыми цифрами по кол-ву байт. И уже были пару раз глюки из-за того, что при определенной версии + SP тело процедуры менялось.
Advanced member
Статус: Не в сети Регистрация: 10.04.2003 Откуда: Москва
WhPh писал(а):
CALL не сработает: мы же сдвинули стек своим адресом возврата... Функция получит неправильные параметры.
Хорошо, например было:
Код:
invoke Sleep,100 label: xor eax,eax
это выродилось в
push 100
call Sleep
Сам "call Sleep" через кучу jump попадает в нужную процедуру
sleep proc
При этом в стеке будет:
> 100; label
Если сделать 'восстановить' и CALL Sleep, то в стеке будет:
> my; 100; label
Т.е. да, ты прав. Но ... что мешает сделать несколько не так - заменить в стеке 'label' на свой 'восстановитель' patch'а? Процедура будет работать как-то так: (циклическая часть)
> [вход]
(1)
- восстановить первые 6 байт вызываемой процедуры
- сохранить из стека 'возвратный ret'
- положить туда указатель на (3)
- jump на начало процедуры
---------------------------------------
(3) обработчик восстановления patch'а
- изменить первые 6 байт на свой обработчик (1)
- положить в стек 'возвратный ret'
- сказать RET
Advanced member
Статус: Не в сети Регистрация: 10.04.2003 Откуда: Москва
Ray Adams, проследил время выполнения запроса к драйверу (моему) и назад - вышло порядка 10uS.
О чем ты говоришь???? .... это увеличит время на 15 операций 'mov [**],eax'
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 21
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения