import sys import re import struct import IPython import copy class AssemblerException(Exception): pass class InvalidRegister(AssemblerException): def __init__(self, register): super().__init__("Invalid register: {}".format(register)) class InvalidOperation(AssemblerException): def __init__(self, operation): super().__init__("Invalid operation: {}".format(operation)) class ExpectedImmediate(AssemblerException): def __init__(self, value): super().__init__("Expected immediate, got {}".format(value)) class ExpectedRegister(AssemblerException): def __init__(self, value): super().__init__("Expected register, got {}".format(value)) class IPOverwrite(AssemblerException): def __init__(self, instruction=None): if instruction: super().__init__("IP can't be overwritten. Instruction: {}".format(instruction)) else: super().__init__("IP can't be overwritten.") class InvalidValue(AssemblerException): def __init__(self, instruction): super().__init__("Invalid value while assembling: {}".format(instruction)) class VMAssembler: def __init__(self, key): self.assembled_code = bytearray() self.encrypt_ops(key) def parse(self, instruction): action = getattr(self, "{}".format(instruction.opcode.method)) action(instruction) def process_code_line(self, line): sys.stdout.write("CODE: ") components = [x for x in re.split('\W', line) if x] instruction = VMInstruction(components[0], components[1:]) sys.stdout.write(str(instruction) + "\n") self.parse(instruction) def imm2reg(self, instruction): """ Intel syntax -> REG, IMM """ opcode = instruction.opcode reg = instruction.args[0] imm = instruction.args[1] 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): """ Intel syntax -> DST_REG, SRC_REG """ opcode = instruction.opcode dst_reg = instruction.args[0] src_reg = instruction.args[1] if dst_reg.name == "ip" or src_reg.name == "ip": raise IPOverwrite(instruction) if not dst_reg.isreg(): raise ExpectedRegister(dst_reg) if not src_reg.isreg(): raise ExpectedRegister(src_reg) if not opcode.uint8() or not dst_reg.uint8() or not src_reg.uint8(): raise InvalidValue(instruction) byte_with_nibbles = struct.pack(" IMM, REG """ opcode = instruction.opcode imm = instruction.args[0] reg = instruction.args[1] 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 byt2reg(self, instruction): """ Intel syntax -> REG, [BYTE]IMM """ opcode = instruction.opcode reg = instruction.args[0] imm = instruction.args[1] 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.uint8(): raise InvalidValue(instruction) self.assembled_code += opcode.uint8() + reg.uint8() + imm.uint8() return def regonly(self, instruction): """ Instruction with only an argument: a register """ opcode = instruction.opcode reg = instruction.args[0] if reg.name == "ip": raise IPOverwrite(instruction) if not reg.isreg(): raise ExpectedRegister(reg) if not opcode.uint8() or not reg.uint8(): raise InvalidValue(instruction) self.assembled_code += opcode.uint8() + reg.uint8() return def immonly(self, instruction): """ Instruction with only an argument: an immediate """ opcode = instruction.opcode imm = instruction.args[0] if not imm.isimm(): raise ExpectedImmediate(imm) if not opcode.uint8() or not imm.uint16(): raise InvalidValue(instruction) self.assembled_code += opcode.uint8() + imm.uint16() return def single(self, instruction): """ Instruction with no arguments """ opcode = instruction.opcode self.assembled_code += opcode.uint8() return def encrypt_ops(self, key): key_ba = bytearray(key, 'utf-8') olds = copy.deepcopy(ops) # RC4 KSA! :-P arr = [i for i in range(256)] j = 0 for i in range(len(arr)): j = (j + arr[i] + key_ba[i % len(key)]) % len(arr) arr[i], arr[j] = arr[j], arr[i] for i, o in enumerate(ops): o.set_value(arr[i]) 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 """ def __init__(self, name, value, method=None): self.name = name.casefold() self.value = value self.method = method 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): return struct.pack("