Skip to content

Instantly share code, notes, and snippets.

@hgarrereyn
Created November 29, 2020 14:45
Show Gist options
  • Save hgarrereyn/9211df7766b1bc3a1372580dbd6c2ca5 to your computer and use it in GitHub Desktop.
Save hgarrereyn/9211df7766b1bc3a1372580dbd6c2ca5 to your computer and use it in GitHub Desktop.
monkey disassembler - Hitcon CTF 2020
import struct
# get symbols with https://github.com/pzl/ciqdb
sym = open('./run/info.txt', 'r').read()
sym = sym.strip().split('\n')
sym = sym[508:-8]
sym = [x.strip().split(': ') for x in sym]
sym = {int(v):s for v,s in sym}
def get_str(off):
o = ''
i = off
while dat[i] != 0:
o += chr(dat[i])
i += 1
return o
def getop(dat, off):
op = dat[off]
if False:
pass
elif op == 0: return 'NOP', 1
elif op == 2: return 'POPV', 1
elif op == 3: return 'ADD', 1
elif op == 4: return 'SUB', 1
elif op == 5: return 'MUL', 1
elif op == 6: return 'DIV', 1
elif op == 7: return 'AND', 1
elif op == 8: return 'OR', 1
elif op == 9: return 'MOD', 1
elif op == 10: return 'SHL', 1
elif op == 11: return 'SHR', 1
elif op == 12: return 'XOR', 1
elif op == 13: return 'GETV', 1
elif op == 14: return 'PUTV', 1
elif op == 16: return 'AGETV', 1
elif op == 17: return 'APUTV', 1
elif op == 20: return 'NEWA', 1
elif op == 21: return 'NEWC', 1
elif op == 22: return 'RETURN', 1
elif op == 26: return 'EQ', 1
elif op == 27: return 'LT', 1
elif op == 28: return 'LTE', 1
elif op == 29: return 'GT', 1
elif op == 30: return 'GTE', 1
elif op == 31: return 'NE', 1
elif op == 42: return 'FRPUSH', 1
elif op == 48: return 'GETM', 1
elif op == 1: return 'INCSP %d' % dat[off+1], 2
elif op == 15: return 'INVOKE %d' % dat[off+1], 2
elif op == 18: return 'LGETV %d' % dat[off+1], 2
elif op == 19: return 'LPUTV %d' % dat[off+1], 2
elif op == 43: return 'BPUSH %d' % dat[off+1], 2
elif op == 46: return 'DUP %d' % dat[off+1], 2
elif op == 53: return 'ARGC %d' % dat[off+1], 2
elif op == 25:
v = struct.unpack('>H', dat[off+1:off+3])[0]
return 'GOTO 0x%04X' % (off+v+3), 3
elif op == 41:
v = struct.unpack('>H', dat[off+1:off+3])[0]
return 'BF 0x%04X' % (off+v+3), 3
elif op == 24:
v = struct.unpack('>I', dat[off+1:off+5])[0]
return 'NEWS 0x%x (%s)' % (v, get_str(v)), 5
elif op == 37:
v = struct.unpack('>I', dat[off+1:off+5])[0]
return 'IPUSH 0x%x (%s)' % (v, sym[v] if v in sym else ''), 5
elif op == 39:
v = struct.unpack('>I', dat[off+1:off+5])[0]
return 'SPUSH 0x%x (%s)' % (v, sym[v] if v in sym else ''), 5
elif op == 49:
v = struct.unpack('>Q', dat[off+1:off+9])[0]
return 'LPUSH 0x%x (%s)' % (v, sym[v] if v in sym else ''), 9
return '???', 0
def disasm(dat, off):
idx = off
while True:
name, sz = getop(dat, idx)
print('%04X :: %s :: %s' % (
idx,
(' '.join(['%02X' % x for x in dat[idx:max(idx+sz,idx+1)]]) + ' '*15)[:15],
name
))
if sz == 0:
break
idx += sz
dat = open('./run/hitcon.prg', 'rb').read()
disasm(dat, 0x57a)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment