def lift_jmp(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 1, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] il.append(il.jump(Lifter._lift_op(il, insn, op_1)))
def lift_bra(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 1, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] il.append(il.jump(il.const(RSIZE, op_1.val)))
def lift(cls, il: LowLevelILFunction, insn: SHInsn): func_name = 'lift_' + insn.opcode["cmd"].replace("/", "_").replace( ".", "_") if hasattr(cls, func_name): getattr(cls, func_name)(il, insn) else: il.append(il.unimplemented())
def lift_movi20(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 2, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] op_2 = insn.opcode["args"][1] il.append( il.set_reg(RSIZE, op_2.reg, Lifter._lift_op(il, insn, op_1, True)))
def _llil_func_info(self, code, pc): if pc in self.llil_func_cache: return self.llil_func_cache[pc] from binaryninja import Architecture, LowLevelILFunction # FIXME func = LowLevelILFunction(Architecture['x86_64']) func.current_address = pc size = self.view.arch.get_instruction_low_level_il(code, pc, func) self.llil_func_cache[pc] = (func, size) return func, size
def lift_mov(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 2, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] op_2 = insn.opcode["args"][1] extend = False if op_1.type == OpType.IMM: extend = True il.append( il.set_reg(RSIZE, op_2.reg, Lifter._lift_op(il, insn, op_1, extend)))
def lift_sub(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 2, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] op_2 = insn.opcode["args"][1] il.append( il.set_reg( RSIZE, op_2.reg, il.sub( RSIZE, il.reg(RSIZE, op_1.reg), il.reg(RSIZE, op_2.reg), )))
def lift_bsrf(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 1, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] il.append( il.call( il.add( RSIZE, il.const(RSIZE, insn.addr), il.add(RSIZE, il.reg(RSIZE, op_1.reg), il.const(RSIZE, 4)))))
def lift_movi20s(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 2, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] op_2 = insn.opcode["args"][1] assert op_1.type == OpType.IMM, f"Invalid instruction at: 0x{insn.addr:x}" assert op_1.size != 0, f"Invalid instruction at: 0x{insn.addr:x}" il.append( il.set_reg( RSIZE, op_2.reg, il.sign_extend( RSIZE, il.shift_left(op_1.size, il.const(op_1.size, op_1.val), il.const(1, 8)))))
return left ^ right def visit_LLIL_LSL(self, expr): mask = (1 << expr.size * 8) - 1 left = self.visit(expr.left) right = self.visit(expr.right) return (left << right) & mask def visit_LLIL_LSR(self, expr): left = self.visit(expr.left) right = self.visit(expr.right) return left >> right if __name__ == '__main__': il = LowLevelILFunction(Architecture['x86_64']) emi = Emilator(il) emi.set_register_value('rbx', -1) emi.set_register_value('rsp', 0x1000) print '[+] Mapping memory at 0x1000 (size: 0x1000)...' emi.map_memory(0x1000, flags=SegmentFlag.SegmentReadable) print '[+] Initial Register State:' for r, v in emi.registers.iteritems(): print '\t{}:\t{:x}'.format(r, v) il.append(il.push(8, il.const(8, 0xbadf00d))) il.append(il.push(8, il.const(8, 0x1000))) il.append(il.set_reg(8, 'rax', il.pop(8)))
def lift_nopy(il: LowLevelILFunction, insn: SHInsn): il.append(il.nop())
def _lift_op(il: LowLevelILFunction, insn: SHInsn, op: Oper, sign_ext=False): il_op = None if op.type == OpType.REG: if op.reg == "PC": il_op = il.const(RSIZE, insn.addr) else: il_op = il.reg(RSIZE, op.reg) elif op.type == OpType.IMM or op.type == OpType.DISP: assert op.size != 0, f"Invalid instruction at: 0x{insn.addr:x}" if op.type == OpType.DISP and op.is_ref and op.is_pair: # Fetch the next part of the pair next_op = None for i, cur_op in enumerate(insn.opcode["args"]): if cur_op.is_pair: next_op = insn.opcode["args"][i + 1] break assert next_op is not None, f"Invalid instruction at: 0x{insn.addr:x}" assert next_op.type == OpType.REG, f"Invalid instruction at: 0x{insn.addr:x}" if next_op.reg == "PC": cur_il = il.shift_left( RSIZE, il.const(RSIZE, op.val), il.const(RSIZE, int(insn.opcode['width'] / 2))) if insn.opcode["width"] == 4: next_il = il.and_expr(RSIZE, il.const(RSIZE, insn.addr), il.const(RSIZE, 0xFFFFFFFC)) else: next_il = il.const(RSIZE, insn.addr) next_il = il.add(RSIZE, next_il, il.const(RSIZE, 4)) else: cur_il = il.const(op.size, op.val) next_il = il.reg(RSIZE, next_op.reg) il_op = il.add(RSIZE, cur_il, next_il) else: il_op = il.const(op.size, op.val) if sign_ext: il_op = il.sign_extend(RSIZE, il_op) return il_op
def _handle_jump(il: LowLevelILFunction, value): label = il.get_label_for_address(Architecture['M6800'], value) return il.jump(il.const(2, value)) if label is None else il.goto(label)
def lift_cmp_eq(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 2, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] op_2 = insn.opcode["args"][1] extend = False if op_1.type == OpType.IMM: extend = True t = LowLevelILLabel() f = LowLevelILLabel() next_insn = LowLevelILLabel() il.append( il.if_expr( il.compare_equal( RSIZE, Lifter._lift_op(il, insn, op_1, sign_ext=extend), Lifter._lift_op(il, insn, op_2)), t, f)) il.mark_label(t) il.append(il.set_flag('t', il.const(0, 1))) il.append(il.goto(next_insn)) il.mark_label(f) il.append(il.set_flag('t', il.const(0, 0))) il.mark_label(next_insn)
def lift_mov_b(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) > 1, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] if op_1.is_pair: op_2 = insn.opcode["args"][2] else: op_2 = insn.opcode["args"][1] extra_op = None if op_1.is_ref: il_op = il.set_reg( RSIZE, op_2.reg, il.load(insn.opcode["width"], Lifter._lift_op(il, insn, op_1))) if op_1.mod_reg != 0: if op_1.type == OpType.REG and op_2.type == OpType.REG and op_1.mod_reg > 0: extra_op = None else: extra_op = il.set_reg( RSIZE, op_1.reg, il.add(RSIZE, il.reg(RSIZE, op_1.reg), il.const(RSIZE, op_1.mod_reg))) elif op_2.is_ref: il_op = il.store(insn.opcode["width"], Lifter._lift_op(il, insn, op_2), Lifter._lift_op(il, insn, op_1)) if op_2.mod_reg != 0: extra_op = il.set_reg( RSIZE, op_2.reg, il.add(RSIZE, il.reg(RSIZE, op_2.reg), il.const(RSIZE, op_2.mod_reg))) else: assert False, f"Invalid instruction at: 0x{insn.addr:x}" il.append(il_op) if extra_op is not None: il.append(extra_op)
def lift_mova(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 3, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] op_2 = insn.opcode["args"][1] op_3 = insn.opcode["args"][2] il.append( il.set_reg( RSIZE, op_3.reg, il.add( RSIZE, il.and_expr(RSIZE, il.reg(RSIZE, op_2.reg), il.const(RSIZE, 0xFFFFFFFC)), il.add( RSIZE, il.const(RSIZE, 4), il.shift_left(RSIZE, il.const(RSIZE, op_1.val), il.const(RSIZE, 2))))))
def get_instruction_low_level_il(self, data, addr, il: LowLevelILFunction): try: (nmemonic, inst_length, inst_operand, inst_type, mode, value) = M6800._decode_instruction(data, addr) except LookupError as error: log_error(error.__str__()) return None # Figure out what the instruction uses load_size = 2 if nmemonic in BIGGER_LOADS else 1 operand, second_operand = None, None # if this is a conditional branch, handle that separately if inst_type == InstructionType.CONDITIONAL_BRANCH: M6800._handle_branch(il, nmemonic, inst_length, value) return inst_length # if this is an unconditional branch, handle that separately if inst_type == InstructionType.UNCONDITIONAL_BRANCH: M6800._handle_jump(il, value) return inst_length if mode == AddressMode.ACCUMULATOR: # handle the case where we need the name, not the reg, for pop operand = inst_operand if nmemonic == 'PUL' else il.reg( 1, inst_operand) elif mode == AddressMode.INDEXED: # set the destination variable for the memory store operations destination = il.add(2, il.reg(2, 'IX'), il.const(1, value)) operand = il.load(load_size, destination) elif mode in [AddressMode.DIRECT, AddressMode.EXTENDED]: # set the destination variable for the memory store operations destination = il.const(inst_length - 1, value) operand = il.load(load_size, destination) elif mode == AddressMode.IMMEDIATE: operand = il.const(inst_length - 1, value) elif mode == AddressMode.RELATIVE: # we have already calculated the absolute address # set the destination variable for the memory store operations destination = il.const(2, value) operand = il.load(load_size, destination) # if we are dual mode, we have to handle things special if inst_type == InstructionType.DUAL: second_operand = inst_operand # calculate the base LLIL operation = LLIL_OPERATIONS[nmemonic](il, operand, second_operand) # if the instruction has different destinations, set them appropriately if nmemonic in REGISTER_OR_MEMORY_DESTINATIONS: if mode == AddressMode.ACCUMULATOR: operation = il.set_reg(1, inst_operand, operation) else: operation = il.store(1, destination, operation) # Finally, calculate and append the instruction(s) il.append(operation) return inst_length
def lift_tst(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 2, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] op_2 = insn.opcode["args"][1] t = LowLevelILLabel() f = LowLevelILLabel() next_insn = LowLevelILLabel() il.append( il.if_expr( il.compare_equal( RSIZE, il.and_expr(RSIZE, Lifter._lift_op(il, insn, op_1), Lifter._lift_op(il, insn, op_2)), il.const(RSIZE, 0)), t, f)) il.mark_label(t) il.append(il.set_flag('t', il.const(0, 1))) il.append(il.goto(next_insn)) il.mark_label(f) il.append(il.set_flag('t', il.const(0, 0))) il.mark_label(next_insn)
def _handle_branch(il: LowLevelILFunction, nmemonic, inst_length, value): true_label = il.get_label_for_address(Architecture['M6800'], value) if true_label is None: true_label = LowLevelILLabel() indirect = True else: indirect = False false_label_found = True false_label = il.get_label_for_address( Architecture['M6800'], il.current_address + inst_length) if false_label is None: false_label = LowLevelILLabel() false_label_found = False il.append( il.if_expr(LLIL_OPERATIONS[nmemonic](il, None, None), true_label, false_label)) if indirect: il.mark_label(true_label) il.append(il.jump(il.const(2, value))) if not false_label_found: il.mark_label(false_label)
def lift_bt(il: LowLevelILFunction, insn: SHInsn): assert len(insn.opcode["args"] ) == 1, f"Invalid instruction at: 0x{insn.addr:x}" op_1 = insn.opcode["args"][0] t = il.get_label_for_address(Architecture["superh"], op_1.val) if t is None: t = LowLevelILLabel() indirect = True else: indirect = False f = LowLevelILLabel() il.append(il.if_expr(il.flag("t"), t, f)) if indirect: il.mark_label(t) il.append(il.jump(il.const(RSIZE, op_1.val))) il.mark_label(f)