Created
November 19, 2017 12:04
-
-
Save ymgve/1540c8fb03ce8489d059202d2452900b to your computer and use it in GitHub Desktop.
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 sys, struct | |
def s2n(s): | |
if s.startswith("0x"): | |
if s.endswith("L"): | |
s = s[:-1] | |
n = int(s[2:], 16) | |
else: | |
n = int(s) | |
return n | |
def s2b(s, nbits=8): | |
n = s2n(s) | |
if n < 0 or n >= (1<<nbits): | |
raise Exception("num too large") | |
res = bin(n)[2:].rjust(nbits, "0") | |
return res | |
functions = [] | |
ram = [] | |
for line in open(sys.argv[1]): | |
line = line.split(";")[0].strip() | |
if len(line) == 0: | |
continue | |
tokens = line.split() | |
op = tokens[0].lower() | |
if op == "function": | |
function = [] | |
inscount = 0 | |
elif op == "end": | |
# emit function bits here | |
functions.append(function) | |
elif op == "blankram": | |
ram.extend([0] * s2n(tokens[1])) | |
elif op == "qword": | |
ram.append(s2n(tokens[1])) | |
elif op == "jmpz": | |
function.append("000" + s2b(tokens[1].replace("label", ""))) | |
elif op == "jmp": | |
function.append("001" + s2b(tokens[1].replace("label", ""))) | |
elif op == "call": | |
function.append("010" + s2b(tokens[1])) | |
elif op == "loadram": | |
function.append("1000" + s2b(tokens[1], 7)) | |
elif op == "saveram": | |
function.append("1001" + s2b(tokens[1], 7)) | |
elif op == "dup": | |
function.append("1010" + s2b(tokens[1], 7)) | |
elif op == "place": | |
function.append("1011" + s2b(tokens[1], 7)) | |
elif op == "loadi": | |
function.append("110" + s2b(tokens[1])) | |
elif op == "shl": | |
function.append("11100" + s2b(tokens[1], 6)) | |
elif op == "shr": | |
function.append("11101" + s2b(tokens[1], 6)) | |
elif op == "not": | |
function.append("111100") | |
elif op == "and": | |
function.append("111101") | |
elif op == "or": | |
function.append("111110") | |
elif op == "setif": | |
function.append("111111") | |
elif op == "pop": | |
function.append("110" + s2b("0")) | |
function.append("111101") | |
function.append("111110") | |
elif op.startswith("label"): | |
function.append("011" + s2b(op.replace("label", ""))) | |
else: | |
raise Exception("invalid token " + line) | |
headersize = 16 + len(functions) * 8 | |
header = struct.pack(">Q", len(functions)) | |
data = "" | |
for function in functions: | |
codebits = "".join(function) | |
while len(codebits) % 8 != 0: | |
codebits += "0" | |
code = "" | |
for i in xrange(0, len(codebits), 8): | |
code += chr(int(codebits[i:i+8], 2)) | |
header += struct.pack(">Q", headersize + len(data)) | |
data += struct.pack(">Q", len(function)) | |
data += code | |
header += struct.pack(">Q", headersize + len(data)) | |
data += struct.pack(">Q", len(ram)) * 2 | |
for n in ram: | |
data += struct.pack(">Q", n) | |
open("output.cmp", "wb").write(header + data) |
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
function 0 | |
call 252 | |
loadi 0 | |
call 8 | |
loadi 1 | |
call 8 | |
loadi 2 | |
call 8 | |
loadi 3 | |
call 8 | |
call 253 | |
end | |
function 1 ; xor(a, b) | |
loadi 0 | |
dup 1 | |
loadi 0 | |
dup 1 | |
or | |
loadi 0 | |
dup 2 | |
loadi 0 | |
dup 2 | |
and | |
not | |
and | |
end | |
function 2 ; add(a, b) | |
loadi 0 | |
dup 1 | |
loadi 0 | |
dup 1 | |
label1 | |
call 1 | |
loadi 0 | |
dup 2 | |
loadi 0 | |
dup 2 | |
and | |
shl 1 | |
loadi 0 | |
dup 0 | |
jmpz label2 | |
loadi 0 | |
place 2 | |
loadi 0 | |
place 0 | |
jmp label1 | |
label2 | |
pop | |
end | |
function 3 ; get key via index | |
loadi 0 | |
dup 0 | |
loadi 3 | |
and | |
loadi 0 | |
dup 0 | |
shr 1 | |
loadram 4 | |
loadi 0 | |
dup 1 | |
loadi 1 | |
and | |
jmpz label1 | |
shl 32 | |
label1 | |
shr 32 | |
end | |
function 4 ; do encrypt round | |
loadi 0 | |
dup 0 | |
shr 32 | |
loadi 0 | |
dup 1 | |
shl 32 | |
shr 32 | |
loadi 0 | |
dup 0 | |
shl 4 | |
loadi 0 | |
dup 1 | |
shr 5 | |
call 1 | |
loadi 0 | |
place 1 | |
pop | |
call 2 | |
loadi 0 | |
place 0 | |
loadi 0 | |
loadram 8 | |
call 3 | |
call 2 | |
loadi 0 | |
place 1 | |
pop | |
call 1 | |
loadi 0 | |
place 1 | |
pop | |
loadi 0 | |
dup 2 | |
call 2 | |
shl 32 | |
shr 32 | |
loadi 0 | |
place 3 | |
pop | |
pop | |
loadi 0 | |
loadram 8 | |
loadi 0 | |
loadram 9 | |
call 2 | |
loadi 0 | |
saveram 8 | |
pop | |
pop | |
loadi 0 | |
dup 1 | |
shl 4 | |
loadi 0 | |
dup 2 | |
shr 5 | |
call 1 | |
loadi 0 | |
place 1 | |
pop | |
loadi 0 | |
dup 2 | |
call 2 | |
loadi 0 | |
place 1 | |
pop | |
loadi 0 | |
loadram 8 | |
loadi 0 | |
dup 0 | |
shr 11 | |
call 3 | |
loadi 0 | |
place 0 | |
call 2 | |
loadi 0 | |
place 1 | |
pop | |
call 1 | |
loadi 0 | |
place 1 | |
pop | |
call 2 | |
shl 32 | |
shr 32 | |
loadi 0 | |
dup 3 | |
shl 32 | |
or | |
end | |
function 5 | |
loadi 0 | |
loadi 0 | |
saveram 8 | |
loadi 1 | |
shl 31 | |
label1 | |
loadi 0 | |
dup 1 | |
loadram 0 | |
call 4 | |
loadi 0 | |
dup 3 | |
saveram 0 | |
pop | |
shr 1 | |
loadi 0 | |
dup 0 | |
jmpz label2 | |
jmp label1 | |
label2 | |
end | |
function 6 | |
loadi 0 | |
dup 0 | |
not | |
loadi 1 | |
call 2 | |
loadi 0 | |
dup 4 | |
call 2 | |
end | |
function 7 | |
loadi 0 | |
dup 0 | |
shr 32 | |
loadi 0 | |
dup 1 | |
shl 32 | |
shr 32 | |
loadi 0 | |
dup 1 | |
shl 4 | |
loadi 0 | |
dup 2 | |
shr 5 | |
call 1 | |
loadi 0 | |
place 1 | |
pop | |
loadi 0 | |
dup 2 | |
call 2 | |
loadi 0 | |
place 1 | |
pop | |
loadi 0 | |
loadram 8 | |
loadi 0 | |
dup 0 | |
shr 11 | |
call 3 | |
loadi 0 | |
place 0 | |
call 2 | |
loadi 0 | |
place 1 | |
pop | |
call 1 | |
loadi 0 | |
dup 3 | |
loadi 0 | |
dup 1 | |
call 6 | |
shl 32 | |
shr 32 | |
loadi 0 | |
place 5 | |
pop | |
pop | |
pop | |
pop | |
pop | |
loadi 0 | |
loadram 8 | |
loadi 0 | |
loadram 9 | |
call 6 | |
loadi 0 | |
saveram 8 | |
pop | |
pop | |
loadi 0 | |
dup 0 | |
shl 4 | |
loadi 0 | |
dup 1 | |
shr 5 | |
call 1 | |
loadi 0 | |
place 1 | |
pop | |
call 2 | |
loadi 0 | |
place 0 | |
loadi 0 | |
loadram 8 | |
call 3 | |
call 2 | |
loadi 0 | |
place 1 | |
pop | |
call 1 | |
loadi 0 | |
dup 4 | |
loadi 0 | |
dup 1 | |
call 6 | |
shl 32 | |
shr 32 | |
shl 32 | |
loadi 0 | |
dup 6 | |
or | |
end | |
function 8 | |
loadi 0 | |
loadram 10 | |
loadi 0 | |
saveram 8 | |
loadi 1 | |
shl 31 | |
label1 | |
loadi 0 | |
dup 1 | |
loadram 0 | |
call 7 | |
loadi 0 | |
dup 3 | |
saveram 0 | |
pop | |
shr 1 | |
loadi 0 | |
dup 0 | |
jmpz label2 | |
jmp label1 | |
label2 | |
end | |
qword 0x64c729478f8e9f5a | |
qword 0x4444444433333333 | |
qword 0x1111111122222222 | |
qword 0x1111111122222222 | |
qword 0x123456789ABCDEF0 | |
qword 0x1F2E3D4C5B6A7988 | |
qword 0 | |
qword 0 | |
qword 0 ; sum | |
qword 0x9e3779b9 ; delta | |
qword 0x13c6ef3720 ; decryptsum | |
blankram 16 |
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, sys | |
class Bits(object): | |
def __init__(self, s): | |
self.s = s | |
self.index = 0 | |
def readbit(self): | |
bitpos = 7 - (self.index % 8) | |
bytepos = self.index / 8 | |
bit = (ord(self.s[bytepos]) >> bitpos) & 1 | |
self.index += 1 | |
return bit | |
def readbits(self, n): | |
res = 0 | |
for i in xrange(n): | |
res = 2 * res + self.readbit() | |
return res | |
data = open(sys.argv[1], "rb").read() | |
ncodeblocks = struct.unpack(">Q", data[0:8])[0] | |
splits = [] | |
for i in xrange(ncodeblocks+1): | |
offset = struct.unpack(">Q", data[8+i*8:16+i*8])[0] | |
splits.append(offset) | |
for i in xrange(ncodeblocks): | |
print "-------------" | |
print "function %d" % i | |
print "-------------" | |
foo = data[splits[i]:splits[i+1]] | |
num_instr = struct.unpack(">Q", foo[0:8])[0] | |
# x = int(foo[8:].encode("hex"), 16) | |
# print bin(x) | |
b = Bits(foo[8:]) | |
for j in xrange(num_instr): | |
op = b.readbits(3) | |
# x = bin(x)[2:] | |
# x = x.rjust(11, "0") | |
# print x | |
if op == 0: | |
arg = b.readbits(8) | |
print "JMPZ label%02x" % arg | |
elif op == 1: | |
arg = b.readbits(8) | |
print "JMP label%02x" % arg | |
elif op == 2: | |
arg = b.readbits(8) | |
print "CALL %d" % arg | |
elif op == 3: | |
arg = b.readbits(8) | |
print "SETLABEL label%02x" % arg | |
elif op == 4: | |
mode = b.readbits(1) | |
offset = b.readbits(7) | |
if mode == 0: | |
print "LOAD MEM rel+%02x" % offset | |
else: | |
print "SAVE MEM rel+%02x" % offset | |
elif op == 5: | |
mode = b.readbits(1) | |
offset = b.readbits(7) | |
if mode == 0: | |
print "DUP %02x" % offset | |
else: | |
print "REPLACE %02x" % offset | |
elif op == 6: | |
arg = b.readbits(8) | |
print "LOAD IMM %02x" % arg | |
elif op == 7: | |
op2 = b.readbits(3) | |
if op2 in (0, 1): | |
arg = (op2 & 1) << 5 | b.readbits(5) | |
print "SHL %d" % arg | |
elif op2 in (2, 3): | |
arg = (op2 & 1) << 5 | b.readbits(5) | |
print "SHR %d" % arg | |
elif op2 == 4: | |
print "NEG" | |
elif op2 == 5: | |
print "AND s1, s2" | |
elif op2 == 6: | |
print "OR s1, s2" | |
elif op2 == 7: | |
print "SETIF s2 >= s1" | |
else: | |
print "UNKNOWN OP2", bin(op2) | |
exit() | |
else: | |
print "UNKNOWN", bin(op), b.readbits(8) | |
break | |
# 111 01000 xxx - shift right | |
# 111 00000 xxx - shift left | |
# 111 100 - xor 0xff | |
# 111 101 - and stack1, stack2 | |
# 111 110 - or stack1, stack2 | |
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, sys | |
class Bits(object): | |
def __init__(self, s): | |
self.s = s | |
self.index = 0 | |
def readbit(self): | |
bitpos = 7 - (self.index % 8) | |
bytepos = self.index / 8 | |
bit = (ord(self.s[bytepos]) >> bitpos) & 1 | |
self.index += 1 | |
return bit | |
def readbits(self, n): | |
res = 0 | |
for i in xrange(n): | |
res = 2 * res + self.readbit() | |
return res | |
class Function(object): | |
def __init__(self, codeseq, labels): | |
self.codeseq = codeseq | |
self.labels = labels | |
class VMException(Exception): | |
pass | |
class VM(object): | |
def __init__(self, functions, memory): | |
self.functions = functions | |
self.memory = memory | |
self.funcstack = [] | |
self.stack = [] | |
self.currfunc = 0 | |
self.currip = 0 | |
def printstate(self): | |
op, op2, arg = self.functions[self.currfunc].codeseq[self.currip] | |
print "stack", | |
for val in self.stack: | |
print hex(val), | |
print self.currfunc, self.currip, "|", op, op2, arg | |
def step(self): | |
op, op2, arg = self.functions[self.currfunc].codeseq[self.currip] | |
# print "funcstack", self.funcstack | |
#self.printstate() | |
do_inc = True | |
if op == 0: | |
if len(self.stack) < 1: | |
raise VMException("stack empty") | |
if self.stack.pop() == 0: | |
if arg not in self.functions[self.currfunc].labels: | |
raise VMException("unknown label") | |
self.currip = self.functions[self.currfunc].labels[arg] | |
do_inc = False | |
elif op == 1: | |
if arg not in self.functions[self.currfunc].labels: | |
raise VMException("unknown label") | |
self.currip = self.functions[self.currfunc].labels[arg] | |
do_inc = False | |
elif op == 2: | |
if arg == 255: | |
print "output byte %s" % repr(chr(self.stack[-1] & 0xff)) | |
# sys.stdout.write(chr(self.stack[-1] & 0xff)) | |
elif arg in (252, 253, 254): | |
raise VMException("this call not impl") | |
else: | |
if arg >= len(self.functions): | |
raise VMException("unknown function called") | |
self.funcstack.append((self.currfunc, self.currip + 1, len(self.stack))) | |
self.currfunc = arg | |
self.currip = 0 | |
do_inc = False | |
#self.printstate() | |
elif op == 4: | |
if op2 == 0: | |
if len(self.stack) < 1: | |
raise VMException("stack empty") | |
index = self.stack.pop() + arg | |
if index >= len(self.memory) or index < 0: | |
raise VMException("memory out of bounds") | |
print "read from mem location %016x %016x" % (index, self.memory[index]) | |
self.stack.append(self.memory[index]) | |
else: | |
if len(self.stack) < 2: | |
raise VMException("stack empty") | |
index = self.stack.pop() + arg | |
data = self.stack.pop() | |
if index >= len(self.memory) or index < 0: | |
raise VMException("memory out of bounds") | |
print "wrote to mem location %016x %016x" % (index, data) | |
self.memory[index] = data | |
elif op == 5: | |
if op2 == 0: | |
if len(self.stack) < 1: | |
raise VMException("stack empty") | |
index = self.stack.pop() + arg + 1 | |
if len(self.stack) < index: | |
raise VMException("stack underflow") | |
self.stack.append(self.stack[-index]) | |
else: | |
if len(self.stack) < 2: | |
raise VMException("stack empty") | |
index = self.stack.pop() + arg + 1 | |
value = self.stack.pop() | |
if len(self.stack) < index: | |
raise VMException("stack underflow") | |
self.stack[-index] = value | |
elif op == 6: | |
self.stack.append(arg) | |
elif op == 7: | |
if op2 == 0: | |
if len(self.stack) < 1: | |
raise VMException("stack empty") | |
res = (self.stack.pop() << arg) & 0xffffffffffffffff | |
self.stack.append(res) | |
elif op2 == 2: | |
if len(self.stack) < 1: | |
raise VMException("stack empty") | |
res = self.stack.pop() >> arg | |
self.stack.append(res) | |
elif op2 == 4: | |
if len(self.stack) < 1: | |
raise VMException("stack empty") | |
res = self.stack.pop() ^ 0xffffffffffffffff | |
self.stack.append(res) | |
elif op2 == 5: | |
if len(self.stack) < 2: | |
raise VMException("stack empty") | |
val1 = self.stack.pop() | |
val2 = self.stack.pop() | |
self.stack.append(val1 & val2) | |
elif op2 == 6: | |
if len(self.stack) < 2: | |
raise VMException("stack empty") | |
val1 = self.stack.pop() | |
val2 = self.stack.pop() | |
self.stack.append(val1 | val2) | |
elif op2 == 7: | |
if len(self.stack) < 2: | |
raise VMException("stack empty") | |
val1 = self.stack.pop() | |
val2 = self.stack.pop() | |
if val2 >= val1: | |
self.stack.append(1) | |
else: | |
self.stack.append(0) | |
else: | |
raise VMException("op2 not impl %d" % op2) | |
else: | |
raise VMException("op not impl %d" % op) | |
if do_inc: | |
self.currip += 1 | |
while self.currip >= len(self.functions[self.currfunc].codeseq): | |
if len(self.funcstack) == 0: | |
print "program exited" | |
return False | |
if len(self.stack) < 1: | |
raise VMException("stack empty") | |
self.currfunc, self.currip, stacksize = self.funcstack.pop() | |
retval = self.stack.pop() | |
self.stack = self.stack[0:stacksize] | |
self.stack.append(retval) | |
return True | |
data = open(sys.argv[1], "rb").read() | |
nfuncs = struct.unpack(">Q", data[0:8])[0] | |
offsets = [] | |
for i in xrange(nfuncs): | |
offset = struct.unpack(">Q", data[8+i*8:16+i*8])[0] | |
offsets.append(offset) | |
functions = [] | |
for funcno in xrange(nfuncs): | |
codeseq = [] | |
labels = {} | |
bytecode = data[offsets[funcno]:] | |
b = Bits(bytecode[8:]) | |
num_instr = struct.unpack(">Q", bytecode[0:8])[0] | |
for i in xrange(num_instr): | |
op = b.readbits(3) | |
if op in (0, 1, 2, 6): | |
arg = b.readbits(8) | |
codeseq.append((op, 0, arg)) | |
elif op == 3: | |
arg = b.readbits(8) | |
labels[arg] = len(codeseq) | |
elif op in (4, 5): | |
mode = b.readbits(1) | |
offset = b.readbits(7) | |
codeseq.append((op, mode, offset)) | |
else: | |
op2 = b.readbits(3) | |
if op2 in (0, 1, 2, 3): | |
arg = (op2 & 1) << 5 | b.readbits(5) | |
codeseq.append((op, op2 & 6, arg)) | |
elif op2 in (4, 5, 6, 7): | |
codeseq.append((op, op2, 0)) | |
else: | |
print "UNKNOWN OP2", bin(op2) | |
exit() | |
functions.append(Function(codeseq, labels)) | |
offset = struct.unpack(">Q", data[8+nfuncs*8:16+nfuncs*8])[0] | |
numqwords, totalqwords = struct.unpack(">QQ", data[offset:offset+16]) | |
memory = [0] * totalqwords | |
for i in xrange(numqwords): | |
qword = struct.unpack(">Q", data[offset+16+8*i:offset+24+8*i])[0] | |
memory[i] = qword | |
vm = VM(functions, memory) | |
while True: | |
cont = vm.step() | |
if not cont: | |
break | |
# for i in xrange(6): | |
# print "%016x" % vm.memory[i] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment