From e5180294855b5e36d4dc09ef52b0a7ef3af6dfe4 Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Wed, 24 May 2017 20:54:12 +0200 Subject: [PATCH] CALL + fix vari --- assembler/assembler.py | 97 +++++++++++++++++++++++++++--------------- test/tea-encrypt.c | 10 ++--- vm/opcodes.h | 7 ++- vm/vm.cpp | 67 +++++++++++++++++++++-------- vm/vm.h | 4 +- 5 files changed, 126 insertions(+), 59 deletions(-) diff --git a/assembler/assembler.py b/assembler/assembler.py index 413d488..9dd7e5c 100644 --- a/assembler/assembler.py +++ b/assembler/assembler.py @@ -56,6 +56,9 @@ class VMAssembler: self.functions = [] self.decrypt_ops(key) self.parse_functions() + self.resolve_functions_offsets() + self.resolve_symbols() + self.disassembly() main = next((x for x in self.functions if x.name == "main"), None) if main == None: print("Main has to be defined") @@ -85,20 +88,46 @@ class VMAssembler: i] = self.functions[i], self.functions[0] break + def resolve_functions_offsets(self): # calculating functions offsets for i in range(1, len(self.functions)): prev_fun_tot_size = self.functions[ - i - 1].size + self.functions[i - 1].offset - cur_fun_size = self.functions[i].size + i - 1].size() + self.functions[i - 1].offset self.functions[i].set_offset(prev_fun_tot_size) return + def resolve_symbols(self): + for f in self.functions: + for i in f.instructions: + symcall = symcall_re.match(str(i)) + if symcall: + symname = symcall.group(1) + + # checking if it's a jump to a label + if symname in [y.label for x in self.functions for y in x.instructions]: + fun = next( + (x for x in self.functions for y in x.instructions if symname == y.label), None) + offset = f.offset_of_label(symname) + f.offset + # function + elif symname in [x.name for x in self.functions]: + offset = next( + (x.offset for x in self.functions if x.name == symname), None) + else: + print("SYMBOL \"{}\" NOT FOUND!".format(symname)) + i.args[0].set_value(offset) + def parse(self): for f in self.functions: for i in f.instructions: action = getattr(self, "{}".format(i.opcode.method)) action(i) + def disassembly(self): + for f in self.functions: + print("FUNCTION {}".format(f.name)) + for idx, ins in enumerate(f.instructions): + print("{}:\t{}".format(hex(f.offset_of_instruction(idx)), ins)) + def imm2reg(self, instruction): """ Intel syntax -> REG, IMM @@ -202,29 +231,11 @@ class VMAssembler: return def jump(self, instruction): - imm_op_re = re.compile(".*[iI]$") + imm_op_re = re.compile("^([cC][aA][lL]{2})$|(.*[iI])$") reg_op_re = re.compile(".*[rR]$") symcall = symcall_re.match(str(instruction)) - dst = instruction.args[0] - # let's check if the jump is to a label or a function - if symcall: - # the symbal has not been resolved - if dst.name == dst.value: - # check whether it is a function - val = next( - (x.offset for x in self.functions if x.name == dst.name), None) - # check whether it is a label - if val == None: - for f in self.functions: - for i in f.instructions: - if i.label == dst.name: - val = f.offset_of_label(dst) + f.offset - - if val == None: - raise AssemblerException() - # resolving the symbol - instruction.args[0].set_value(val) + print(instruction) # define the kind of jump: to immediate or to register if imm_op_re.match(instruction.opcode.name): self.immonly(instruction) @@ -263,7 +274,6 @@ class VMFunction: def __init__(self, name, code): self.name = name - self.size = 0 self.offset = 0 self.instructions = [] @@ -283,11 +293,12 @@ class VMFunction: i += 1 else: raise InvalidOperation(line) - self.calc_size() - def calc_size(self): + def size(self): + size = 0 for i in self.instructions: - self.size += i.size + size += i.size + return size def set_offset(self, offset): self.offset = offset @@ -301,8 +312,16 @@ class VMFunction: return offset + def offset_of_instruction(self, idx): + offset = 0 + for i, ins in enumerate(self.instructions): + if i == idx: + break + offset += ins.size + return offset + def __repr__(self): - return "{}: size {}, offset {}".format(self.name, hex(self.size), hex(self.offset)) + return "{}: size {}, offset {}".format(self.name, hex(self.size()), hex(self.offset)) class VMInstruction: @@ -316,7 +335,7 @@ class VMInstruction: def __init__(self, line, label=None): self.opcode = None self.args = [] - self.size = 1 + self.size = 0 self.label = label ins = instruction_re.match(line) @@ -326,13 +345,13 @@ class VMInstruction: self.opcode = next((x for x in ops if x.name == opcode), None) if self.opcode == None: raise InvalidOperation(opcode) - + self.size = ops_sizes[self.opcode.method] args = [x for x in ins.groups()[1:] if x is not None] + print("OP: {} | ARGS: {} | SYMCALL: {}".format(self.opcode, args,symcall)) for a in args: if immediate_re.match(a) or symcall: # directly append the immediate self.args.append(VMComponent(a, a)) - self.size += 2 continue elif register_re.match(a): # create a VM component for a register @@ -340,7 +359,6 @@ class VMInstruction: if reg == None: raise InvalidRegister(a) self.args.append(reg) - self.size += 1 continue def __repr__(self): @@ -436,7 +454,8 @@ op_names = [["MOVI", "imm2reg"], ["SHRR", "reg2reg"], ["PUSH", "regonly"], ["POOP", "regonly"], - ["CMPI", "imm2reg"], + ["CMPB", "byt2reg"], + ["CMPW", "imm2reg"], ["CMPR", "reg2reg"], ["JMPI", "jump"], ["JMPR", "jump"], @@ -448,12 +467,21 @@ op_names = [["MOVI", "imm2reg"], ["JPER", "jump"], ["JPNI", "jump"], ["JPNR", "jump"], + ["CALL", "jump"], ["RETN", "single"], ["SHIT", "single"], ["NOPE", "single"], ["GRMN", "single"]] -reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "BP", "SP"] +reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "RP", "SP"] +ops_sizes = {"reg2reg": 2, + "imm2reg": 4, + "reg2imm": 4, + "byt2reg": 3, + "regonly": 3, + "immonly": 3, + "jump": 3, + "single": 1} ops = [VMComponent(le[0], i, le[1]) for i, le in enumerate(op_names)] regs = [VMComponent(s.casefold(), i) for i, s in enumerate(reg_names)] instruction_re = re.compile( @@ -463,7 +491,7 @@ immediate_re = re.compile("(?:0x)?[0-9a-fA-F]+$") alpha_re = re.compile("^[a-zA-Z]*$") register_re = re.compile("(^[rRsS][0-4]$)|([iIrRsS][pP]$)") label_re = re.compile("^([a-zA-Z]+)\:$") -symcall_re = re.compile("^([jJ][pPmM][pPaAbBeEnN][iIrR])\ +([\w]*)$") +symcall_re = re.compile("^(?:[jJ][pPmM][pPaAbBeEnN][iIrR]|(?:[cC][aA][lL]{2}))\ +([\w]*)$") def main(): @@ -477,6 +505,7 @@ def main(): filedata = [x.strip() for x in filedata if x.strip()] vma = VMAssembler(sys.argv[1], filedata) + print(vma.functions) vma.parse() with open(sys.argv[3], 'wb') as f: diff --git a/test/tea-encrypt.c b/test/tea-encrypt.c index 687d9bb..94d38b3 100644 --- a/test/tea-encrypt.c +++ b/test/tea-encrypt.c @@ -4,12 +4,12 @@ #include #include -void encrypt(uint32_t *v, uint32_t *k) { - uint32_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */ +void encrypt(uint16_t *v, uint16_t *k) { + uint16_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */ //uint32_t delta = 0x9e3779b9; /* a key schedule constant */ uint16_t delta= 0x9e37; - uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */ - for (i = 0; i < 32; i++) { /* basic cycle start */ + uint16_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */ + for (i = 0; i < 64; i++) { /* basic cycle start */ sum += delta; v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1); v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3); @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) { buflen = strlen(argv[1]); buf = (uint8_t *)malloc(buflen); memcpy(buf, argv[1], buflen); - encrypt((uint32_t *)buf, (uint32_t *)argv[2]); + encrypt((uint16_t *)buf, (uint16_t *)argv[2]); printf("Result:\n"); for (i = 0; i < buflen; i++) { printf("%02x", buf[i]); diff --git a/vm/opcodes.h b/vm/opcodes.h index 48d4e5b..bb94a2d 100644 --- a/vm/opcodes.h +++ b/vm/opcodes.h @@ -32,7 +32,8 @@ enum OPS_STARTING_VALUES { SHRR, PUSH, POOP, - CMPI, + CMPB, + CMPW, CMPR, JMPI, JMPR, @@ -44,6 +45,7 @@ enum OPS_STARTING_VALUES { JPER, JPNI, JPNR, + CALL, RETN, SHIT, NOPE, @@ -97,7 +99,8 @@ INSTRUCTION SIZES #define SHRR_SIZE REG2REG #define PUSH_SIZE REGONLY #define POOP_SIZE REGONLY -#define CMPI_SIZE IMM2REG +#define CMPB_SIZE BYT2REG +#define CMPW_SIZE IMM2REG #define CMPR_SIZE REG2REG #define JMPI_SIZE IMMONLY #define JMPR_SIZE REGONLY diff --git a/vm/vm.cpp b/vm/vm.cpp index 777fc2b..5af5b10 100644 --- a/vm/vm.cpp +++ b/vm/vm.cpp @@ -561,16 +561,38 @@ bool VM::execPOOP(void) { memcpy(®s[dst], &as.stack[regs[SP]], sizeof(uint16_t)); return true; } -bool VM::execCMPI(void) { +bool VM::execCMPB(void) { /* - CMPI R0, 0x2 -> Compare immediate with register + CMPB R0, 0x2 -> Compare immediate with lower half (BYTE) register + */ + uint8_t reg; + uint8_t imm; + + reg = as.code[regs[IP] + 1]; + imm = as.code[regs[IP] + 2]; + DBG_INFO(("CMPB %s, 0x%x\n", getRegName(reg), imm)); + if (*((uint8_t *)®s[reg]) == imm) { + flags.ZF = 1; + } else { + flags.ZF = 0; + } + if (*((uint8_t *)®s[reg]) > imm) { + flags.CF = 1; + } else { + flags.CF = 0; + } + return true; +} +bool VM::execCMPW(void) { + /* + CMPW R0, 0x2 -> Compare immediate with whole (WORD) register */ uint8_t reg; uint16_t imm; reg = as.code[regs[IP] + 1]; imm = *((uint16_t *)&as.code[regs[IP] + 2]); - DBG_INFO(("CMPI %s, 0x%x\n", getRegName(reg), imm)); + DBG_INFO(("CMPW %s, 0x%x\n", getRegName(reg), imm)); if (regs[reg] == imm) { flags.ZF = 1; } else { @@ -613,7 +635,6 @@ bool VM::execJMPI(void) { imm = *(uint16_t *)&as.code[regs[IP] + 1]; DBG_INFO(("JMPI 0x%x\n", imm)); - regs[RP] = regs[IP] + 3; regs[IP] = imm; return true; } @@ -625,7 +646,6 @@ bool VM::execJMPR(void) { reg = as.code[regs[IP] + 1]; DBG_INFO(("JMPR %s = 0x%x\n", getRegName(reg), regs[reg])); - regs[RP] = regs[IP] + 2; regs[IP] = regs[reg]; return true; } @@ -638,7 +658,6 @@ bool VM::execJPAI(void) { imm = *(uint16_t *)&as.code[regs[IP] + 1]; DBG_INFO(("JPAI 0x%x\n", imm)); if (flags.CF == 1) { - regs[RP] = regs[IP] + 2; regs[IP] = imm; return true; } @@ -653,7 +672,6 @@ bool VM::execJPAR(void) { reg = as.code[regs[IP] + 1]; DBG_INFO(("JPAR %s = 0x%x\n", getRegName(reg), regs[reg])); if (flags.CF == 1) { - regs[RP] = regs[IP] + 2; regs[IP] = reg; return true; } @@ -668,7 +686,6 @@ bool VM::execJPBI(void) { imm = *(uint16_t *)&as.code[regs[IP] + 1]; DBG_INFO(("JPBI 0x%x\n", imm)); if (flags.CF == 0) { - regs[RP] = regs[IP] + 3; regs[IP] = imm; return true; } @@ -683,7 +700,6 @@ bool VM::execJPBR(void) { reg = as.code[regs[IP] + 1]; DBG_INFO(("JPBR %s = 0x%x\n", getRegName(reg), regs[reg])); if (flags.CF == 0) { - regs[RP] = regs[IP] + 2; regs[IP] = reg; return true; } @@ -698,7 +714,6 @@ bool VM::execJPEI(void) { imm = *(uint16_t *)&as.code[regs[IP] + 1]; DBG_INFO(("JPEI 0x%x\n", imm)); if (flags.ZF == 1) { - regs[RP] = regs[IP] + 2; regs[IP] = imm; return true; } @@ -713,7 +728,6 @@ bool VM::execJPER(void) { reg = as.code[regs[IP] + 1]; DBG_INFO(("JPER %s = 0x%x\n", getRegName(reg), regs[reg])); if (flags.ZF == 1) { - regs[RP] = regs[IP] + 2; regs[IP] = reg; return true; } @@ -728,7 +742,6 @@ bool VM::execJPNI(void) { imm = *(uint16_t *)&as.code[regs[IP] + 1]; DBG_INFO(("JPNI 0x%x\n", imm)); if (flags.ZF == 0) { - regs[RP] = regs[IP] + 2; regs[IP] = imm; return true; } @@ -743,17 +756,32 @@ bool VM::execJPNR(void) { reg = as.code[regs[IP] + 1]; DBG_INFO(("JPNR %s = 0x%x\n", getRegName(reg), regs[reg])); if (flags.ZF == 0) { - regs[RP] = regs[IP] + 2; regs[IP] = reg; return true; } return false; } +bool VM::execCALL(void) { + /* + CALL 0x1000 -> Jump to data[0x1000] and saves the RP onto the stack + */ + uint16_t dst; + + dst = *((uint16_t *)&as.code[regs[IP] + 1]); + DBG_INFO(("CALL 0x%x\n", dst)); + *((uint16_t *)&as.stack[regs[SP]]) = regs[IP] + 3; + regs[SP] += sizeof(uint16_t); + regs[IP] = dst; + return false; +} bool VM::execRETN(void) { /* RETN -> IP = RP , restores saved return IP */ + regs[SP] -= sizeof(uint16_t); + regs[RP] = *((uint16_t *)&as.stack[regs[SP]]); DBG_INFO(("RETN 0x%x\n", regs[RP])); + regs[IP] = regs[RP]; return true; } bool VM::execGRMN(void) { @@ -860,9 +888,12 @@ void VM::run(void) { } else if (opcode == OPS[POOP]) { execPOOP(); regs[IP] += POOP_SIZE; - } else if (opcode == OPS[CMPI]) { - execCMPI(); - regs[IP] += CMPI_SIZE; + } else if (opcode == OPS[CMPB]) { + execCMPB(); + regs[IP] += CMPB_SIZE; + } else if (opcode == OPS[CMPW]) { + execCMPW(); + regs[IP] += CMPW_SIZE; } else if (opcode == OPS[CMPR]) { execCMPR(); regs[IP] += CMPR_SIZE; @@ -902,6 +933,8 @@ void VM::run(void) { if (!execJPNR()) { regs[IP] += JPNR_SIZE; } + } else if (opcode == OPS[CALL]) { + execCALL(); } else if (opcode == OPS[RETN]) { execRETN(); regs[IP] = regs[RP]; @@ -914,7 +947,7 @@ void VM::run(void) { } else if (opcode == OPS[NOPE]) { regs[IP] += NOPE_SIZE; } else { - DBG_ERROR(("WAT\n")); + DBG_ERROR(("WAT: 0x%x\n", as.code[regs[IP]])); finished = true; } } diff --git a/vm/vm.h b/vm/vm.h index 8fcfdb6..2400998 100644 --- a/vm/vm.h +++ b/vm/vm.h @@ -62,7 +62,8 @@ private: bool execSHRR(void); bool execPUSH(void); bool execPOOP(void); - bool execCMPI(void); + bool execCMPB(void); + bool execCMPW(void); bool execCMPR(void); bool execJMPI(void); bool execJMPR(void); @@ -74,6 +75,7 @@ private: bool execJPER(void); bool execJPNI(void); bool execJPNR(void); + bool execCALL(void); bool execRETN(void); bool execGRMN(void);