From 1431f6e104a07a7def846e867e69587fa183b2ea Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Wed, 17 May 2017 11:01:47 +0200 Subject: [PATCH] Opcode encryption in assembler --- python/assembler.py | 133 +++++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 56 deletions(-) diff --git a/python/assembler.py b/python/assembler.py index a0eb6ac..738c652 100644 --- a/python/assembler.py +++ b/python/assembler.py @@ -2,33 +2,38 @@ import sys import re import struct import IPython +import copy -class InvalidRegisterException(Exception): +class AssemblerException(Exception): + pass + + +class InvalidRegister(AssemblerException): def __init__(self, register): super().__init__("Invalid register: {}".format(register)) -class InvalidOperationException(Exception): +class InvalidOperation(AssemblerException): def __init__(self, operation): super().__init__("Invalid operation: {}".format(operation)) -class ExpectedImmediateException(Exception): +class ExpectedImmediate(AssemblerException): def __init__(self, value): super().__init__("Expected immediate, got {}".format(value)) -class ExpectedRegisterException(Exception): +class ExpectedRegister(AssemblerException): def __init__(self, value): super().__init__("Expected register, got {}".format(value)) -class IPOverwriteException(Exception): +class IPOverwrite(AssemblerException): def __init__(self, instruction=None): if instruction: @@ -37,17 +42,23 @@ class IPOverwriteException(Exception): super().__init__("IP can't be overwritten.") -class InvalidValueException(Exception): +class InvalidValue(AssemblerException): def __init__(self, instruction): super().__init__("Invalid value while assembling: {}".format(instruction)) +rol = lambda val, r_bits, max_bits: \ + (val << r_bits%max_bits) & (2**max_bits-1) | \ + ((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits))) class VMAssembler: - assembled_code = bytearray() + + def __init__(self, key): + self.assembled_code = bytearray() + self.define_ops(key) def parse(self, instruction): - action = getattr(self, "{}".format(instruction.opcode.name)) + action = getattr(self, "op_{}".format(instruction.opcode.name)) action(instruction) def process_code_line(self, line): @@ -64,20 +75,15 @@ class VMAssembler: opcode = instruction.opcode reg = instruction.args[0] imm = instruction.args[1] - print(instruction) - if reg.name != "ip": - if imm.isimm(): - if reg.isreg(): - if opcode.uint8() and reg.uint8() and imm.uint16(): - self.assembled_code += opcode.uint8() + reg.uint8() + imm.uint16() - else: - raise InvalidValueException(instruction) - else: - raise ExpectedRegisterException(reg) - else: - raise ExpectedImmediateException(imm) - else: - raise IPOverwriteException(instruction) + if reg.name == "ip": + raise IPOverwrite(instruction) + if not imm.isimm(): + raise ExpectedImmediate(imm) + if not reg.isreg(): + raise ExpectedRegister(reg) + if not opcode.uint8() or not reg.uint8() or not imm.uint16(): + raise InvalidValue(instruction) + self.assembled_code += opcode.uint8() + reg.uint8() + imm.uint16() return def reg2reg(self, instruction): @@ -90,47 +96,55 @@ class VMAssembler: opcode = instruction.opcode imm = instruction.args[0] reg = instruction.args[1] - print(instruction) - if reg.name != "ip": - if imm.isimm(): - if reg.isreg(): - if opcode.uint8() and reg.uint8() and imm.uint16(): - self.assembled_code += opcode.uint8() + imm.uint16() + reg.uint8() - else: - raise InvalidValueException(instruction) - else: - raise ExpectedRegisterException(reg) - else: - raise ExpectedImmediateException(imm) - else: - raise IPOverwriteException(instruction) + if reg.name == "ip": + raise IPOverwrite(instruction) + if not imm.isimm(): + raise ExpectedImmediate(imm) + if not reg.isreg(): + raise ExpectedRegister(reg) + if not opcode.uint8() or not reg.uint8() or not imm.uint16(): + raise InvalidValue(instruction) + self.assembled_code += opcode.uint8() + imm.uint16() + reg.uint8() return def imm(self, instruction): return - def movi(self, instruction): + def op_movi(self, instruction): self.imm2reg(instruction) - def movr(self, instruction): + def op_movr(self, instruction): self.reg2reg(instruction) - def getm(self, instruction): + def op_load(self, instruction): self.imm2reg(instruction) - def putm(self, instruction): + def op_stor(self, instruction): self.reg2imm(instruction) - def addi(self, instruction): + def op_addi(self, instruction): self.imm2reg(instruction) + def define_ops(self, key): + key_ba = bytearray(key, 'utf-8') + olds = copy.deepcopy(ops) + for b in key_ba: + for op_com in ops: + if b % 2: + op_com.set_value(rol(b ^ op_com.value, b % 8, 8)) + else: + op_com.set_value(rol(b ^ op_com.value, (b + 1) % 8, 8)) + for i in ops: + for j in ops: + j.set_value(rol(j.value, i.value % 8, 8)) + for o, n in zip(olds, ops): + print("{} : {}->{}".format(o.name, hex(o.value), hex(n.value))) + class VMComponent: """ Represents a register, operation or an immediate the VM recognizes """ - name = "" - value = "" def __init__(self, name, value): self.name = name.casefold() @@ -139,6 +153,12 @@ class VMComponent: def __repr__(self): return "{}".format(self.name) + def set_name(self, name): + self.name = name + + def set_value(self, value): + self.value = value + def uint8(self): numre = re.compile("^[0-9]+$") if isinstance(self.value, int): @@ -203,8 +223,8 @@ class VMInstruction: op_names = ["MOVI", "MOVR", - "GETM", - "PUTM", + "LOAD", + "STOR", "ADDI", "ADDR", "SUBI", @@ -220,8 +240,10 @@ op_names = ["MOVI", "PUSH", "POOP", "CALL", - "HALT", - "NOPE"] + "SHIT", + "NOPE", + "GERM"] + reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "BP", "SP"] section_names = ["DATA:", "CODE:", "STACK:"] section_flags = {s.casefold(): i + 1 for i, s in enumerate(section_names)} @@ -230,7 +252,6 @@ regs = [VMComponent(s.casefold(), i) for i, s in enumerate(reg_names)] def value_from_list(fromlist, name): - global ops, regs """ returns a tuple (name, value) from a list of VMComponents """ @@ -238,9 +259,9 @@ def value_from_list(fromlist, name): if el.name == name: return (el.name, el.value) if fromlist == ops: - raise InvalidOperationException(name) + raise InvalidOperation(name) elif fromlist == regs: - raise InvalidRegisterException(name) + raise InvalidRegister(name) def name_from_list(fromlist, value): @@ -259,12 +280,12 @@ def assemble_data(line): def main(): - if len(sys.argv) < 3: - print("Usage: {} file_to_assemble output".format(sys.argv[0])) + if len(sys.argv) < 4: + print("Usage: {} opcodes_key file_to_assemble output".format(sys.argv[0])) return - vma = VMAssembler() - with open(sys.argv[1], 'r') as f: - gen = (line.casefold().strip("\n") for line in f if line != "\n") + vma = VMAssembler(sys.argv[1]) + with open(sys.argv[2], 'r') as f: + gen = (line.casefold().strip() for line in f if line != "\n") flag = None for line in gen: @@ -278,7 +299,7 @@ def main(): if not flag: sys.stderr.write( "Nothing was assembled! Did you use the section delimiters?\n") - with open(sys.argv[2], 'wb') as f: + with open(sys.argv[3], 'wb') as f: f.write(vma.assembled_code) if __name__ == '__main__':