Пример #1
0
    def output(self, outctx):
        insn = outctx.insn
        mne = ida_ua.print_insn_mnem(insn.ea)

        if insn.itype in [ida_allins.ARM_msr, ida_allins.ARM_mrs]:
            if insn.ops[2].type > 0:
                cp_reg, gp_reg = self.decode_msr_mrs(insn)
                if cp_reg:
                    if insn.itype == ida_allins.ARM_msr:
                        return Arch.output_insn(outctx, mne, cp_reg, gp_reg)
                    else:
                        return Arch.output_insn(outctx, mne, gp_reg, cp_reg)

            else:
                fields = {5: "SPSel", 6: "DAIFSet", 7: "DAIFClr"}
                pstatefield = fields.get(insn.ops[0].value, None)
                if pstatefield:
                    outctx.out_custom_mnem(mne.upper(), 16)
                    outctx.out_register(pstatefield)
                    outctx.out_printf(", ")
                    imm = ida_ua.print_operand(insn.ea, 1)
                    outctx.out_printf(imm)
                    outctx.flush_outbuf()
                    return True

        if insn.itype == ida_allins.ARM_sys:
            op1 = insn.ops[0].value
            crn = insn.ops[1].reg
            crm = insn.ops[2].reg
            op2 = insn.ops[3].value
            xt = insn.ops[4].reg

            ops = [1, op1, crn, crm, op2]
            gp_reg = ida_idp.ph.regnames[xt]
            cp_reg = self.find_reg_enc("SYS", ops)
            if cp_reg:
                mne, op = cp_reg.split()
                if xt == 160:
                    return Arch.output_insn(outctx, mne, op)
                else:
                    return Arch.output_insn(outctx, mne, op, gp_reg)

        return False
Пример #2
0
def matches(ea, reqs, gets):
    results = []
    for offs, ins in reqs:
        mnem = ida_lines.tag_remove(ida_ua.print_insn_mnem(ea + offs) or '')
        if ins[0] != mnem:
            return None
        i = 0
        for arg in ins[1:]:
            opnd = ida_lines.tag_remove(
                ida_ua.print_operand(ea + offs, i) or '')
            if opnd != arg and re.match('^' + arg + '$', opnd) is None:
                return None
            i += 1
    for get in gets:
        if type(get) == tuple:
            reqi, opi, fun = get
            results += [fun(idc.get_operand_value(ea + reqs[reqi][0], opi))]
        else:
            results += [get]
    return results
Пример #3
0
def color_head(ea):
    flags = ida_bytes.get_flags(ea)
    if not ida_bytes.is_code(flags):
        return

    mnem = ida_ua.print_insn_mnem(ea)
    if mnem == 'call':
        logger.debug('call: 0x%x', ea)
        idc.set_color(ea, idc.CIC_ITEM, CALL_COLOR)
    elif mnem == 'xor':
        if idc.get_operand_value(ea, 0) != idc.get_operand_value(ea, 1):
            logger.debug('non-zero xor: 0x%x', ea)
            idc.set_color(ea, idc.CIC_ITEM, ENCRYPT_COLOR)
    elif mnem in ('sdit', 'sgdt', 'sldt', 'smsw', 'str', 'in', 'cpuid'):
        logger.debug('anti-vm: 0x%x', ea)
        idc.set_color(ea, idc.CIC_ITEM, ANTIANALYSIS_COLOR)
    elif mnem == 'in':
        if idc.get_operand_value(ea, 0) in ("3", "2D"):
            logger.debug('anti-debug: 0x%x', ea)
            idc.set_color(ea, idc.CIC_ITEM, ANTIANALYSIS_COLOR)
    elif mnem in ('rdtsc', 'icebp'):
        logger.debug('anti-debug: 0x%x', ea)
        idc.set_color(ea, idc.CIC_ITEM, ANTIANALYSIS_COLOR)
Пример #4
0
    def output(self, outctx):
        insn = outctx.insn
        mne = ida_ua.print_insn_mnem(insn.ea)

        if insn.itype in [ida_allins.ARM_mcr, ida_allins.ARM_mrc]:
            cp_reg, gp_reg = self.decode_mcr_mrc(insn)
            if cp_reg:
                if insn.itype == ida_allins.ARM_mcr:
                    return Arch.output_insn(outctx, mne, cp_reg, gp_reg)
                else:
                    return Arch.output_insn(outctx, mne, gp_reg, cp_reg)

        if insn.itype in [ida_allins.ARM_mcrr, ida_allins.ARM_mrrc]:
            cp = insn.ops[0].specflag1
            op3 = insn.ops[0].value
            rt = insn.ops[1].reg
            rt2 = insn.ops[1].specflag1
            crm = insn.ops[1].specflag2

            ops = [cp, op3, crm]
            gp_reg = "%s%s%s:%s%s%s" % (
                ida_idp.ph.regnames[rt2],
                ida_lines.SCOLOR_OFF,
                ida_lines.SCOLOR_REG,
                ida_lines.SCOLOR_ON,
                ida_lines.SCOLOR_REG,
                ida_idp.ph.regnames[rt],
            )
            cp_reg = self.find_reg_enc("MCRR|MRRC", ops)
            if cp_reg:
                if insn.itype == ida_allins.ARM_mcrr:
                    return Arch.output_insn(outctx, mne, cp_reg, gp_reg)
                else:
                    return Arch.output_insn(outctx, mne, gp_reg, cp_reg)

        return False
