This demo corresponds to the **Buffer Overflow: Code Execution** slide of the Software Security lecture.
The function `mystr()` is vulnerable as it has a buffer overflow when calling `fread()` with a wrong maximum lenght: only 512B would fit into the buffer but 1024B are passed as maximum length argument.
Attackers can therefore overflow the buffer `char mystr[512]` by providing input files larger than 512B.
**NOTE:** Before starting here, make sure you have your `.gdbinit` file configured correctly (see Moodle).
## Demo usage
To compile the demo, use an x64 system with `gcc` and `nasm` installed and invoke `make`. Then:
`./bufoverflow <filename>`
If the file is too large, the program should receive a segmentation fault during execution.
You can then execute the program using the gdb command `run`. The program will execute until hitting the breakpoint. If you don't see registers or assembly you, simply enter `layout asm` and `layout regs`. You should then see the program before executing the `mystr` function prologue. Now, you can single-step using the `gdb` command `ni`. Single-step until after the function prologue (i.e., right after`sub rsp,0x200`). You then see the stack frame looking at `rbp` and `rsp`, where `rsp` points to the top of the stack and thus the single local function variable (the 512B buffer) in our function. Note down this value (in my case, `0x7fffffffe090`) and exit the debugger with SIGINT (i.e., CTRL+D) or using `exit` (noone does that). Update the last line of the shellcode accordingly (the `dq` contains the stack pointer).
It should start with a (long) `nop` chain, followed by the system call, the shell string (misinterpreted as code) and the shellcode pointer (likewise misinterpreted as code).
Once you're satisfied, invoke
`gdb --args ./bufoverflow ./shellcode`
and then use the `run` command to get your shell.
Exit with SIGINT (CTRL+D); the first SIGINT will exit the shell, the second the debugger.
Second, the stack pointer you obtained using `gdb` is invalid when the program is being run without `gdb`.
This is as `gdb` places environment variables on the stack that change (decrease!) the stack (i.e., `rsp` value).
There are (at least) two solutions to this problem:
#### Variant A: Guesstimate the right stack address
We can take into account that `gdb` places environment variables that change (decrease!) the `rsp` value (see [here](https://stackoverflow.com/questions/17775186/buffer-overflow-works-in-gdb-but-not-without-it) for details and possible workarounds that however only work for programs without arguments).
Thankfully, given that we have sufficient room for a `nop` sled in our sled, we can adopt to this and try to guesstimate a valid `rsp` value.
Try to increase the value by 256B (0x100).
This address should now point somewhere in the middle of our shellcode, i.e., into our NOP sled.
Then recompile the shellcode and give it a try.
#### Variant B: Inspecting a core dump.
If you're really after the exact correct `rsp` value, you can also record a so-called `core` dump of the vulnerable program upon crash, and then inspect the core dump using `gdb`.
To enable core dumps, run:
`ulimit -S -c unlimited`
Then, run the program and let it crash.
`setarch `uname -m` -R ./bufoverflow ./shellcode`
Now you should see a file called `core`, which is our core dump. We can inspect this using `gdb`:
`gdb ./bufoverflow ./core`
By inspecting the registers or memory content, you may be able to find out the correct `rsp` value. Note however that the core dump was taken *after* the function's epilogue and hence the `rbp` and `rsp` values will be clobbered. So it's always a little nasty to find the exact value and there's no systematic answer how to find it.