Opcode encryption in assembler
This commit is contained in:
		
							parent
							
								
									e1f984c72d
								
							
						
					
					
						commit
						1431f6e104
					
				| @ -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(): | ||||
|         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() | ||||
|                     else: | ||||
|                         raise InvalidValueException(instruction) | ||||
|                 else: | ||||
|                     raise ExpectedRegisterException(reg) | ||||
|             else: | ||||
|                 raise ExpectedImmediateException(imm) | ||||
|         else: | ||||
|             raise IPOverwriteException(instruction) | ||||
|         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(): | ||||
|         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() | ||||
|                     else: | ||||
|                         raise InvalidValueException(instruction) | ||||
|                 else: | ||||
|                     raise ExpectedRegisterException(reg) | ||||
|             else: | ||||
|                 raise ExpectedImmediateException(imm) | ||||
|         else: | ||||
|             raise IPOverwriteException(instruction) | ||||
|         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__': | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user