Last active
April 18, 2025 11:25
-
-
Save whitequark/e8c7ffab0208d1b033aae715488881d6 to your computer and use it in GitHub Desktop.
concolic execution engine written for https://crackmes.one/crackme/67f9bdc38f555589f3530a85
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
# /// script | |
# requires-python = "~=3.11" | |
# dependencies = [ | |
# "colored==2.3.0", | |
# "z3-solver==4.14.1.0" | |
# ] | |
# /// | |
import os | |
import sys | |
import code | |
import traceback | |
import readline | |
import datetime | |
import z3 | |
import colored as cl | |
from data import vm_code, vm_data | |
from parse import parse, disasm | |
def meow(locals): | |
print() | |
code.InteractiveConsole(locals).interact() | |
key = [z3.BitVec(f'k{n:02x}', 8) for n in range(0x20)] | |
goal = 0x30b # 'Welcome home :)' | |
fail = 0x31c # 'Have you forgotten it :(' | |
pc = 0x169 | |
# uncomment this to make it work; lack of state merging makes starting at 0x169 require | |
# a search of like 6**32 states, most of which are unsat | |
pc = 0x18e | |
fl = False, False, -1 | |
reg = [(0, -1) for _ in range(0x10)] | |
reg[4] = (0x20, -1) | |
mem = [(b, -1) for b in vm_data] | |
mem[0x40:0x60] = [(b, -1) for b in key] | |
# mem[0x40:0x60] = [(z3.BitVecVal(b, 8), -1) for b in b"()v3Ng34nce_I5_4n_1D10T5_g4m3_()"] | |
# mem[0x40:0x60] = [(b, -1) for b in b"()v3Ng34nce_I5_4n_1D10T5_g4m3_()"] | |
# mem[0x40] = (z3.BitVecVal(ord('('), 8), -1) | |
stp = 0 | |
out = "" | |
sym = set() | |
act = set() | |
stack = [ | |
(pc, fl, reg, mem, stp, act) | |
] | |
hashes = set() | |
solver = z3.SolverFor("QF_BV") # actually faster than the default! | |
def bind(val): | |
return val | |
const = z3.FreshConst(val.sort()) | |
solver.add(const == z3.simplify(val)) | |
return const | |
def format_val(val, fmt="", slow=os.getenv("VERBOSE") is not None): | |
if isinstance(val, int): | |
return format(val, fmt) | |
elif slow: | |
# val = z3.simplify(val) | |
if isinstance(val, z3.BitVecNumRef): | |
return f"{val.as_long():{fmt}}" | |
else: | |
return f"{val.sexpr()}" | |
else: | |
return f"{{...}}" | |
smt2 = [] | |
def add_smt2(): | |
smt2.append(list(act)) | |
def save_smt2(): | |
with open("concolic.smt2", "w") as f: | |
f.write(f"(set-option :produce-models true)\n") | |
f.write(f"(set-logic QF_BV)\n") | |
f.write(solver.to_smt2().replace("(check-sat)\n", "")) | |
for act in smt2: | |
f.write(f"(check-sat-assuming ({' '.join(map(lambda x: x.sexpr(), act))}))\n") | |
f.write(f"(get-value ((concat {' '.join(map(lambda x: x.sexpr(), key))})))\n") | |
def solve_with(active): | |
return solver.check(*act) | |
def get_key(): | |
try: | |
model = solver.model() | |
except: | |
return "" | |
chars = "" | |
for bv in key: | |
k = z3.simplify(model[bv]) | |
if isinstance(k, z3.BitVecNumRef): | |
chars += chr(k.as_long()) | |
else: | |
chars += "." | |
return chars | |
def execute(pc, step, instr): | |
global fl, reg, mem, stp, act, key | |
# for val, val_pc in reg: | |
# if isinstance(val, int): | |
# assert val in range(0, 0x100000000) | |
# elif isinstance(val, z3.BitVecRef): | |
# assert val.size() == 32 | |
# else: | |
# assert False, f"Invalid type {val!r}" | |
# for val, val_pc in mem: | |
# if isinstance(val, int): | |
# assert val in range(0, 0x100) | |
# elif isinstance(val, z3.BitVecRef): | |
# assert val.size() == 8 | |
# else: | |
# assert False, f"Invalid type {val!r}" | |
opcode, modeA, operA, modeB, operB = parse(instr) | |
if modeA == 0: | |
def getA(): | |
val, pc = reg[operA] | |
if isinstance(val, z3.BitVecRef): | |
assert val.size() == 32 | |
print(f"\tr{operA:X}\t= {format_val(val, '08x')} ; from {pc:x}") | |
return val | |
def setA(val): | |
if isinstance(val, z3.BitVecRef): | |
assert val.size() == 32 | |
elif isinstance(val, int): | |
val = val & 0xffffffff | |
print(f"\t{cl.Fore.red}r{operA:X}\t← {format_val(val, '08x')}{cl.Style.reset}") | |
reg[operA] = val, pc | |
elif modeA == 1: | |
def getA(): | |
val, pc = mem[operA] | |
if isinstance(val, z3.BitVecRef): | |
assert val.size() == 8 | |
val = z3.ZeroExt(24, val) | |
print(f"\t[{operA:X}]\t= {format_val(val, '02x')} ; from {pc:x}") | |
return val | |
def setA(val): | |
if isinstance(val, z3.BitVecRef): | |
assert val.size() == 32 | |
val = bind(z3.Extract(7, 0, val)) | |
elif isinstance(val, int): | |
val = val & 0xff | |
print(f"\t{cl.Fore.red}[{operA:02X}]\t← {format_val(val, '02x')}{cl.Style.reset}") | |
mem[operA] = val, pc | |
else: | |
assert False, "Undefined modeB" | |
if modeB == 0: | |
def getB(): | |
val, pc = reg[operB] | |
if isinstance(val, z3.BitVecRef): | |
assert val.size() == 32 | |
print(f"\tr{operB:X}\t= {format_val(val, '08x')} ; from {pc:x}") | |
return val | |
elif modeB == 1: | |
def getB(): | |
val, pc = mem[operB] | |
if isinstance(val, z3.BitVecRef): | |
assert val.size() == 8 | |
val = z3.ZeroExt(24, val) | |
print(f"\t[{operB:X}]\t= {format_val(val, '02x')} ; from {pc:x}") | |
return val | |
elif modeB == 2: | |
def getB(): | |
return operB | |
else: | |
assert False | |
match opcode: | |
case 0x0: # mov | |
setA(getB()) | |
case 0x1: # movi | |
valB = getB() | |
if modeA == 0: | |
if isinstance(valB, int): | |
val, val_pc = mem[valB] | |
if isinstance(val, int): | |
setA(val) | |
else: | |
setA(z3.ZeroExt(24, val)) | |
else: | |
addr = z3.Extract(7, 0, valB) | |
if True: | |
all_mem = z3.Concat(*[ | |
z3.BitVecVal(val, 8) if isinstance(val, int) else val | |
for val, val_pc in reversed(mem) | |
]) | |
data = z3.Extract(7, 0, z3.LShR(all_mem, | |
z3.Concat(z3.ZeroExt(8 * 255 - 3, addr), z3.BitVecVal(0, 3)))) | |
elif True: | |
addr = z3.simplify(addr) | |
assert addr.decl().name() == 'concat' | |
assert addr.arg(0).as_long() == 8 | |
assert addr.arg(0).size() == 4 | |
all_mem = z3.Concat(*[ | |
z3.BitVecVal(val, 8) if isinstance(val, int) else val | |
for val, val_pc in reversed(mem[0x80:0x90]) | |
]) | |
addr = z3.Extract(3, 0, addr) | |
data = z3.Extract(7, 0, z3.LShR(all_mem, | |
z3.Concat(z3.ZeroExt(8 * 15 + 1, addr), z3.BitVecVal(0, 3)))) | |
else: | |
addr = z3.simplify(addr) | |
assert addr.decl().name() == 'concat' | |
assert addr.arg(0).as_long() == 8 | |
assert addr.arg(0).size() == 4 | |
data = z3.BitVecVal(0, 8) | |
for idx, (val, val_pc) in enumerate(mem): | |
if idx in range(0x80, 0x90): | |
data = z3.If(addr == idx, val, data) | |
setA(z3.ZeroExt(24, data)) | |
elif modeA == 1: | |
addr, addr_pc = mem[operA] | |
assert isinstance(addr, int) | |
print(f"\t[{format_val(addr, '02X')}]\t= {format_val(valB, '02x')}") | |
if isinstance(valB, int): | |
mem[addr] = valB, pc | |
else: | |
mem[addr] = bind(z3.Extract(7, 0, valB)), pc | |
case 0x2: # add | |
setA(getA() + getB()) | |
case 0x3: # sub | |
setA(getA() - getB()) | |
case 0x4: # mul | |
assert False, "Multiplication never actually used" | |
setA(getA() * getB()) | |
case 0x5: # mod | |
valA, valB = getA(), getB() | |
assert bin(valB).count("1") == 1, "(Non-power-of-2) modulo never actually used" | |
if isinstance(valA, int) and isinstance(valB, int): | |
setA(valA % valB) | |
else: | |
setA(z3.URem(valA, valB)) | |
case 0xb: # and | |
setA(getA() & getB()) | |
case 0xc: # or | |
setA(getA() | getB()) | |
case 0xd: # xor | |
setA(getA() ^ getB()) | |
case 0xe: # shl | |
setA(getA() << getB()) | |
case 0xf: # ushr | |
valA, valB = getA(), getB() | |
if isinstance(valA, int) and isinstance(valB, int): | |
setA(valA >> valB) | |
else: | |
setA(z3.LShR(valA, valB)) | |
case 0x6: # write | |
assert modeA == 1 and modeB == 2 | |
# chars = chr(getA()) * getB() | |
# print(f" write\t{chars!r}") | |
case 0x7: # read | |
assert modeA == 1 and modeB == 0 | |
for offset in range(getB()): | |
key.append(val := z3.BitVec(f'k{offset:02x}', 8)) | |
print(f" [{operA + offset:02x}]\t= {val!r}") | |
# solver.add((val >= 0x30) & (val <= 0x39)) | |
# mem[operA + offset] = val, pc | |
mem[operA + offset] = z3.BitVecVal(b"()v3Ng34nce_I5_4n_1D10T5_g4m3_()"[offset], 8), pc | |
# solver.add(key[0] == 0x33) | |
# solver.add(key[1] == 0x32) | |
# solver.add(z3.Concat(*key) == int.from_bytes(b"()v3Ng34nce_I5_4n_1D10T5_g4m3_()")) | |
case 0x9: # cmp | |
valA, valB = getA(), getB() | |
fl_eq = (valA == valB) | |
if isinstance(valA, int) and isinstance(valB, int): | |
fl_lt = (valA < valB) | |
else: | |
fl_lt = z3.ULT(valA, valB) | |
print(f"\tfl\t← {format_val(fl_eq, 'd')}, {format_val(fl_lt, 'd')}") | |
fl = fl_eq, fl_lt, pc | |
case 0xa: # br | |
fl_eq, fl_lt, fl_pc = fl | |
match getB(): | |
case 0x40: | |
taken = True | |
case 0x20: | |
taken = False | |
case 0x04: | |
print(f"\tfl.lt\t= {format_val(fl_lt, 'd')} ; from {fl_pc:x}") | |
taken = fl_lt | |
case 0x02: | |
print(f"\tfl.eq\t= {format_val(fl_eq, 'd')} ; from {fl_pc:x}") | |
print(f"\tfl.lt\t= {format_val(fl_lt, 'd')} ; from {fl_pc:x}") | |
if isinstance(fl_eq, bool) and isinstance(fl_lt, bool): | |
taken = not fl_lt and not fl_eq | |
else: | |
taken = z3.And(z3.Not(fl_lt), z3.Not(fl_eq)) | |
case 0x01: | |
print(f"\tfl.eq\t= {format_val(fl_eq, 'd')} ; from {fl_pc:x}") | |
taken = fl_eq | |
case _: | |
assert False, "Branch condition must be one-hot immediate" | |
target = getA() | |
if isinstance(taken, z3.BoolRef): | |
print(f" {cl.Fore.cyan}split {format_val(taken)} " | |
f"(t={target:x} f={pc + 1:x}){cl.Style.reset}") | |
sym.add(act_t := z3.Bool(f"{step}:{pc:x}#t")) | |
solver.add(z3.Implies(act_t, taken == True)) | |
stack.append((target, fl, list(reg), list(mem), stp + 1, {*act, act_t})) | |
sym.add(act_f := z3.Bool(f"{step}:{pc:x}#f")) | |
solver.add(z3.Implies(act_f, taken == False)) | |
stack.append((pc + 1, fl, list(reg), list(mem), stp + 1, {*act, act_f})) | |
return | |
assert isinstance(taken, bool) | |
if taken: | |
color = cl.Fore.yellow if target > pc else cl.Fore.magenta | |
print(f"\t{color}pc\t← {target:x}{cl.Style.reset}") | |
return target | |
return pc + 1 | |
# c == 0x28 | |
# c == 0x29 | |
# c == 0x5f | |
# 0x7a - c < 0x1a : c > 0x60 | |
# 0x5a - c < 0x1a : c > 0x40 | |
# 0x39 - c < 0x0a : c > 0x30 | |
# goal = 0x187 | |
result = [] | |
while stack: | |
pc, fl, reg, mem, stp, act = stack.pop() | |
header = ' '.join(sorted((f'{var}' for var in act), key=lambda s: int(s.split(':')[0]))) | |
print(f"\n{cl.Fore.cyan}{{{header}}}{cl.Style.reset}") | |
# if solve_with(act) == z3.sat: | |
# print(f' {cl.Fore.hot_pink_2}{cl.Style.bold}sat {get_key()}{cl.Style.reset}') | |
while True: | |
# if pc in range(0x2ad, 0x30a, 3): | |
# add_smt2() | |
# if pc == 0x2ad: save_smt2("concolic1.smt2"); #pc = 0x30a | |
# if pc == 0x2b0: save_smt2("concolic2.smt2"); #pc = 0x30a | |
# if pc == 0x2b3: save_smt2("concolic3.smt2"); #pc = 0x30a | |
# if pc == 0x2b6: save_smt2("concolic4.smt2"); #pc = 0x30a | |
instr = vm_code[pc] | |
print(f"{stp}:\t{cl.Fore.green}{disasm(pc, *parse(instr))}{cl.Style.reset}\t" | |
f"; bn: {0x100+(pc<<2):x}; stack: {len(stack)}") | |
if pc == goal: | |
print(f"\t {cl.Fore.white}goal{cl.Style.reset}") | |
add_smt2(); save_smt2() | |
# print(mem[0x40][0].sexpr()) | |
result = solve_with(act) | |
print(f"{result} {get_key()!r}") | |
if result == z3.sat: | |
stack.clear() | |
break # success | |
else: | |
break # impossibility | |
if pc == fail: | |
print(f"\t {cl.Style.bold}fail{cl.Style.reset}") | |
break # failure | |
pc = execute(pc, stp, instr); stp += 1 | |
if pc is None: | |
break | |
for line_addr in range(0x40, 0x60, 0x20): | |
print(f"{line_addr:02x} |", end="") | |
for byte_addr in range(line_addr, line_addr + 0x20): | |
byte, byte_pc = mem[byte_addr] | |
if z3.is_bv_value(byte): | |
byte = z3.simplify(byte) | |
if z3.is_const(byte): | |
byte = byte.as_long() | |
if isinstance(byte, int): | |
print(f" {byte:02x}", end="") | |
else: | |
print(f" ??", end="") | |
print() |
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
vm_code = [995601494, 961915476, 3635759284, 241344097, 2330401257, 3184602320, 592360013, 3652537271, 3736293042, 2748265408, 7115374, 2714579148, 1881006354, 1678374667, 1127142191, 3917838728, 3299366572, 460819062, 1981540116, 1227151904, 3635759284, 2330335980, 1981538330, 3249296301, 124491626, 1260837671, 1028762962, 1546702397, 1227217188, 3449839009, 2582972918, 3266203823, 3502064060, 1429783865, 726055493, 792903497, 460818805, 276660604, 2731422671, 4271009425, 4018372232, 224435810, 3619309243, 1011920209, 2865183684, 327123574, 1429849402, 1611461133, 4204161687, 3901061252, 575648588, 2048322333, 2246645738, 2764584393, 3518841278, 828219482, 1210374183, 2632977393, 928687448, 2798270155, 4271009683, 3316143275, 2815112646, 2616593143, 1045671506, 23892079, 460818806, 2014701844, 642496074, 845062749, 1028763484, 3934747526, 3399900071, 3817763469, 3466747055, 2263554026, 124491370, 625521739, 3619374524, 2380274913, 1346158909, 1327685153, 2566130421, 527667058, 4237323665, 2967282142, 73963109, 3201445587, 1728837130, 1881006366, 3383057312, 1310973730, 3967843713, 3518841278, 4170542740, 2482962684, 2932031426, 1761998855, 1396621885, 1761933824, 4271074962, 642496328, 2748264907, 4137379482, 1981540120, 2881894596, 7114861, 2649820400, 2666663673, 592425290, 1761999108, 3934681991, 1546701883, 3834214284, 2666663667, 3184602320, 3518841264, 74028136, 327057532, 2213417711, 1310908195, 1244125996, 3817762955, 1678374152, 224435553, 3585689010, 3117754580, 1293998881, 1580452918, 427067509, 4154091416, 4036780191, 1277222434, 1862467331, 2229868012, 2449277951, 7115117, 4103693722, 3184537299, 1745156101, 1244060455, 1227217190, 393971324, 3753004212, 3232584108, 3249295789, 928687705, 4237388950, 90740334, 541962572, 1062448722, 4187318678, 2466185974, 3951524227, 1695151368, 1260902950, 2566129911, 961849683, 1998251036, 4254100625, 1914626847, 1110430508, 2881960641, 2633043442, 4154089883, 2449277690, 1778907910, 140810598, 2683440881, 2397249250, 310280829, 2748199887, 1260903204, 3702607024, 3801052044, 1379844154, 592360015, 3834213512, 1160369450, 3518841776, 258187106, 393906043, 410290295, 3784143744, 709344070, 3850925449, 2666663665, 811377233, 2983993565, 310281087, 1611526414, 3901062024, 3767300237, 2380340448, 327058045, 3784143753, 3502064060, 3552527037, 157587559, 4221004950, 3449839529, 659207755, 174496612, 2098261014, 327123581, 1227151393, 1628238345, 2313492964, 1862467331, 3034064091, 3282981027, 3901061508, 2566195444, 1645212428, 1828781581, 4237323409, 3416742566, 3349829289, 1076679201, 2632977649, 3316143529, 4170541462, 3669379259, 3333052075, 1964565785, 3333052073, 1479920432, 1897717789, 3383056551, 2848209095, 477137777, 2397183465, 3801052046, 1346158910, 3602532025, 1981539609, 2831431877, 978823765, 978758229, 2115235093, 90739817, 3316143529, 3266204321, 4287786131, 2865183686, 3767300493, 878224471, 1143592744, 3518775485, 861840223, 1661923853, 4287786143, 1045671762, 3050906840, 2229802215, 2246645736, 1011985744, 3917773189, 2263488233, 3552460984, 1998317338, 675592518, 1661989644, 2229801961, 2466120179, 3201511378, 608744779, 3801051531, 2179797484, 4070466461, 1914691864, 1045671762, 3736227773, 2616658421, 3017679583, 3568846263, 2984059871, 1745221892, 3767300495, 1210440491, 1463469627, 377128821, 978757716, 3333052075, 1127142189, 1761933836, 3702541489, 3702607026, 709344326, 642430244, 1496582709, 1260791591, 4187261589, 3483600034, 2649821168, 3266225583, 3984631937, 3201497043, 3151429335, 3502015421, 4220939671, 124412267, 343429241, 1728785418, 659254090, 995600470, 2948788163, 3552484543, 2714561229, 3901070212, 510889074, 124407147, 3201563602, 1045605715, 4187339156, 3619333304, 1546701105, 3184537553, 1210399268, 1914647582, 3767381900, 541938508, 4070553758, 3050947800, 2098259985, 845128798, 393965690, 1931411742, 2065054487, 2599815671, 895055704, 3067803355, 4254166672, 276648316, 3067802587, 1310932258, 477195120, 2599932918, 2865182918, 2162999789, 1761944580, 894977625, 541962828, 3535770558, 776099907, 3884685194, 3502020541, 293430140, 895042648, 3719384752, 2499399928, 1412962617, 1778789639, 3399924903, 40846190, 3535708351, 592360527, 3767301005, 168692270, 225719408, 4254100369, 2038264189, 1482511266, 2393547821, 791356628, 2945090933, 2709818235, 1281910647, 3183001336, 406404917, 420023311, 4167724884, 347127473, 2839166725, 2684619269, 883336024, 3227806309, 2223408309, 1097888373, 2839363367, 1240261352, 3284189913, 655824146, 4033111678, 2684685057, 2054715973, 740040217, 529238401, 629182084, 1033410520, 791291093, 523908277, 488118247, 2759888875, 2069779039, 2449673991, 3614670194, 2954107732, 3284584505, 991826060, 707732271, 1516133630, 3454856928, 453708553, 2979305092, 2190644112, 3972647897, 3790150123, 499961037, 152166673, 4225749982, 3378336077, 2216767269, 4025149930, 1482447964, 2998319798, 4109694452, 3688878815, 622930537, 507393341, 2444278717, 3519070923, 842216753, 2518885843, 3057796166, 774842413, 45527481, 404494300, 1383299186, 1885365355, 3974685567, 2544283051, 891560239, 1049594762, 1566136230, 3404718378, 960312002, 3353537836, 800833467, 2436184884, 83887232, 840111893, 3369655004, 3631050594, 2907261773, 1785621230, 2225447330, 975843118, 2127285819, 1637126544, 854847990, 2869887055, 100861827, 3888562880, 1719039090, 78754625, 3873695587, 35858212, 2643233160, 3019900175, 4282334522, 1364480148, 4292795102, 4192792044, 1401061511, 2341179273, 2442499989, 3048256800, 4058048229, 2302230333, 1788844444, 955841278, 3854681280, 1702196080, 1708446416, 769253341, 1351651990, 237645611, 3502294725, 11581108, 3661576509, 2825415278, 220802088, 3013780647, 3714869864, 82966512, 837940215, 2427761077, 85267216, 2268475442, 2237687394, 1267370124, 2709815685, 102109203, 2418026020, 1922470034, 703130350, 1041964570, 3653881804, 580097431, 2188800119, 96847811, 570884614, 2121164907, 2569613101, 4111472145, 4113839666, 2055107902, 856889360, 740827832, 1987279595, 387128812, 3097334626, 389168142, 3570782680, 507133501, 3853628857, 3655127843, 3606313996, 705626116, 4014687499, 909587258, 3690986489, 3565258121, 1599755685, 1180855709, 3336760816, 1067161051, 4059100413, 2996212372, 4054098092, 2324660336, 2878243185, 2393548211, 397655539, 3183327664, 975117086, 3649931653, 218630135, 2979371626, 3029442225, 1358298037, 4160156411, 1130783331, 2868837110, 4244239878, 2241900383, 873471799, 347193329, 1027422512, 1816677448, 1175656219, 3081944397, 3336760605, 1732463725, 10791652, 2391706243, 2427826614, 3955211191, 505026021, 2928313717, 389233670, 3632034364, 3772835053, 991894299, 3649931653, 3435775542, 3046154095, 36055402, 1976622736, 151522570, 2459145624, 1366390645, 3199117480, 792672309, 2643297668, 3489727495, 2026491086, 1759109073, 4164435262, 2576375963, 3013307295, 1736413050, 3871525059, 3589404912, 1240261548, 4227854592, 2258873692, 2613031403, 3173590062, 1155657696, 1593570809, 3180960152, 1664497190, 2829886035, 237708680, 322321207, 1643510013, 983470234, 774582123, 2861207177, 151849029, 3707566591, 808728884, 353443822, 2326765904, 1231839757, 169483294, 992619823, 2829144485, 824826158, 17430796, 2191157916, 305541687, 3269911527, 2878309006, 2028855525, 3227872097, 2964634187, 4124106353, 2911405193, 3746186842, 3206157342, 993933950, 1816938575, 1044070003, 1901155410, 1229734220, 556018395, 2208803160, 1985109035, 3199183275, 2898115256, 1887013245, 3385926102, 1364764765, 402780423, 2053003871, 4192000477, 3741054714, 4033112428, 145597353, 3537296342, 707731920, 1197698460, 3707303536, 319952415, 2679881650, 2885614318, 1094992260, 3097074836, 690760444, 2225382048, 3064439714, 1465822808, 2676389506, 3164116377, 360746384, 1993530582, 3503675605, 757671894, 3471500309, 2208737343, 2677776219, 2629679536, 3672038158, 3972909248, 152575517, 4110224889, 3353292761, 423440444, 2232491009, 3846196804, 2542967917, 3939418193, 2241962673, 3746187626, 2044580825, 1296582327, 1215128466, 570886648, 1968267086, 3662022298, 1475542256, 397655479, 549256659, 3846196802, 4267332702, 3227328267, 111390113, 1441923061, 1827713842, 1458765040, 1841874636, 4084149180, 1926748629, 347127476, 445039560, 2785152000, 865507474, 3545106462, 1033475995, 3531045235, 3966842374, 3897377615, 2419407665, 1760869533, 262907305, 2886206988, 43964204, 10791590, 2044515032, 2467185731, 1441923059, 532395455, 10344052, 3846196802, 2604544058, 1878245244, 1358232310, 1425080052, 1088262184, 680297102, 44542371, 934012294, 2335055916, 2902984204, 1322491073, 10857383, 44476578, 2600883756, 881893010, 815111057, 2283095168, 2027803615, 3829419588, 3377792980, 562334342, 3514071664, 3377727409, 3564142194, 1375009520, 3156309268, 1274012141, 747144844, 2249936576, 1290397675, 3227872097, 478271243, 4200550749, 2819359240, 1017247409, 2469804084, 612470661, 1456182239, 3547756660, 229156524, 4217847448, 3071417360, 4250490717, 4017236181, 1492972286, 1707200453, 934015151, 596019332, 2801995015, 1539742230, 2987858197, 2401969455, 1961407785, 3665719420, 4183642969, 934016334, 714047885, 3429459821, 1844555397, 713982092, 3155695132, 2368218632, 3753026739, 527592563, 2213465071, 1828723713, 2881941191, 2948785347, 2483020286, 2163020524, 2330445542, 811365469, 4287804563, 1429743161, 3635759796, 224434785, 2031364885, 3084591321, 0, 3753096370, 293431164, 3017732575, 4220946583, 1362936637, 2649867248, 327112574, 1778854150, 1127141679, 3249320877, 861894494, 3266282670, 241386338, 174542694, 4154177177, 1396580415, 3151426007, 3117689813, 4271092114, 1947808792, 1227152165, 845129054, 3151423703, 3884609928, 0, 0] | |
vm_data = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()\xd4\xce\xccmf\xa4\xa6\x97.^\xa0D\xd6\x8b\xc5dl\x04\xc6B>_\x10\x83IJ}\xb0\xdb\x85\x165\xcc<\xb4\xf1\xb5\xb7\x9a\xa3\x14\xcb%U~\xbe\x84n\xbb\xa4\x8e\x9c=\x96\xc2\xd8\xa8DY\x03vm\x05$\xc7\xf2~\xa9\xe3\xdb\xb0\x04,m1\x1a\x96OX\x85\x80@ \x10\x08\x04\x02\x01\x7f\xbf\xdf\xef\xf7\xfb\xfd\xfe\x14\xd6\x8c\x9e\x0c\x80\xcf\x909\xe2\x86C\x16\xf7\x84\x18R*\xefs\xaa\xc1H\xe1\xe5o\xc6\xdf\xcc\x96^\x02\xb5\xab\xe7\x8f&\xe7\x99O\x84\x8f\x97\xe2\x1a\xed\xaeK(D\xd8\x1b\x83b\x05\xfb\xd5k#\x86\x06\xe4\xc7\xce\xdd}\x8c\x18#\x11\xb2\xec\xfa\x8e\xfe\x16\xc6pl"\x008\xe0\x97\xbfO\xe6\xa8.,:\n\\/_ ' |
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
def parse(instr): | |
instr = 0xffffffff & ((((instr >> 0x10) & 0xff) * 0x1010101) ^ instr) | |
opcode = instr >> 0x1c | |
modeA = (instr >> 0x1b) & 1 | |
operA = (instr >> 8) & 0xff | |
modeB = (instr >> 0x19) & 3 | |
operB = (instr >> 0) & 0xff | |
# print(f"{instr:08x}: op={opcode:1x} mA={modeA} rA={operA} mB={modeB} rB={operB}") | |
return (opcode, modeA, operA, modeB, operB) | |
mnemonics = "mov movi add sub mul mod write read und cmp br and or xor shl ushr".split() | |
def disasm(addr, opcode, modeA, operA, modeB, operB): | |
if modeA == 0: | |
dst = f"r{operA:X}" | |
elif modeA == 1: | |
dst = f"[{operA:02X}]" | |
if modeB == 0: | |
src = f"r{operB:X}" | |
elif modeB == 1: | |
src = f"[{operB:02X}]" | |
elif modeB == 2: | |
src = f"{operB:02X}" | |
if opcode == 0x1: | |
if modeA == 0: | |
src = f"[{src}]" | |
elif modeA == 1: | |
dst = f"[{dst}]" | |
return f"{addr:<5x} {mnemonics[opcode]:8} {dst:8} {src}" | |
if __name__ == "__main__": | |
from data import vm_code | |
for addr, instr in enumerate(vm_code): | |
print(disasm(addr, *parse(instr))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment