Created
November 29, 2020 14:45
-
-
Save hgarrereyn/9211df7766b1bc3a1372580dbd6c2ca5 to your computer and use it in GitHub Desktop.
monkey disassembler - Hitcon CTF 2020
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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