我有以下短程序,它将堆栈上的返回地址设置为某个值,这样当它返回时它将跳转到这个设置地址:
(gdb) disas main
Dump of assembler code for function main:
0x000000000040051c <+0>: push rbp
0x000000000040051d <+1>: mov rbp,rsp
0x0000000000400520 <+4>: mov DWORD PTR [rbp-0x14],edi
0x0000000000400523 <+7>: mov QWORD PTR [rbp-0x20],rsi
0x0000000000400527 <+11>: lea rax,[rbp-0x1]
0x000000000040052b <+15>: add rax,0x9
0x000000000040052f <+19>: mov QWORD PTR [rax],0x400520
0x0000000000400536 <+26>: mov eax,0x0
0x000000000040053b <+31>: pop rbp
0x000000000040053c <+32>: ret
End of assembler dump.
为什么我放入[rax]的地址是什么? (在本例中为0x400520,即main + 4)
当我尝试各种地址时,它可能会成功或失败,并显示错误:&#34;无法访问地址0x8和#34;的内存,此处(使用main + 4)失败:
(gdb) b *0x000000000040053c
Breakpoint 1 at 0x40053c
(gdb) run
Breakpoint 1, 0x000000000040053c in main ()
=> 0x000000000040053c <main+32>: c3 ret
(gdb) x/a $rsp
0x7fffffffdd18: 0x400520 <main+4>
(gdb) si
Cannot access memory at address 0x8
(gdb) x/i $rip
=> 0x400520 <main+4>: mov DWORD PTR [rbp-0x14],edi
这是什么问题?它返回的地址是映射的,可读的和可执行的。 &#34; SI&#34;只执行一条指令,因此它只执行ret指令。
我还看到rip设置的地址包含要执行的有效指令。
可能有必要提一下,手动将$ rip设置为同一地址似乎不会产生任何问题(例如,只需设置$ rip = 0x400520然后再设置si。)
从这里尝试访问地址0x8来自哪里?为什么会有这样的访问权限?&#34; 0x8&#34;来自? ret只会从堆栈弹出到rip中。肯定有一些明显的东西我在这里失踪了吗?
如果我返回不同的地址,例如主+ 0或主+ 32,它有效,但大多数其他似乎都失败了。
C程序很简单(魔术+9只是通过使用gdb来看看我需要多少,可能需要针对不同的系统进行调整):
#include <stdio.h>
#include <stdint.h>
int main(int argc, char **argv)
{
char stack;
*((uint64_t *) (&stack + 9)) = 0x0000000000400520;
return 0;
}
我正在使用GNU gdb(Gentoo 7.6.2 p1)7.6.2,但我也注意到了GNU gdb(GDB)7.5-4.0.61的问题。我正在使用gcc(Gentoo 4.7.3-r1 p1.4,pie-0.5.5)4.7.3。