Пример #5
0
def idenLib():
    global func_sigs
    global mainSigs
    # function sigs from the current binary
    func_bytes_addr = {}
    for addr, size in getFuncRanges():
        f_bytes = getOpcodes(addr, size)
        func_bytes_addr[f_bytes] = addr

    # load sigs
    if not os.path.isdir(symEx_dir):
        print("[idenLib - FAILED] There is no {} directory".format(symEx_dir))
        return

    if os.path.isfile(idenLibCache):
        func_sigs = pickle.load(open(idenLibCache, "rb"))
        if os.path.isfile(idenLibCacheMain):
            mainSigs = pickle.load(open(idenLibCacheMain, "rb"))
    else:
        idenLibProcessSignatures()
    # apply sigs
    counter = 0
    mainDetected = False
    for sig_opcodes, addr in func_bytes_addr.items():
        if func_sigs.has_key(sig_opcodes):
            func_name = func_sigs[sig_opcodes]
            current_name = ida_funcs.get_func_name(addr)
            if (current_name != func_name):
                digit = 1
                while func_name in getNames():
                    func_name = func_name + str(digit)
                    digit = digit + 1
                ida_name.set_name(addr, func_name, ida_name.SN_NOCHECK)
                print("{}: {}".format(hex(addr), func_name))
                counter = counter + 1
        if mainSigs.has_key(sig_opcodes):  # "main" sig
            callInstr = mainSigs[sig_opcodes][1] + addr
            if ida_ua.print_insn_mnem(callInstr) == "call":
                call_target = idc.get_operand_value(callInstr, 0)
                current_name = ida_funcs.get_func_name(call_target)
                func_name = mainSigs[sig_opcodes][0]
                if (current_name != func_name):
                    ida_name.set_name(call_target, func_name,
                                      ida_name.SN_NOCHECK)
                    print("{}: {}".format(hex(call_target), func_name))
                    counter = counter + 1
                    mainDetected = True
    if not mainDetected:
        for entry in idautils.Entries():
            for sig_opcodes, name_funcRva_EntryRva in mainSigs.items():
                callInstr = name_funcRva_EntryRva[2] + entry[2]  # from EP
                if ida_ua.print_insn_mnem(callInstr) == "call":
                    fromFunc = name_funcRva_EntryRva[1]
                    func_start = callInstr - fromFunc
                    func_opcodes = getOpcodes(func_start, MAX_FUNC_SIZE)
                    if func_opcodes.startswith(sig_opcodes):
                        call_target = idc.get_operand_value(callInstr, 0)
                        current_name = ida_funcs.get_func_name(call_target)
                        func_name = mainSigs[sig_opcodes][0]
                        if (current_name != func_name):
                            ida_name.set_name(call_target, func_name,
                                              ida_name.SN_NOCHECK)
                            print("{}: {}".format(hex(call_target), func_name))
                            counter = counter + 1
                            mainDetected = True
                            break

    print("[idenLib] Applied to {} function(s)".format(counter))
Пример #6
0
    def execute(self, start=None, end=None, max_instructions=10000):
        """
        "Execute" the instruction at IP and store results in the context.
        The RIP/EIP register will be set to the value supplied in IP so that it is
        correct.

        :param start: instruction address to start execution (defaults to currently set ip)
        :param end: instruction to stop execution (not including)
            (defaults to only run start)
        :param max_instructions: Maximum number of instructions to execute before
            raising an RuntimeError

        :raises RuntimeError: If maximum number of instructions get hit.
        """
        if not start:
            start = self.ip

        # Set instruction pointer to where we are currently executing.
        self.ip = start

        # Extra processing if we are at the start of a function.
        func_obj = ida_funcs.get_func(self.ip)
        if func_obj.start_ea == self.ip:
            # Reset the sp_start
            self._sp_start = self.sp

            # Add the passed in arguments to the variables map.
            # (This also helps to standardize the argument names to "a*" instead of "arg_*")
            for arg in self.passed_in_args:
                addr = arg.addr
                # TODO: Support variables from registers?
                if addr is not None:
                    if arg.is_stack:
                        try:
                            frame = ida_frame.get_frame(func_obj)
                            if not frame:
                                logger.warning(
                                    f"Failed to get frame for function argument: {repr(arg)}"
                                )
                                continue

                            # Getting member stack offset from name is more reliable then calculating
                            # it from the address.
                            member = ida_struct.get_member_by_name(
                                frame, arg.name)
                            if not member:
                                logger.warning(
                                    f"Failed to get member for function argument: {repr(arg)}"
                                )
                                continue

                            self.variables.add(addr,
                                               frame_id=frame.id,
                                               stack_offset=member.soff)
                        except ValueError:
                            logger.warning(
                                f"Failed to get stack information for function argument: {repr(arg)}"
                            )
                    else:
                        self.variables.add(addr)

        # If end is provided, recursively run execute() until ip is end.
        if end is not None:
            count = max_instructions
            prev_ecx = self.registers.ecx
            prev_ecx_count = count
            while self.ip != end:
                if ida_ua.print_insn_mnem(self.ip) == 'retn':
                    return
                self.execute()
                # TODO: Re-enable this feature after rigorous testing.
                # # Dynamically allow more instructions to be executed if we detect we are in a loop
                # # and it is making progress.
                # # Ie. this will allow most while statements not to ding our max instruction quota.
                # if self.registers.ecx and (self.registers.ecx < prev_ecx or prev_ecx == 0):
                #     if prev_ecx:
                #         count += min(prev_ecx_count - count, 1000)
                #     prev_ecx = self.registers.ecx
                #     prev_ecx_count = count
                count -= 1
                if not count:
                    raise RuntimeError('Hit maximum number of instructions.')
            return

        # Determine if a rep* instruction and add termination condition.
        term_condition = None
        if idc.get_wide_byte(start) in (0xF2, 0xF3):
            insn = idc.GetDisasm(
                start)  # IDA pro never has operands for rep opcodes.
            if insn.startswith("rep "):
                term_condition = lambda: self.registers.ecx == 0
                term_condition.unconditional = True
            elif insn.startswith(("repe ", "repz ")):
                term_condition = lambda: self.registers.ecx == 0 or self.registers.zf == 0
                term_condition.unconditional = False
            elif insn.startswith(("repne ", "repnz ")):
                term_condition = lambda: self.registers.ecx == 0 or self.registers.zf == 1
                term_condition.unconditional = False

        # Emulate instruction.
        mnem = ida_ua.print_insn_mnem(start)

        # Log a header line for debug messages of this instruction.
        # This is simpler and faster then trying to include the information at each log line
        logger.debug("[0x%X %03X] :: %s", start, self.sp_diff, mnem)

        # Run any pre-hooks first.
        self.execute_instruction_hooks(start, mnem, pre=True)

        instruction = self.OPCODES.get(mnem)
        if instruction:
            operands = self.operands

            try:
                if term_condition:
                    if self.emulator.disabled_rep:
                        logger.debug("Ignoring rep instructions: DISABLED.")

                    # As a safety measure, don't allow rep instructions to surpass
                    # our max memory read limit.
                    # Only do this check if the terminating condition is unconditional, otherwise
                    # this number usually big because it expects zf to be toggled.
                    elif term_condition.unconditional and self.registers.ecx > self.memory.MAX_MEM_READ:
                        logger.warning(
                            "Emulation attempted to read %s instruction %d times. "
                            "Ignoring instruction.", mnem, self.registers.ecx)
                    else:
                        logger.debug("Emulating %s instruction %d times.",
                                     mnem, self.registers.ecx)
                        count = 0
                        while not term_condition():
                            instruction(self, start, mnem, operands)
                            self.registers.ecx -= 1
                            # Stop if we are iterating too much.
                            count += 1
                            if count > self.memory.MAX_MEM_READ:
                                logger.warning(
                                    "Looped too many times, exiting prematurely."
                                )
                                break
                else:
                    instruction(self, start, mnem, operands)
            except Exception:
                logger.exception("Failed to execute address 0x%X: %s", start,
                                 idc.GetDisasm(start))
        else:
            logger.debug("%s instruction not implemented.", mnem)

        # Record executed instruction.
        self.executed_instructions.append(start)

        # Run any post-hooks
        self.execute_instruction_hooks(start, mnem, pre=False)

        # Add a blank space to help visually separate logs for each instruction.
        logger.debug(" ")

        # After execution, set instruction pointer to next instruction assuming
        # standard code flow and if no jump was made.
        if self.ip == start:
            self.ip = idc.next_head(start)
Пример #7
0
def get_mnem(ea):
    """
    获取操作符并去除末尾的 ".W"
    """
    mnem = ida_ua.print_insn_mnem(ea).split('.')[0]
    return mnem