Вопрос

Я пытаюсь написать упаковщик/защитник exe, чтобы узнать больше об ассемблере, C++ и о том, как работают PE-файлы.В настоящее время у меня все работает, поэтому раздел, содержащий EP, подвергается операции XOR с ключом, и создается новый раздел, содержащий мой код дешифрования.Все работает отлично, за исключением случая, когда я пытаюсь перейти к оригинальному 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++?

Это было полезно?

Решение

я думаю что E9 — это код операции для относительного перехода:его операнд определяет относительное расстояние, на которое необходимо перейти, плюс или минус от начала следующей инструкции.

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

Другие советы

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

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 — самое маленькое решение, если у вас есть адрес VA и изображение не перемещается, но его размер все равно составляет 6 байт, поэтому он больше, чем прямой jmp rel32.

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top