Created
December 23, 2019 10:57
-
-
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.
This file contains hidden or 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
| 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