jmp vs push ret

Тема в разделе "WASM.BEGINNERS", создана пользователем Codegrammer, 21 май 2010.

  1. Codegrammer

    Codegrammer New Member

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    37
    http://www.rsdn.ru/article/baseserv/IntercetionAPI.xml
    автор пишет

    Практика показала, что вместо обычного jmp лучше применять комбинацию
    push xxxxxxxx
    ret

    Может ли кто-нибудь это прокомментировать? Почему лучше? jmp иногда не срабатывает должным образом?
     
  2. deLight

    deLight New Member

    Публикаций:
    0
    Регистрация:
    26 май 2008
    Сообщения:
    879
    На стеке остается адрес перехода, что радует автора и, возможно, где-то даже радует профитом, а не хрен знает чем.
     
  3. K10

    K10 New Member

    Публикаций:
    0
    Регистрация:
    3 окт 2008
    Сообщения:
    1.590
    он и с джампом остается
     
  4. Oleg_SK

    Oleg_SK Guest

    Публикаций:
    0
    K10
    Интересно, каким образом при джампе адрес перехода попадает в стек???
     
  5. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Это бред.
     
  6. K10

    K10 New Member

    Публикаций:
    0
    Регистрация:
    3 окт 2008
    Сообщения:
    1.590
    Oleg_SK
    Адрес, откуда была вызвана перехваченная функция
     
  7. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    K10
    Вы бы для начала что-ли почитали что такое JMP и как эта инструкция работает со стеком (скажу вам по секрету - стек она совсем не трогает). Когда вы прочтете мануал по JMP можете переходить к изучению связки PUSH+RET - каким образом она (эта связка) влияет на значение в вершине стека (до выполнения PUSH) - скажу вам по секрету RET "забирает" значение PUSH со стека и НЕ ТРОГАЕТ стек выше.
    Codegrammer
    Код (Text):
    1. Может ли кто-нибудь это прокомментировать? Почему лучше? 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-х битное значение
     
  8. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Код (Text):
    1. mov rax, 0xFFFFFFFF
    2. push rax
    3. ret
    Но размер возрастает до 1 + 1 + 10 = 12
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    dermatolog
    2. Тогда есчо лучше юзать межсегментные ветвления(jmp far seg:offset имеет размер 7 байт, что влаживается в lock cmpxchg8b при установке, иногда это важно).
     
  10. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    n0name
    Там по-моему получается 9+1+1 = 11, но это все равно дохрена. При плайсинге нативных АПИ - оптимальный вариант все-таки это JMP, т.к. он отлично "входит" на место MOV EAX,XXXX
    Clerk
    В x64 нет jmp far seg:offset
     
  11. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Вообще-то АП "закольцовано", т.е. отрицательные адреса переадресуются в старшую часть АП, а сверх 4Г в младшую (путём простого отбрасывания "лишних" битов адреса после всех адресных вычислений). Так что через +-2Г тоже попасть можно куда угодно.
    ЗЫ: пробовал при самопальном переходе в защищённый режим - никаких исключений не наблюдалось. Под win не пробовал.
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    dermatolog
    Это да, есть косвенные ветвления:
     
  13. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Надуманные проблемы. Юзать абсолютный jmp r32/m32 религия не позволяет?
     
  14. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    сплайсинг вообще зло :)
    PS: 1 байт REX + 1 байт опкод + 8 байт imm64
     
  15. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Y_Mur
    Если учесть что с некоторых версий венды поддерживается память>2 гиг, то ваше выссказывание вызывает сомнение :))

    medstrax1
    У меня проблем вообще нет :)) Топикстартер спрашивал про конкретный пример - чем хуже/лучше JMP и PUSH+RET. Я рассказал плюсы и минусы обоих подходов. Задача сплайсинга сводится не только к тому как правильнее скакануть на свой обработчик, но еще и как минимизировать размер самого перехода на этот обработчик. "Обычный" JMP тут рулит адназначна+обработка ситуации с прыжками +-2 гига, которая решается выделением памяти "возле" перехватываемых API, в которой уже можно делать вообще все что угодно, хоть PUSH+RET, хоть JMP DWORD/QWORD PTR [MEM]
     
  16. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    dermatolog
    Возможно, имеет смысл по умолчанию предполагать, что одного окружают люди, а не ледяные феи:
    >>Интересно, каким образом при джампе адрес перехода попадает в стек???
    >Адрес, откуда была вызвана перехваченная функция.
    ==
    >>Интересно, каким образом при джампе адрес перехода попадает в стек???
    >При джампе, выполняемом в начале функции в рамках перехвата, стек не трогается и там сохраняется адрес того места, откуда была вызвана перехваченная функция.


    dermatolog
    Y_Mur имеет в виду, что из любого места 4х-гигабайтного адресного пространства можно с помощью джампа попасть в любое. И мы с ним абсолютно согласны. Например, нужно попасть с адреса 10000h в С001000h:
    10000h: jmp C0010000h
    10000h: jmp -3fff0000h

    Clerk
    Не видим соединительной нити между "jmp far seg:offset" и "lock cmpxchg8b". Скорее всего ты в чём-то заблуждаешься (можешь описать сценарий – и тогда мы скажем где).
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Sol_Ksacap
    Код изменять следует атомарно. Обычно это делается с помощью инструкции cmpxchg8b, есть есчо cmpxchg16b, но не желательна к использованию ибо не все камни поддерживают. Некоторые извращенцы юзают fpu для этих целей.
     
  18. dermatolog

    dermatolog Member

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    406
    Адрес:
    Екатеринбург
    Sol_Ksacap
    Вы про что?
    Для х32 - согласен, но я в целом говорил про универсальных подход в том числе и для х64.
     
  19. Medstrax

    Medstrax Забанен

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    673
    Это точно изврат. Учитывая, что lock с fpu/sse командами юзать нельзя, cmpxchg8b - самый кошерный способ.
     
  20. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    Codegrammer

    имхо push & ret гибко и удобно - просто прыжок на указанный адрес + бонусы что значение адреса у вас под рукой в стеке до его ближайшего изменения