Skip to content

Instantly share code, notes, and snippets.

@lionaneesh
Created December 23, 2019 10:57
Show Gist options
  • Save lionaneesh/9b4bafffecb8d5751752674bc2fff11e to your computer and use it in GitHub Desktop.
Save lionaneesh/9b4bafffecb8d5751752674bc2fff11e to your computer and use it in GitHub Desktop.
Solution for EMU 2.0, X-Mas CTF 2019, parsing a custom 8bit RISC micro-processor.
state = {'a': 0, 'pc': 0x100}
mem = []
blocked_addrs = []
def parse_opcode(opcode, arg):
global state
global mem
global blocked_addrs
jumped = False
x = int(arg, base=16)
if opcode == "00":
state['a'] += x
state['a'] = state['a'] & 0xff
return "add", jumped
elif opcode == "01":
state['a'] = x
return "set_a", jumped
elif opcode == "02":
#print state['a'], x, state['a'] ^ x
state['a'] ^= x
return "xor_a", jumped
elif opcode == "03":
state['a'] |= x
return "or_a", jumped
elif opcode == "04":
state['a'] &= x
return "and_a", jumped
elif opcode[0] == "8":
state['a'] = int(''.join(mem[2*x:2*x+2]), base=16)
return "set_a_ptr", jumped
elif opcode[0] == "d":
#print "xor ptr:", x, 2*x
#print "xor ptr:", mem[2*x:2*x+2], state['a']
if x in blocked_addrs:
return "blocked, xor_xxx", jumped
mem[2*x:2*x+2] = list(hex(int(''.join(mem[2*x:2*x+2]), base=16) ^ state['a'])[2:].zfill(2))
#print "after xor ptr:", mem[2*x:2*x+2]
return "xor_xxx", jumped
elif opcode[0] == "f":
if x in blocked_addrs:
return "blocked, set_xxx", jumped
mem[2*x:2*x+2] = list(hex(state['a'])[2:].zfill(2))
return "set_xxx", jumped
elif opcode[0] == "2":
state['pc'] = x
jumped = True
return "jmp", jumped
elif opcode[0] == "3":
if state['a'] == 0:
state['pc'] = x
jumped = True
return "jmp_if_a0", jumped
elif opcode[0] == "4":
if state['a'] == 1:
state['pc'] = x
jumped = True
return "jmp_if_a1", jumped
elif opcode[0] == "5":
if state['a'] == 255:
state['pc'] = x
jumped = True
return "jmp_if_a255", jumped
elif opcode == "60":
if state['a'] == x:
state['a'] = 0
elif state['a'] < x:
state['a'] = 1
elif state['a'] > x:
state['a'] = 255
return "cmp_a", jumped
elif opcode[0] == "7":
xxx = int(''.join(mem[2*x:2*x+2]), base=16)
if state['a'] == xxx:
state['a'] = 0
elif state['a'] < xxx:
state['a'] = 1
elif state['a'] > xxx:
state['a'] = 255
return "cmp_a_ptr", jumped
elif opcode == "be":
if x == 0xef:
state['a'] = 0x42
state['pc'] = 0x100
jumped = True
return "jmp_100", jumped
else:
state['a'] -= 1
return "invalid", jumped
elif opcode[0] == "9":
blocked_addrs.append(x)
return "block_write", jumped
elif opcode[0] == "a":
blocked_addrs.remove(x)
return "unblock_write", jumped
elif opcode[0] == 'c':
xxx = int(''.join(mem[2*x:2*x+2]), base=16)
xxx = xxx ^ 0x42
#print "Before frob:", mem[2*x:2*x+2]
if x in blocked_addrs:
return "blocked write, frobnicate", jumped
mem[2*x:2*x+2] = list(hex(xxx)[2:].zfill(2))
#print "After frob:", mem[2*x:2*x+2]
return "frobnicate", jumped
elif opcode == "ee":
if x == 0xee:
return 'nop', jumped
else:
state['a'] -= 1
return 'invalid', jumped
elif opcode == "13":
if x == 0x37:
print chr(state['a'])
return "print", jumped
else:
state['a'] -= 1
return "invalid", jumped
else:
state['a'] -= 1
return "invalid", jumped
state['a'] &= 0xff
return opcode, jumped
fp = open("rom", "rb")
bs = fp.read()
mem = list('0' * 0x200 + bs.encode('hex').lower())
x = 0
while state['pc'] < len(bs):
if state['pc'] == 0x408:
break
x = state['pc'] * 2
opcode = ''.join(mem[x:x+2])
second = ''.join(mem[x+2:x+4])
argument = second
if opcode[0] == "8" or opcode[0] == "2" or opcode[0] == "3" or opcode[0] == "4" or opcode[0] == "5" or opcode[0] == "7" or opcode[0] == "9" or opcode[0] == "a" or opcode[0] == "c":
argument = opcode[1] + argument
elif opcode[0] == "d":
argument = opcode[1] + argument
elif opcode[0] == "f":
argument = opcode[1] + argument
ins, jumped = parse_opcode(opcode, argument)
# only increment 'pc' if last instruction was not a jmp
#print hex(x/2) + ">", ins, argument, ";", "a:", state['a']
if not jumped:
state['pc'] += 2
#x += 2
#print state['pc']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment