如何在没有0x00或0xFF字节的x86_64中获取指令指针?

时间:2018-08-28 03:02:35

标签: assembly x86-64 shellcode program-counter

有没有一种方法可以在不使用汇编语言的call后跟pop的情况下访问指令指针(RIP)中的值?还是有可以做到的机器码操作码?

我一直在搜索,没有明确的结果。

我的问题是机器代码中不能有任何零,否则会收到SIGSEGV错误。这是由于服务器加载代码并从字节字符串执行代码的方式所致。 Near调用到子例程的距离为零,因此不能使用call。

我使用的是64位Linux,并且具有nasm和yasm。

1 个答案:

答案 0 :(得分:4)

在x86_64中,标准方法是使用相对RIP寻址,而不是像x86中那样使用CALL。即使这样,也不建议使用通话/弹出 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 The recommended way

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

为了避免调用堆栈和返回堆栈缓冲区(RSB)之间不匹配。但是在shellcode中可能并不重要