GDB无法访问内存...为什么它在映射和可执行内存中返回的位置很重要?

时间:2014-10-16 17:26:11

标签: c linux assembly gdb

我有以下短程序,它将堆栈上的返回地址设置为某个值,这样当它返回时它将跳转到这个设置地址:

(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。

0 个答案:

没有答案