split

64 bit

Let's run the executable to check what it does.

$ ./split
split by ROP Emporium
x86_64

Contriving a reason to ask user for data...
> 1111111
Thank you!

Exiting

It takes user input and then exits.

We can use the checksec utility in order to identify the security properties of the binary executable.

$ checksec split
[*] '/home/hacker/ropEmporium/split/split'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

There's two important properties we want to focus on here:

  • NX enabled: This means that the stack is not executable. Therefore we cannot use a shellcode injection.

  • No PIE (0x400000): This means that the executable is not positionally independent and it is always loaded at address 0x400000. So the code and memory regions will have the same address every time we run it.

Let's open the executable using gdb-pwndbg and look at the functions.

There is a function called usefulFunction. Let's disassemble it and see how useful it is.

usefulFunction()

We can see that the instruction at usefulFunction+9 makes a system call and that the instruction at usefulFunction+4 loads the argument.

So this system call executes /bin/ls which isn't what we want. We want it to execute /bin/cat flag.txt.

/bin/cat flag.txt

Let's search the string /bin/cat flag.txt.

We can link this string with our system call in order to read the flag.txt file.

In order to put this string into rdi, we will need a pop rdi gadget.

pop rdi gadget

We can find the gadget using the ROPgadget utility.

We can see that the address of the pop rdi gadget is 0x00000000004007c3.

Cyclic pattern

We now have to find the offset using a cyclic pattern.

Let's provide this as input.

The rbp register points to 0x6161616161616165 which is the little endian eaaaaaaa in ASCII.

Let's find the offset of this value in our cyclic pattern.

So the offset is 32 bytes.

Let's see how this looks on the stack.

Stack

We can see that if we increment the rbp by 8, it will point to the saved return address.

Therefore the distance between the buffer and the saved return address is offset+8 which is equal to 40.

Exploit requirements

We now have all the information we need to create an exploit.

All that remains is to link these pieces of information to create a ROP chain.

ROP chain

In this technique, we have to execute our instructions in a carefully chosen sequence:

  1. First we have to replace the return address with the address of the pop rdi gadget so that it is executed when pwnme returns.

  2. Then we have to chain it with the address of the /bin/cat flag.txt string so that it gets popped into the rdi register.

  3. Finally we chain it with the address of the system@plt call.

This is what the ROP chain would look like on the stack.

Exploit

Let's run the exploit.

32 bit

usefulFunction()

The arguments for a 32-bit function call are pushed on the stack. At usefulFunction+9, we can see the argument for the system call being pushed onto the stack.

Let's see what the argument is.

We have to replace this argument with /bin/cat flag.txt.

/bin/cat flag.txt

We can link this string with our system call in order to read the flag.txt file.

In this case we do not need a pop rdi gadget because as we saw the arguments are not stored in registers.

Cyclic pattern

We now have to find the offset using a cyclic pattern.

Let's provide this as input.

The ebp register points to 0x61616166 which is the little endian faaa in ASCII.

Let's find the offset of this value in our cyclic pattern.

So the offset is 40 bytes.

Let's see how this looks on the stack.

We can see that if we increment the ebp by 4, it will point to the saved return address.

Therefore the distance between the buffer and the saved return address is offset+4 which is equal to 44.

Exploit requirements

We now have all the information we need to create an exploit.

All that remains is to link these pieces of information to create a ROP chain.

ROP chain

In this technique, we have to execute our instructions in a carefully chosen sequence:

  1. First we have to replace the return address with the address of the system@plt call so that it is executed when pwnme returns.

  2. Then we have to chain it with the address of the /bin/cat flag.txt string so that it can act as the argument of the system@plt call.

  • This is what the ROP chain would look like on the stack.

Exploit

Let's run the exploit.

Last updated

Was this helpful?