JMP на абсолютный адрес (коды операций) - PullRequest
5 голосов
/ 10 октября 2009

Я пытаюсь написать exe-упаковщик / защитник, чтобы узнать больше о ассемблере, c ++ и о том, как работают PE-файлы В настоящее время он работает, поэтому раздел, содержащий EP, XORed с ключом, и создается новый раздел, содержащий мой код дешифрования. Все отлично работает, за исключением случаев, когда я пытаюсь и JMP к оригинальному EP после расшифровки.

В основном я делаю это:

DWORD originalEntryPoint = optionalHeader->AddressOfEntryPoint;
// -- snip -- //
    crypted.put(0xE9);
 crypted.write((char*)&orginalEntryPoint, sizeof(DWORD)); 

Но вместо того, чтобы перейти к точке входа, ollydbg показывает, что этот код разбирается на:

00404030   .-E9 00100000    JMP 00405035 ; should be 00401000 =[

и когда я пытаюсь изменить его вручную в olly, новый код операции отображается как

00404030    -E9 CBCFFFFF    JMP crypted.00401000

Откуда взялся 0xCBCFFFFF? Как бы я сгенерировал это со стороны C ++?

Ответы [ 3 ]

18 голосов
/ 12 января 2010

вы можете использовать:

mov eax,DESTINATION_VA
jmp eax                ; pick any register the destination doesn't care about

или

push DESTINATION_VA
ret                    ; not recommended for performance

Эта и следующие до 16 ret инструкции, возвращающиеся в дерево вызовов выше этой глубины, будут неверно предсказаны, если только они не были вытолкнуты из стека предикторов обратных адресов более глубокой глубиной вызова. (Текущие процессоры обычно имеют стек предикторов из 16 записей).


относительная E9 jmp кодировка используется следующим образом:

CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])

push + ret - это наименьшее решение, если у вас есть адрес виртуальной машины, и изображение не перемещено, но оно по-прежнему 6 байт, поэтому оно больше, чем прямой jmp rel32.

Регистр-косвенный, вероятно, наиболее эффективен, если вы не можете использовать обычный прямой jmp.

5 голосов
/ 10 октября 2009

Я думаю, что E9 - это код операции для относительного прыжка: его операнд указывает относительное расстояние, которое нужно прыгнуть, плюс или минус от начала следующей инструкции.

Если вы хотите, чтобы операнд указывал абсолютный адрес, вам потребуется другой код операции.

4 голосов
/ 10 апреля 2011

код операции для абсолютного косвенного перехода - адрес FF + 4 байта. Это чаще всего используется для переходных таблиц адресов, хранящихся в данных.

Абсолютные адреса требуют перемещения, когда они не загружены на ожидаемый адрес, поэтому относительные адреса обычно предпочтительнее. Код для относительных переходов также на 2 байта меньше.

В руководстве по оптимизации Intel говорится, что процессор ожидает, что call и ret будут использоваться в парах, поэтому ret без вызова, предложенного в ответе 2, вызовет то, что они называют «снижением производительности».

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

...