I wanna write a simple buffer overflow example for the ARMv6 instruction set architecture using a Raspberry PI and Raspbian OS. First thing i took a look on was the layout of the stack frame. Unfortunately I am not able to find the return address. Consider the following example:
void foo
(int b)
{
int c = 3;
}
int main
(int argc, char **argv)
{
int a = 1;
foo(2);
a = 4;
}
I have compiled it with:
gcc exploit_me.c -g -O0 -o exploit_me
Debugging the code with gdb gives me the following information:
gdb exploit_me
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux-gnueabihf".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/pi/_development/buffer_overflow/exploit_me...done.
(gdb) b 4
Breakpoint 1 at 0x83a0: file exploit_me.c, line 4.
(gdb) run
Starting program: /home/pi/_development/buffer_overflow/exploit_me
Breakpoint 1, foo (b=2) at exploit_me.c:4
4 int c = 3;
(gdb) disas foo
Dump of assembler code for function foo:
0x00008390 <+0>: push {r11} ; (str r11, [sp, #-4]!)
0x00008394 <+4>: add r11, sp, #0
0x00008398 <+8>: sub sp, sp, #20
0x0000839c <+12>: str r0, [r11, #-16]
=> 0x000083a0 <+16>: mov r3, #3
0x000083a4 <+20>: str r3, [r11, #-8]
0x000083a8 <+24>: add sp, r11, #0
0x000083ac <+28>: pop {r11}
0x000083b0 <+32>: bx lr
End of assembler dump.
(gdb) info r
r0 0x2 2
r1 0xbefff804 3204446212
r2 0xbefff80c 3204446220
r3 0x1 1
r4 0x0 0
r5 0x0 0
r6 0x82e4 33508
r7 0x0 0
r8 0x0 0
r9 0x0 0
r10 0xb6fff000 3070226432
r11 0xbefff69c 3204445852
r12 0xb6fc0000 3069968384
sp 0xbefff688 0xbefff688
lr 0x83d8 33752
pc 0x83a0 0x83a0 <foo+16>
cpsr 0x60000010 1610612752
(gdb) disas main
Dump of assembler code for function main:
0x000083b4 <+0>: push {r11, lr}
0x000083b8 <+4>: add r11, sp, #4
0x000083bc <+8>: sub sp, sp, #16
0x000083c0 <+12>: str r0, [r11, #-16]
0x000083c4 <+16>: str r1, [r11, #-20]
0x000083c8 <+20>: mov r3, #1
0x000083cc <+24>: str r3, [r11, #-8]
0x000083d0 <+28>: mov r0, #2
0x000083d4 <+32>: bl 0x8390 <foo>
0x000083d8 <+36>: mov r3, #4
0x000083dc <+40>: str r3, [r11, #-8]
0x000083e0 <+44>: mov r0, r3
0x000083e4 <+48>: sub sp, r11, #4
0x000083e8 <+52>: pop {r11, pc}
End of assembler dump.
(gdb) x/12xw $sp
0xbefff688: 0x00000000 0x00000002 0x00008360 0x00008438
0xbefff698: 0xb6fc1b80 0xbefff6b4 0xbefff804 0x00000001
0xbefff6a8: 0x00000000 0x00000001 0x00000000 0xb6eac81c
According to that the link register which holds the return address is set to the address 0x83d8
lr 0x83d8 33752
which is indeed the correct address for the next instruction in main:
0x000083d8 <+36>: mov r3, #4
However the stack (see end of gdb output) does not contain the return address preventing an buffer overflow attack.
Is it by design that the return address is only held in the link register and not being pushed to the stack or am I missing something?