Как получить указатель инструкции в x86_64 без байтов 0x00 или 0xFF?

Есть ли способ получить доступ к значению в указателе инструкций (RIP) без использования call с последующим pop на ассемблере? Или есть опкод машинного кода, который может это сделать?

Я гуглил без четких результатов.

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

Я на Linux, 64-битный, и у меня есть нос и ясм.

1 ответ

В x86_64 стандартным способом является использование RIP-относительной адресации вместо CALL как в x86. Даже тогда, колл / поп не рекомендуется1

Обычно вы будете использовать lea rax, [rip] чтобы получить RIP в RAX (который на самом деле кодируется как lea rax, [rip + 0] с четырьмя байтами для непосредственного в конце). Однако так как LEA не разыменовывает адрес памяти, вы можете просто добавить любое постоянное смещение в RIP и вычесть его позже

0:  48 8d 05 04 03 02 01    lea    rax,[rip+0x1020304]
7:  48 2d 04 03 02 01       sub    rax,0x1020304

Вы можете выбрать любые непосредственные значения, которые не имеют нулевого или 0xFF байта. Если вы хотите адрес инструкции после lea (длиной 7 байт) вы можете исправить с помощью sub rax, 0x01020304 - 7


1 Рекомендуемый способ

GetCurrentAddress:
    mov eax, [esp]
    ret
...
    call GetCurrentAddress
    mov [currentInstruction], eax

во избежание несоответствия между стеком вызовов и буфером стека возврата (RSB). Но, вероятно, это не важно в шеллкоде

Другие вопросы по тегам