writeups/2020/gctf/sprint/disassemble.py

171 lines
5.1 KiB
Python
Executable File

#!/usr/bin/env python3
import fileinput
import re
literalMove = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$(\d*)s%(\d*)\$hn$")
regMove = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$\*(\d*)\$s%(\d*)\$hn$")
regAdd = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$\*(\d*)\$s%1\$\*(\d*)\$s%(\d*)\$hn$")
regLiteralAdd = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$\*(\d*)\$s%1\$(\d*)s%(\d*)\$hn$")
literalRegAdd = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$(\d*)s%1\$\*(\d*)\$s%(\d*)\$hn$")
jump = re.compile(r"^%1\$(\d*)s%3\$hn$")
condJump = re.compile(r"^%(\d*)\$c%1\$(\d*)s%2\$c%4\$s%1\$(\d*)s%3\$hn$")
# The address of the instruction being read
addr = 0
def showRegisterDest(regRef):
if regRef == 6:
regStr = "(%r1)"
elif regRef >= 7 and regRef <= 23 and regRef % 2 == 1:
regStr = "%r{}".format(regRef // 2 - 2)
else:
print("bad destination: {}".format(regRef))
exit()
return regStr
def showRegisterSource(regRef):
if regRef == 5:
regStr = "(%r1)"
elif regRef >= 6 and regRef <= 22 and regRef % 2 == 0:
regStr = "%r{}".format(regRef // 2 - 2)
else:
print("bad source")
exit()
return regStr
for line in fileinput.input():
oldAddr = addr
addr += len(line)
m = literalMove.match(line)
if m:
nextAddr = int(m.group(1))
filler = int(m.group(2))
literal = int(m.group(3))
regRef = int(m.group(4))
if addr != nextAddr:
print("address is not the next instruction")
exit()
if nextAddr + filler != 0x10000:
print("first two numbers do not add to 0x10000")
exit()
dest = showRegisterDest(regRef)
print("{:04x}: mov 0x{:x}, {}".format(oldAddr, literal, dest))
continue
m = regMove.match(line)
if m:
nextAddr = int(m.group(1))
filler = int(m.group(2))
sourceRef = int(m.group(3))
destRef = int(m.group(4))
if addr != nextAddr:
print("address is not the next instruction")
exit()
if nextAddr + filler != 0x10000:
print("first two numbers do not add to 0x10000")
exit()
source = showRegisterSource(sourceRef)
dest = showRegisterDest(destRef)
print("{:04x}: mov {}, {}".format(oldAddr, source, dest))
continue
m = regAdd.match(line)
if m:
nextAddr = int(m.group(1))
filler = int(m.group(2))
source1Ref = int(m.group(3))
source2Ref = int(m.group(4))
destRef = int(m.group(5))
if addr != nextAddr:
print("address is not the next instruction")
exit()
if nextAddr + filler != 0x10000:
print("first two numbers do not add to 0x10000")
exit()
source1 = showRegisterSource(source1Ref)
source2 = showRegisterSource(source2Ref)
dest = showRegisterDest(destRef)
print("{:04x}: add {}, {}, {}".format(oldAddr, source1, source2, dest))
continue
m = regLiteralAdd.match(line)
if m:
nextAddr = int(m.group(1))
filler = int(m.group(2))
sourceRef = int(m.group(3))
literal = int(m.group(4))
destRef = int(m.group(5))
if addr != nextAddr:
print("address is not the next instruction")
exit()
if nextAddr + filler != 0x10000:
print("first two numbers do not add to 0x10000")
exit()
source = showRegisterSource(sourceRef)
dest = showRegisterDest(destRef)
print("{:04x}: add {}, 0x{:x}, {}".format(oldAddr, source, literal, dest))
continue
m = literalRegAdd.match(line)
if m:
nextAddr = int(m.group(1))
filler = int(m.group(2))
sourceRef = int(m.group(4))
literal = int(m.group(3))
destRef = int(m.group(5))
if addr != nextAddr:
print("address is not the next instruction")
exit()
if nextAddr + filler != 0x10000:
print("first two numbers do not add to 0x10000")
exit()
source = showRegisterSource(sourceRef)
dest = showRegisterDest(destRef)
print("{:04x}: add {}, 0x{:x}, {}".format(oldAddr, source, literal, dest))
continue
m = jump.match(line)
if m:
target = int(m.group(1))
if target == 0xfffe:
print("{:04x}: halt".format(oldAddr))
else:
print("{:04x}: jmp {:04x}".format(oldAddr, target))
continue
m = condJump.match(line)
if m:
sourceRef = int(m.group(1))
fill1 = int(m.group(2))
fill2 = int(m.group(3))
source = showRegisterSource(sourceRef)
zeroTarget = (fill1 + fill2 + 2) % 0x10000
nonzeroTarget = (fill1 * 2 + fill2 + 3) % 0x10000
if zeroTarget == addr:
print("{:04x}: jnz {}, {:04x}".format(oldAddr, source, nonzeroTarget))
elif nonzeroTarget == addr:
print("{:04x}: jz {}, {:04x}".format(oldAddr, source, zeroTarget))
else:
print("neither jump target is the next instruction")
exit()
continue
print(line[:-1])