# Stack Buffer Overflow

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/servers-and-cloud-computing/exploiting-stack-buffer-overflow-aarch64/)
- [Introduction: "Smashing the stack"](https://learn.arm.com/learning-paths/servers-and-cloud-computing/exploiting-stack-buffer-overflow-aarch64/introduction/)
- [Docker Setup](https://learn.arm.com/learning-paths/servers-and-cloud-computing/exploiting-stack-buffer-overflow-aarch64/setup/)
- [Frame Layout](https://learn.arm.com/learning-paths/servers-and-cloud-computing/exploiting-stack-buffer-overflow-aarch64/frame-layout/)
- [Stack Buffer Overflow](https://learn.arm.com/learning-paths/servers-and-cloud-computing/exploiting-stack-buffer-overflow-aarch64/buffer-overflow/)
- [Redirect control flow](https://learn.arm.com/learning-paths/servers-and-cloud-computing/exploiting-stack-buffer-overflow-aarch64/redirect-control-flow-1/)
- [Answers to exercises](https://learn.arm.com/learning-paths/servers-and-cloud-computing/exploiting-stack-buffer-overflow-aarch64/exercise-answers/)
- [Next Steps](https://learn.arm.com/learning-paths/servers-and-cloud-computing/exploiting-stack-buffer-overflow-aarch64/_next-steps/)

Arrays that are local function variables are allocated on the stack. When a programming error results in the program writing to an array index beyond the size of that array, a [stack buffer overflow](https://en.wikipedia.org/wiki/Stack_buffer_overflow) happens.

Using a file editor, save the contents of the program shown below into a file named `stack-buffer-overflow.c`:

```c
#include <string.h>

__attribute__((noinline))
char f(char *src) {
    char buffer[8];
    strcpy(buffer, src);
    return buffer[2];
}

// Note that a 0 byte is automatically appended.
//                     00000000011111111112222
//                     12345678901234567890123
char many_chars[24] = "These are 24 chars. yes";
int main() {
    f(many_chars);
    return 0;
}
```

Compile it with the following command at your docker prompt:

```bash
clang -g -O1 stack-buffer-overflow.c -o stack-buffer-overflow
```

Now, run this program:

```bash
./stack-buffer-overflow
__output__ 
Bus error
```

The program crashed with a bus error. What happened exactly?

### Deep dive using a debugger

Let’s use the gdb debugger to figure out why the program crashed with a bus error. Start the gdb debugger:

```bash
gdb -q ./stack-buffer-overflow
__output__ 
Reading symbols from ./stack-buffer-overflow...
(gdb)
```

Put a breakpoint on the first instruction of function `f`. If you simply execute `break f` at the gdb prompt, it will set the breakpoint after the function prologue. You don’t want to do that, as you need to investigate what happens during the function prologue. To set a breakpoint, perform the following steps at the gdb prompt and then run:

```bash
(gdb) break main
__output__ 
Breakpoint 1 at 0x784: file stack-buffer-overflow.c, line 15.
```

```bash
(gdb) run
__output__ 
Starting program: /armlearningpaths/stack-buffer-overflow
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at stack-buffer-overflow.c:15
15          f(many_chars);
```

Look at the disassembly of function `f`:

```bash
(gdb) disass f
__output__ 
Dump of assembler code for function f:
   0x0000aaaaaaaa0754 <+0>:     sub     sp, sp, #0x20
   0x0000aaaaaaaa0758 <+4>:     stp     x29, x30, [sp, #16]
   0x0000aaaaaaaa075c <+8>:     add     x29, sp, #0x10
   0x0000aaaaaaaa0760 <+12>:    mov     x1, x0
   0x0000aaaaaaaa0764 <+16>:    add     x0, sp, #0x8
   0x0000aaaaaaaa0768 <+20>:    bl      0xaaaaaaaa0630 <strcpy@plt>
   0x0000aaaaaaaa076c <+24>:    ldp     x29, x30, [sp, #16]
   0x0000aaaaaaaa0770 <+28>:    ldrb    w0, [sp, #10]
   0x0000aaaaaaaa0774 <+32>:    add     sp, sp, #0x20
   0x0000aaaaaaaa0778 <+36>:    ret
End of assembler dump.
```

This shows that the first instruction of function `f` is located at address `0x0000aaaaaaaa0754`. Now you can explicitly put a breakpoint there:

```bash
(gdb) break *0x0000aaaaaaaa0754
__output__ 
Breakpoint 2 at 0xaaaaaaaa0754: file stack-buffer-overflow.c, line 4.
```

Continue running the program so it runs until the start of function `f`, where it should hit the breakpoint on the first instruction.

```bash
(gdb) cont
__output__ 
Continuing.
Breakpoint 2, f (src=0xaaaaaaab1038 <many_chars> "These are 24 chars. yes") at stack-buffer-overflow.c:4
4       char f(char *src) {
```

You can check what the value of the key register `sp`, `x29` and `x30` is before any instructions are executed in function `f`.

```bash
(gdb) info registers sp x29 x30
__output__ 
sp             0xfffffffff5a0      0xfffffffff5a0
x29            0xfffffffff5a0      281474976708000
x30            0xaaaaaaaa0790      187649984432016
```

Now, step through the 3 instructions in the function prologue:

```bash
(gdb) nexti 3
__output__ 
0x0000aaaaaaaa0760 in f (src=0xaaaaaaab1038 <many_chars> "These are 24 chars. yes") at stack-buffer-overflow.c:4
4       char f(char *src) {
```

What have the 3 instructions in the prologue done?

1. `sub sp, sp, #0x20`
   - Moves the stack pointer downwards by `0x20` = 32 bytes. Looking at the source code and disassembly of function `f`, you expect that 2 times 8 bytes = 16 bytes are needed to store `x29` and `x30`. Furthermore array `buffer` is 8 bytes long. So, in total 24 bytes should be needed on the frame for function `f`. Why does the code reserve 32 bytes then? The [AArch64 PCS ABI](https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#6451universal-stack-constraints) specifies that the stack pointer must always be aligned to a 16-byte boundary, so the compiler has no choice but to round up the minimum of 24 bytes to the next higher 16-byte boundary, which is 32.

2. `stp x29, x30, [sp, #16]`
   - Stores the value of `x29` and `x30` on the stack as they will get clobbered by the call to `strcpy`.

3. `add x29, sp, #0x10`
   - Sets the frame pointer (always in register `x29`) for the frame of function `f` to be 16 bytes (`0x10`) higher than the stack pointer.

### Exercise 3
Draw the frame layout of function `f` at this point, including where the stack pointer and the frame pointer point to.

The answer to this exercise can be found in the [Answers section](https://learn.arm.com/learning-paths/servers-and-cloud-computing/exploiting-stack-buffer-overflow-aarch64/exercise-answers/#answer-to-exercise-3).

Let’s print the content of the frame `f` at this point. The frame is 32 bytes long. Let’s print it as if it were 4 64-bit values:

```bash
(gdb) x/4gx $sp
__output__ 
0xfffffffff580: 0x0000aaaaaaab0dd0      0x0000fffff7ffe040
0xfffffffff590: 0x0000fffffffff5a0      0x0000aaaaaaaa0790
```

Then the old value of `x29` is `0x0000fffffffff5a0` matches the value printed by gdb when you printed the value at the start of the function. Similarly, the value of `x30` on the stack also matches with what was printed at the start of the function.

### strcpy writing beyond the bounds of the buffer

In the stack layout you have drawn in exercise 3, you see that 8 bytes have been allocated on the stack for `buffer`. Immediately after that, the old values that need to be restored at the end of the function of `x29` (the frame pointer) and `x30` (the return address) are stored.

If you look again at the source code at the start of this section, you can see that `strcpy` is going to write a string of 24 bytes in `buffer`. Now that you know the stack layout, it is clear that the old values of `x29` and `x30` on the stack will be overwritten with bytes from the copied string. Let’s see if you can see that using the debugger.

```bash
(gdb) nexti
__output__ 
6           strcpy(buffer, src);
```

```bash
(gdb) nexti
__output__ 
0x0000aaaaaaaa0768      6           strcpy(buffer, src);
```

You are now right before the call to the `strcpy` function. Let it execute. After that you can check if the values of the saved `x29` and `x30` registers on the stack get overwritten.

```bash
(gdb) nexti
__output__ 
7           return buffer[2];
```

```bash
(gdb) x/4gx $sp
__output__ 
0xfffffffff580: 0x0000aaaaaaab0dd0      0x7261206573656854
0xfffffffff590: 0x6168632034322065      0x00736579202e7372
```

Indeed, the values of where `x29` and `x30` are stored have changed! Let’s print out this same memory, interpreted as ASCII characters to see if those hexadecimal numbers correspond to the expected string in the source program.

```bash
(gdb) x/32c $sp
__output__ 
0xfffffffff580: -48 '\320'      13 '\r' -85 '\253'      -86 '\252'      -86 '\252'      -86 '\252'      0 '\000'        0 '\000'
0xfffffffff588: 84 'T'  104 'h' 101 'e' 115 's' 101 'e' 32 ' '  97 'a'  114 'r'
0xfffffffff590: 101 'e' 32 ' '  50 '2'  52 '4'  32 ' '  99 'c' 104 'h' 97 'a'
0xfffffffff598: 114 'r' 115 's' '.'  32 ' '  121 'y' 101 'e' 115 's' 0 '\000'
```

Indeed!

The next instruction that is executed, `ldp x29, x30, [sp, #16]`, will restore the old values of `x29` and `x30` from the stack.

```bash
(gdb) nexti
__output__ 
0x0000aaaaaaaa0770 in f (src=<optimized out>) at stack-buffer-overflow.c:7
7           return buffer[2];
```

```bash
(gdb) info registers sp x29 x30
__output__ 
sp             0xfffffffff580      0xfffffffff580
x29            0x6168632034322065  7018969009222721637
x30            0x736579202e7372    32481193227088754
```

Indeed, registers `x29` and `x30` do not contain the value that they had at the start of the function. They were supposed to have those values by now though.

The return `ret` instruction at the end of the function uses the value in register `x30` as the address to jump to. Let’s see what happens when you execute it.

```bash
(gdb) nexti
__output__ 
0x0000aaaaaaaa0774      7           return buffer[2];
```

```bash
(gdb) nexti
__output__ 
0x0000aaaaaaaa0778      7           return buffer[2];
```

```bash
(gdb) nexti
__output__ 
0x736579202e7372 in ?? ()
```

The program counter now points to `0x73657920202e7372`. It is not a valid address. It is not even a 4-byte aligned value, which the program counter always should be. That results in a “Bus error” signal when you continue to run the program:

```bash
(gdb) cont
__output__ 
Continuing.
Program received signal SIGBUS, Bus error.
0x00736579202e7372 in ?? ()
```
