http://www.rsdn.ru/article/baseserv/IntercetionAPI.xml автор пишет Практика показала, что вместо обычного jmp лучше применять комбинацию push xxxxxxxx ret Может ли кто-нибудь это прокомментировать? Почему лучше? jmp иногда не срабатывает должным образом?
На стеке остается адрес перехода, что радует автора и, возможно, где-то даже радует профитом, а не хрен знает чем.
K10 Вы бы для начала что-ли почитали что такое JMP и как эта инструкция работает со стеком (скажу вам по секрету - стек она совсем не трогает). Когда вы прочтете мануал по JMP можете переходить к изучению связки PUSH+RET - каким образом она (эта связка) влияет на значение в вершине стека (до выполнения PUSH) - скажу вам по секрету RET "забирает" значение PUSH со стека и НЕ ТРОГАЕТ стек выше. Codegrammer Код (Text): Может ли кто-нибудь это прокомментировать? Почему лучше? jmp иногда не срабатывает должным образом? PUSH удобнее использовать, т.к. на стек кладется сразу адрес перехода. Если использовать JMP, то: 1. Перед записью аргумента для JMP придется самому вычислять дельту между адресом перехода и адресом самого JMP (хотя это в целом не проблема) 2. Аргумент JMP имеет "ограничения" на дистанцию в силу своей относительности - т.е. прыгнуть с его помощью можно только в пределах +-2 Гб (в случае с PUSH аргумент принимает любое значение от 0 до 4Гиг) С другой стороны у PUSH+RET есть минусы: 1. Пространство под сплайсинг нужно 5+1=6 байт (вместо 5-ти в случае с JMP) 2. Для х64 PUSH придется все равно менять на что-то другое, т.к. аргумент у PUSH не позволяет писать в него 64-х битное значение
dermatolog 2. Тогда есчо лучше юзать межсегментные ветвления(jmp far seg:offset имеет размер 7 байт, что влаживается в lock cmpxchg8b при установке, иногда это важно).
n0name Там по-моему получается 9+1+1 = 11, но это все равно дохрена. При плайсинге нативных АПИ - оптимальный вариант все-таки это JMP, т.к. он отлично "входит" на место MOV EAX,XXXX Clerk В x64 нет jmp far seg:offset
Вообще-то АП "закольцовано", т.е. отрицательные адреса переадресуются в старшую часть АП, а сверх 4Г в младшую (путём простого отбрасывания "лишних" битов адреса после всех адресных вычислений). Так что через +-2Г тоже попасть можно куда угодно. ЗЫ: пробовал при самопальном переходе в защищённый режим - никаких исключений не наблюдалось. Под win не пробовал.
Y_Mur Если учесть что с некоторых версий венды поддерживается память>2 гиг, то ваше выссказывание вызывает сомнение ) medstrax1 У меня проблем вообще нет ) Топикстартер спрашивал про конкретный пример - чем хуже/лучше JMP и PUSH+RET. Я рассказал плюсы и минусы обоих подходов. Задача сплайсинга сводится не только к тому как правильнее скакануть на свой обработчик, но еще и как минимизировать размер самого перехода на этот обработчик. "Обычный" JMP тут рулит адназначна+обработка ситуации с прыжками +-2 гига, которая решается выделением памяти "возле" перехватываемых API, в которой уже можно делать вообще все что угодно, хоть PUSH+RET, хоть JMP DWORD/QWORD PTR [MEM]
dermatolog Возможно, имеет смысл по умолчанию предполагать, что одного окружают люди, а не ледяные феи: >>Интересно, каким образом при джампе адрес перехода попадает в стек??? >Адрес, откуда была вызвана перехваченная функция. == >>Интересно, каким образом при джампе адрес перехода попадает в стек??? >При джампе, выполняемом в начале функции в рамках перехвата, стек не трогается и там сохраняется адрес того места, откуда была вызвана перехваченная функция. dermatolog Y_Mur имеет в виду, что из любого места 4х-гигабайтного адресного пространства можно с помощью джампа попасть в любое. И мы с ним абсолютно согласны. Например, нужно попасть с адреса 10000h в С001000h: 10000h: jmp C0010000h 10000h: jmp -3fff0000h Clerk Не видим соединительной нити между "jmp far seg:offset" и "lock cmpxchg8b". Скорее всего ты в чём-то заблуждаешься (можешь описать сценарий – и тогда мы скажем где).
Sol_Ksacap Код изменять следует атомарно. Обычно это делается с помощью инструкции cmpxchg8b, есть есчо cmpxchg16b, но не желательна к использованию ибо не все камни поддерживают. Некоторые извращенцы юзают fpu для этих целей.
Sol_Ksacap Вы про что? Для х32 - согласен, но я в целом говорил про универсальных подход в том числе и для х64.
Это точно изврат. Учитывая, что lock с fpu/sse командами юзать нельзя, cmpxchg8b - самый кошерный способ.
Codegrammer имхо push & ret гибко и удобно - просто прыжок на указанный адрес + бонусы что значение адреса у вас под рукой в стеке до его ближайшего изменения