Как получить указатель инструкции в 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
GetCurrentAddress:
mov eax, [esp]
ret
...
call GetCurrentAddress
mov [currentInstruction], eax
во избежание несоответствия между стеком вызовов и буфером стека возврата (RSB). Но, вероятно, это не важно в шеллкоде