GDB cannot access memory ... why does it matter where it returns in mapped and executable memory?
I have the following short program that sets the return address on the stack to some value so that when it returns it will go to that address:
(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.
Why does it matter which address I entered in [rax]? (0x400520 in this example, i.e. main + 4)
When I try different addresses it may succeed or fail with the error: "Unable to access memory at address 0x8", here (with main + 4) it fails:
(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
What is the problem? The address it returns is displayed, readable, and executed. "si" only executes one command, so it only executes the ret instruction.
I can also see that the address the rip was set to contains a valid instruction to execute.
It might seem interesting to note that manually setting $ rip to the same address doesn't seem to cause problems (for example, just set $ rip = 0x400520 and then si).
Where does this attempt to access address 0x8 come from? Why such access at all and where does "0x8" come from? ret only pops off the stack into rip. Surely there is something obvious that I'm missing here?
If I go back to different addresses for example. main + 0 or main + 32, it works, but most of the others seem to fail.
The C program is simple (+9 magic just gotten with gdb, to see how much I need it might need to tweak another system):
#include <stdio.h>
#include <stdint.h>
int main(int argc, char **argv)
{
char stack;
*((uint64_t *) (&stack + 9)) = 0x0000000000400520;
return 0;
}
I am using GNU gdb (Gentoo 7.6.2 p1) 7.6.2, but I also noticed an issue with GNU gdb (GDB) 7.5-4.0.61. I am using gcc (Gentoo 4.7.3-r1 p1.4, pie-0.5.5) 4.7.3.
source to share
No one has answered this question yet
Check out similar questions: