示例#1
0
    def update_flags_from_il(cpu, il):
        # FIXME what about get_flag_condition_low_level_il
        from binaryninja.lowlevelil import LowLevelILInstruction
        flags = cpu.arch.flags_written_by_flag_write_type.get(il.flags)
        if flags is None:
            return
        func = cpu.disasm.current_llil_func

        # FIXME normally we would pass il.operands but binja has a bug here
        operands = [i for i, _ in enumerate(il.operands)]
        for f in flags:
            expr = cpu.arch.get_flag_write_low_level_il(
                il.operation, il.size, il.flags, f, operands,
                func.low_level_il)
            flag_il = LowLevelILInstruction(func, expr.index)
            # FIXME properly invoke the implementation
            op_name = str(flag_il.operation).split(".")[1][len("LLIL_"):]
            if op_name == "UNIMPL":
                continue
            implementation = getattr(cpu, op_name)
            # flag_il.operands have indexes, involving the original operands.
            # E.g., for xor.d{*}(eax, eax), invoking `print flag_il.operands`
            # we get [<il: 0 ^ 1>, <il: 0>]
            # where 0 and 1 are the indexes. We need the operands to be
            # 'eax'. 'eax'
            flop = []
            for i, o in enumerate(flag_il.operands):
                for j, x in enumerate(o.operands):
                    x = il.operands[int(str(x))].op
                    o.operands[j] = x
                flop.append(o)
            flag_il.operands = [
                BinjaOperand(cpu, flag_il, x) for x in flag_il.operands
            ]
            res = implementation(*flag_il.operands)
示例#2
0
    def perform_get_instruction_low_level_il(self, data, addr, il):
        log('Asking to decode %d bytes at 0x%x' % (len(data), addr))
        valid, instr = get_instruction(data[0:8], addr)
        if not valid:
            log('*********** Tried an failed **********')
            # This is _EXCEEDINGLY_ important to return on failure.
            # Things will break in creative ways if anything other than None
            # is returned for invalid data
            return None
        if instr.opcode not in InstructionLLIL:
            log('Adding il.undefined()')
            # il.append(il.unimplemented())
            il.append(il.undefined())
        else:
            il_exp = InstructionLLIL[instr.opcode](il, instr)
            if il_exp is not None:
                il.append(il_exp)
                log('appended: %s' % LowLevelILInstruction(il, il_exp.index))
            else:
                log('Failed to generate il')

        log('Full IL Decode was successful len(il): %d' % len(il))
        return 8
示例#3
0
    def IF(cpu, condition, true, false):
        import binaryninja.enums as enums
        from binaryninja.lowlevelil import LowLevelILInstruction

        il = cpu.disasm.disasm_il
        cond = condition.op.operands[0].op
        exp = cpu.arch.get_default_flag_condition_low_level_il(
            cond, il.function)
        cond_il = LowLevelILInstruction(cpu.disasm.current_llil_func,
                                        exp.index)
        implementation = getattr(cpu, cond_il.operation.name[len("LLIL_"):])
        cond_il.operands = [
            BinjaOperand(cpu, cond_il, x) for x in cond_il.operands
        ]
        res = implementation(*cond_il.operands)
        idx = true.op if res else false.op
        assert isinstance(idx, long)

        try:
            next_il = cpu.disasm.current_llil_func[idx]
        except IndexError as e:
            # If we got an index error this means that we have the true
            # branch executing one insn followed by a GOTO, and the false
            # branch is outside the current_llil_func and is a JUMP
            # FIXME verify that this is true
            cpu.PC += cpu.disasm.disasm_insn_size
            return

        # if we have a (real) instruction from the IF family, the next
        # instruction should have an address different than the current PC
        if next_il.address != cpu.disasm.current_pc:
            cpu.PC = next_il.address + cpu.disasm.entry_point_diff
            return

        # The next IL instruction has the same PC. Probably a real assembly
        # instruction was resolved into multiple IL instructions. Clear the
        # queue and execute them here
        last_op_in_queue = cpu.disasm.il_queue[-1][1].operation
        assert (last_op_in_queue == enums.LowLevelILOperation.LLIL_GOTO
                or last_op_in_queue == enums.LowLevelILOperation.LLIL_JUMP
                or last_op_in_queue == enums.LowLevelILOperation.LLIL_JUMP_TO)
        del cpu.disasm.il_queue[:]

        # the sequence of instructions sharing the same PC includes both the
        # True and False branches. If we start executing at the True branch,
        # make sure we don't also execute on the False branch
        break_idx = true.op if not res else false.op

        while idx != break_idx and next_il.address == cpu.disasm.current_pc:
            goto_addr = None
            implementation = getattr(cpu,
                                     next_il.operation.name[len("LLIL_"):])
            next_il.operands = [
                BinjaOperand(cpu, next_il, x) for x in next_il.operands
            ]
            cpu.disasm.insn_size = next_il.size
            goto_addr = implementation(*next_il.operands)
            try:
                idx += 1
                next_il = cpu.disasm.current_llil_func[idx]
            except IndexError as e:
                break
        assert goto_addr is not None
        cpu.PC = goto_addr