2012-06-11 1 views
4

В настоящее время я играю с трюком windows/WOW64, известным как «небесные ворота», который, как некоторые из вас, вероятно, знают, позволяет нам войти в режим x64, хотя в программе x86 (я был так поражен, когда я проверил его и он работал) Но я знаю, что это не поддерживается на всех версиях Windows, поэтому мой код (потому что есть код) использует SEH, это выглядит следующим образом:О ассемблерных дальних звонках и небесных воротах, выполняйте сегментные вызовы, которые вызывают исключение push cs и eip ПЕРЕД исключением, которое выбрано?

start: 
    use32 
    ;; setup seh... 
    call $33:.64bits_code ; specify 0x33 segment, it's that easy 
    ;; success in x64 mode, quit seh... 
    jmp .exit 

.64bits_code: 
    use64 
    ;; ... 
    use32 
    retf 

.seh_handler: 
    use32 
    ;; ... 
    xor eax,eax ; EXCEPTION_CONTINUE_EXECUTION 
    ret 

.32bits_code: 
    ; we have been called by a far call (well, indirectly, routed by a seh handler) 
    ; HERE IS THE PROBLEM => Should i use a retf since cs and eip are on the stack, 
    ;      or the exception has been triggered before pushing them??? 
    ; "retf" or "jmp .exit"? 

.exit: 
    xor eax,eax 
    push eax 
    call [ExitProcess] 

Я знаю, что простой «JMP .exit "сделал бы трюк, но мне ужасно интересно об этом

+0

Что вы хотите сказать? Если это код в коде, сделайте его частью вашего вопроса. –

+0

Мне очень жаль, это мой первый вопрос StackOverflow. Ну, да, мой вопрос: если инициируется исключение (например, если код работает только в системе x86), будут ли cs и eip уже вставлены в стек? поэтому, должен ли я retf или просто jmp? – nts94

ответ

1

Когда ОС получает прерывание или происходит ошибка, он ожидает, что независимо от того, что было в коде пользователя, CPU сохранил требуемый в стек ядра, чтобы IRET незримо возобновит все, что он делает.

Обратите внимание, что в этом состоянии в стеке ядра нет «магии». «Продолжение выполнения» означает только восстановление сохраненных значений rflags, cs:rip и ss:rsp и запуск кода, который cs:rip заканчивает тем, что указывает на.

Это означает, что без участия SEH специально, просто думать о каких-то исключение происходит во время дальнего вызова, на самом деле есть только два случая:

  1. Исключение происходит «до» скачка: ничего было нажато, состояние в стеке ядра говорит, что мы должны возобновить перезапуск команды вызова.
  2. Исключение происходит «после» прыжка: cs:eip были нажаты, rip указывает на то, что на отметке .64bits_code или после нее, и что сохраненное состояние говорит, что для возобновления мы должны перейти к 64-битовому коду.

Если процессор позволил дальний вызов будет прерван «в середине», то не было бы возможным значением cs:rip, который производит последовательный результат, когда операционная система продолжает выполнение. Например, если обратный адрес удаленного вызова был нажат до того, как произошло исключение, но сохраненный cs:rip указывает на инструкцию удаленного вызова, вы получите две копии обратного адреса в стеке, и все ад разрывается.

Теперь, чтобы ответить на ваш вопрос: это зависит от значения rIP, которое ОС сообщает об исключении. Если он указывает на 64-битный код, вы должны иметь cs: eip в стеке, если он указывает на 32-битный код, который можно смело предположить, что он еще не нажат.

Смежные вопросы