Buffer Overflow Attacks ROM Emporium Challenge Solutions Return Oriented Programming Buffer Overflow Attack

Return Oriented Programming – split – ROP Emporium

So today, we are going to look at the second challenge of ROP Emporium and that’s split. We are going to look at X86 and X86_64 version of the binary, reverse engineer it, analyzing the stack frame and finally capturing the flag. Let’s get into it.

Before Diving into this challenge, I would like to suggest to go through some basics of ROPgadgets. The GitHub descriptions says “This tool lets you search your gadgets on your binaries to facilitate your ROP exploitation. ROPgadgets supports ELF/PE/Mach-O/Raw formats on x86, x64, ARM, ARM64, PowerPC, SPARC, MIPS, RISC-V 64, and RISC-V Compressed architectures.” Make sure you familiar yourself with the ROPgadgets tool. It’s really very simple.

x86 Architecture

Attack Planning:

We have a two strings present in our binary. “/bin/ls” and “/bin/cat flag.txt”. But the system function executes “/bin/ls”. NX Enabled which means we can’t insert any malicious payload instead of “/bin/ls”. If you’re following the previous blog than the same exploit will work but does not print the flag instead it executes the “/bin/ls” command. Which means we need to replace the “/bin/ls” of the system function argument with “/bin/cat flag.txt” so that we can grab the flag.

checksec status of the given binary in kali linux

Looking at the image above, we can see that the NX enabled which means it will prevent us adding payloads onto the stack and any runtime stack execution is disabled. Now let’s get into gdb and list the functions attached to this binary.

gdb function list for return oriented programming buffer overflow attacks on ROP Emporium

Looking at the function list above, we have one interesting function (I did disassemble almost all the function before making this call) and that is ‘usefulFunction‘.

Disassembling the function using GDB on kali linux for ROP Emporium challenge

Disassembling the usefulFunction shows that there’s a system function. You can disassemble the pwnme and main function and notice you won’t see the system function in it. Anyways that’s fine. Printing the string form of what’s holding at the “0x08048615 <+9>: push 0x804870e” right before calling the system@plt function tells me that it stores “/bin/ls” string.

x/s within GDB prints the strings holding at the given address

Perfect. We will need to replace this with “/bin/cat flag.txt” in our final exploit. We’ll look into that later.

Finding the OffSet

So for calculating the OffSet, I was initially used gef as well as peda but I was getting different offset values for the same binary hence I switch to pattern_offset command on Kali. Here’s how I calculate the offset for x86 Binary.

If you are using gef or peda within GDB while following this article, you can always disabled loading your plugin by commenting out the gdb plugin in /home/ringbuffer/.gdbinit file.

Creating the pattern of 100 byets

Creating a pattern for Buffer Overflow exploits

Running the program with the give pattern.

Debugging the binary for buffer overflow attacks

Printing the registers in gdb using info register command.

Getting the list of registers and values inside the register in gdb

Notice the eip (Next Instruction) register holds the value 0x35624134. Now lets find out the offset based on the value we have seen here in EIP register.

offset calculation buffer overflow attack

So we have our offset 44. Let’s form up one liner to get the flag. We notice above that the ‘0x804870e‘ is pushed right before it call the system function when we disassemble the ‘usefulFunction’ and it is the string ‘/bin/ls’ command. We will need to first find the address of the “/bin/cat” command. To do this, I simply put the break point on ret in the main function and run the program with gdb-peda. Then entering the ‘find’ command retunes me the address of the “/bin/cat” command.

Locating the string within gdb

Cool! we have our memory location for the string “/bin/cat flag.txt”. The one liner exploit is really simple as follow:

The one liner simply adds b”A”*44 following to the address of the system function and address of the string “/bin/cat”. Great! We have got our flag. Now we can form up a working exploit as follows:

┌──(ringbuffer㉿kali)-[~/Downloads/BufferOverFlow/split32]
└─$ more exploit.py 
from pwn import *
p = process('./split32')
payload = b"A"*44 + p32(0x0804861a) + p32(0x804a030)
p.send(payload)
p.interactive()
Executing the exploit for ROP Emporium split challenge

If you notice, for x86 Architecture, we do not use ROPgadgets and the reason is that the binary allowed us to alter the string at the given address by replacing “/bin/ls” with “/bin/cat” However, that is not the case with X86_64 Architecture.

x86_64 Architecture

OffSet Calculation

Again, I’m using the same pattern_offset method to calculate the offset but for this binary, we are going to take the address of the RBP (Base Pointer) register instead of the RIP registers because the RIP register points to the pwnme function. Here’s my offset calculation.

OffSet calculation for 64 bit binary in gdb

So we have our offset 32 plus 8 bytes for padding which makes it 40;

Time to play with ROPgadgets

The plan here is to find “pop” instructions within binary and when program encounter the payload, it jump controls to the pop instructions which then points to the memory address of “/bin/cat flag.txt” following to that jump back to the execution of the system function inside the ‘usefulFunction’ method.

ROPgadgets to find the pop instruction

So we have the memory address of our ‘pop rdi’ instruction in the memory. The structure of our exploit is as follows:

40 bytes of A + address of pop rdi instruction + address of the string “/bin/cat” instruction + address of the “system” function

split ROP Buffer overflow one liner exploit to capture the flag

Bingo! so our one liner goes into the file called payload1 and then running the binary importing the payload returns the flag right after the “Thank you!” word.

We can form an exploit as follows:

from pwn import *
context.bits = 64
p = process('./split')
system_addr = 0x000000000040074b
bincat_addr = 0x601060
poprdi_addr = 0x00000000004007c3
payload = b"A"*40 + p64(poprdi_addr) + p64(bincat_addr) + p64(system_addr)
p.send(payload)
p.interactive()
64 bit architecture ROP emporium payload execution

We have got our flag.

@ringbuffer

Some of the latest posts