Ejemplo n.º 1
0
    def populate_items(self):
        self.items = []

        for (func_ea, xrefs) in self.profile.functions.iteritems():
            if not self.function_filters or func_ea in self.function_filters:
                orig_items_len = len(self.items)

                for xref in xrefs:
                    if not self.string_filters or \
                            xref.string in self.string_filters:
                        if xref.type == callable:
                            display_string = xref.string + "()"
                        elif xref.type == str:
                            display_string = '"%s"' % xref.string
                        else:
                            display_string = xref.string

                        self.items.append([
                            ida_shims.get_name(func_ea), display_string,
                            xref.xref, func_ea
                        ])

                if len(self.items) != orig_items_len:
                    self.items.append([
                        self.DELIM_COL_1, self.DELIM_COL_2, idc.BADADDR,
                        idc.BADADDR
                    ])

        # Remove the last delimiter column
        if self.items and self.items[-1][-1] == idc.BADADDR:
            self.items.pop(-1)
Ejemplo n.º 2
0
    def rename_functions(self, debug=True, dry_run=False):
        '''
        Renames functions starting with "sub_" based on unique string xrefs.

        @debug   - Set to False to suppress debug output.
        @dry_run - Set to True to perform a dry run (functions will not actually
                   be renamed).

        Returns the number of renamed functions.
        '''
        count = 0

        for (function_address,
             function_name) in self.func2str_mappings().items():
            if ida_shims.get_name(function_address).startswith("sub_"):
                if dry_run or ida_shims.set_name(function_address,
                                                 function_name):
                    if debug:
                        print("0x%.8X  =>  %s" %
                              (function_address, function_name))
                    count += 1

        if debug:
            print("Renamed %d functions based on unique string xrefs!" % count)

        return count
Ejemplo n.º 3
0
    def populate_items(self):
        self.items = []

        for function in self.lb.functions:
            candidates = []

            if function.leaf:
                if function.xrefs < self.min_xrefs:
                    continue
                if function.loop is False and self.must_have_loop is True:
                    continue

            for candidate in function.candidates:
                candidates.append(candidate)

            if function.xrefs:
                xrefs = str(function.xrefs)
            else:
                xrefs = "*"

            if function.argc is not None:
                argc = str(function.argc)
            else:
                argc = "*"

            if function.leaf:
                loops = str(function.loop)
            else:
                loops = "*"

            name = ida_shims.get_name(function.start)

            self.items.append([
                name, xrefs, argc, loops, ', '.join(candidates), function.leaf
            ])
Ejemplo n.º 4
0
    def __init__(self, **kwargs):
        self.argc = None
        self.loop = False
        self.leaf = False
        self.xrefs = None
        self.fmtarg = None
        self.start = idc.BADADDR
        self.end = idc.BADADDR
        self.candidates = {}
        self.argp = ArgParser()

        for (k, v) in kwargs.iteritems():
            setattr(self, k, v)

        self.name = ida_shims.get_name(self.start)

        if self.xrefs is None:
            self.xrefs = len([x for x in idautils.XrefsTo(self.start)])

        if not self.candidates:
            for prototype in self.PROTOTYPES:
                if self.leaf and prototype.fmtarg is None and \
                        prototype.argc == self.argc and prototype.loop == self.loop:
                    if prototype.name in self.candidates:
                        self.candidates[prototype.name] += 1
                    else:
                        self.candidates[prototype.name] = 1
                elif not self.leaf and \
                        self.fmtarg is not None and \
                        prototype.fmtarg is not None and \
                        self.fmtarg == prototype.fmtarg:
                    if prototype.name in self.candidates:
                        self.candidates[prototype.name] += 1
                    else:
                        self.candidates[prototype.name] = 1
Ejemplo n.º 5
0
 def _name(self, ea):
     name = ida_shims.get_name(ea)
     if not name:
         name = ida_shims.get_func_off_str(ea)
         if not name:
             name = '0x%X' % ea
     return name
Ejemplo n.º 6
0
    def _find_and_plot_paths(self, sources, targets, klass=AlleyCatFunctionPaths):
        results = []

        for target in targets:
            for source in sources:
                s = time.time()
                r = klass(source, target).paths
                e = time.time()
                print "Found %d paths in %f seconds." % (len(r), (e-s))

                if r:
                    results += r
                else:
                    name = ida_shims.get_name(target)
                    if not name:
                        name = "0x%X" % target
                    print "No paths found to", name

        if results:
            # Be sure to close any previous graph before creating a new one.
            # Failure to do so may crash IDA.
            try:
                self.graph.Close()
            except:
                pass

            self.graph = AlleyCatGraph(results, 'Path Graph')
            self.graph.Show()
Ejemplo n.º 7
0
    def _build_function_xrefs(self):
        for function in idautils.Functions():
            for xref in idautils.XrefsTo(function):
                func = idaapi.get_func(xref.frm)
                if func:
                    start_ea = ida_shims.start_ea(func)
                    if not self.functions.has_key(start_ea):
                        self.functions[start_ea] = list()

                    self.functions[start_ea].append(IDAProfilerXref(
                        ea=function, string=ida_shims.get_name(function),
                        xref=xref.frm, type=callable))
Ejemplo n.º 8
0
Archivo: rizzo.py Proyecto: ufwt/ida
 def rename(self, ea, name):
     # Don't rely on the name in curfunc, it could have already been renamed
     curname = ida_shims.get_name(ea)
     # Don't rename if the name is a special identifier, or if the ea has
     # already been named
     if curname.startswith('sub_') and \
             name.split('_')[0] not in \
             ['sub', 'loc', 'unk', 'dword', 'word', 'byte']:
         # Don't rename if the name already exists in the IDB
         if ida_shims.get_name_ea_simple(name) == idc.BADADDR:
             if ida_shims.set_name(ea, name):
                 ida_shims.set_func_flags(
                     ea, (ida_shims.get_func_flags(ea) | idc.FUNC_LIB))
                 return 1
     return 0
Ejemplo n.º 9
0
    def get_name_by_ea(self, ea):
        """
        Get the name of the specified address.

        @ea - Address.

        Returns a name for the address, one of idc.Name, idc.GetFuncOffset or
        0xXXXXXXXX.
        """
        name = ida_shims.get_name(ea)
        if not name:
            name = ida_shims.get_func_off_str(ea)
            if not name:
                name = "0x%X" % ea
        return name
Ejemplo n.º 10
0
    def pointify(self):
        counter = 0

        print("Renaming pointers...", end=' ')

        for (name_ea, name) in idautils.Names():
            for xref in idautils.XrefsTo(name_ea):
                xref_name = ida_shims.get_name(xref.frm)
                if xref_name and xref_name.startswith("off_"):
                    i = 0
                    new_name = name + "_ptr"
                    while ida_shims.get_name_ea_simple(
                            new_name) != idc.BADADDR:
                        new_name = name + "_ptr%d" % i
                        i += 1

                    if ida_shims.set_name(xref.frm, new_name):
                        counter += 1
                    #else:
                    #    print "Failed to create name '%s'!" % new_name

        print("renamed %d pointers" % counter)
Ejemplo n.º 11
0
    def parse_function_tables(self):
        count = 0

        for pattern in self.search():
            name2func = {}

            ea = pattern.start
            while ea < pattern.stop:
                string_address = ida_shims.get_wide_dword(
                    ea + (pattern.name_element * pattern.element_size))
                function_address = ida_shims.get_wide_dword(
                    ea + (pattern.function_element * pattern.element_size))

                new_function_name = ida_shims.get_strlit_contents(
                    string_address).decode("utf8")
                current_function_name = ida_shims.get_name(function_address)

                if not self.valid_function_name(new_function_name):
                    print("ERROR: '%s' is not a valid function name. This is " \
                          "likely not a function table, or I have parsed it " \
                          "incorrectly!" % new_function_name)
                    print("       Ignoring all entries in the structures " \
                          "between 0x%X and 0x%X.\n" % (pattern.start,
                                                        pattern.stop))
                    name2func = {}
                    break
                elif current_function_name.startswith("sub_"):
                    name2func[new_function_name] = function_address

                ea += (pattern.num_elements * pattern.element_size)

            for (name, address) in name2func.items():
                print("0x%.8X => %s" % (address, name))
                ida_shims.set_name(address, name)
                count += 1

        print("Renamed %d functions!" % count)
Ejemplo n.º 12
0
Archivo: rizzo.py Proyecto: ufwt/ida
    def generate(self):
        signatures = RizzoSignatures()

        # Generate unique string-based function signatures
        for (ea, string) in self.strings.iteritems():
            # Only generate signatures on reasonably long strings with one xref
            if len(string.value) >= 8 and len(string.xrefs) == 1:
                func = idaapi.get_func(string.xrefs[0])
                if func:
                    str_hash = self.sighash(string.value)

                    # Check for and remove string duplicate signatures (the same
                    # string can appear more than once in an IDB).
                    # If no duplicates, add this to the string signature dict.
                    if str_hash in signatures.strings:
                        del signatures.strings[str_hash]
                        signatures.stringdups.add(str_hash)
                    elif str_hash not in signatures.stringdups:
                        signatures.strings[str_hash] = ida_shims.start_ea(func)

        # Generate formal, fuzzy, and immediate-based function signatures
        for ea in idautils.Functions():
            func = idaapi.get_func(ea)
            if func:
                # Generate a signature for each block in this function
                blocks = self.function(func)

                # Build function-wide formal and fuzzy signatures by simply
                # concatenating the individual function block signatures.
                formal = self.sighash(''.join(
                    [str(e) for (e, f, i, c) in blocks]))
                fuzzy = self.sighash(''.join(
                    [str(f) for (e, f, i, c) in blocks]))

                # Add this signature to the function dictionary.
                start_ea = ida_shims.start_ea(func)
                signatures.functions[start_ea] = (ida_shims.get_name(start_ea),
                                                  blocks)

                # Check for and remove formal duplicate signatures.
                # If no duplicates, add this to the formal signature dict.
                if signatures.formal.has_key(formal):
                    del signatures.formal[formal]
                    signatures.formaldups.add(formal)
                elif formal not in signatures.formaldups:
                    signatures.formal[formal] = ida_shims.start_ea(func)

                # Check for and remove fuzzy duplicate signatures.
                # If no duplicates, add this to the fuzzy signature dict.
                if signatures.fuzzy.has_key(fuzzy):
                    del signatures.fuzzy[fuzzy]
                    signatures.fuzzydups.add(fuzzy)
                elif fuzzy not in signatures.fuzzydups:
                    signatures.fuzzy[fuzzy] = ida_shims.start_ea(func)

                # Check for and remove immediate duplicate signatures.
                # If no duplicates, add this to the immediate signature dict.
                for (e, f, immediates, c) in blocks:
                    for immediate in immediates:
                        if signatures.immediates.has_key(immediate):
                            del signatures.immediates[immediate]
                            signatures.immediatedups.add(immediate)
                        elif immediate not in signatures.immediatedups:
                            signatures.immediates[immediate] = \
                                ida_shims.start_ea(func)

        # These need not be maintained across function calls,
        # and only add to the size of the saved signature file.
        signatures.fuzzydups = set()
        signatures.formaldups = set()
        signatures.stringdups = set()
        signatures.immediatedups = set()

        # DEBUG
        signatures.show()

        return signatures
Ejemplo n.º 13
0
Archivo: rizzo.py Proyecto: ufwt/ida
    def block(self, block):
        '''
        Returns a tuple:
        ([formal, block, signatures], [fuzzy, block, signatures],
        set([unique, immediate, values]), [called, function, names])
        '''
        formal = []
        fuzzy = []
        functions = []
        immediates = []

        ea = ida_shims.start_ea(block)
        while ea < ida_shims.end_ea(block):
            insn = ida_shims.decode_insn(ea)

            # Get a list of all data/code refs from the current instruction
            drefs = [x for x in idautils.DataRefsFrom(ea)]
            crefs = [x for x in idautils.CodeRefsFrom(ea, False)]

            # Add all instruction mnemonics to the formal block hash
            formal.append(ida_shims.print_insn_mnem(ea))

            # If this is a call instruction, be sure to note the name of the
            # function being called. This is used to apply call-based
            # signatures to functions.
            #
            # For fuzzy signatures, we can't use the actual name or EA of the
            # function, but rather just want to note that a function call was
            # made.
            #
            # Formal signatures already have the call instruction mnemonic,
            # which is more specific than just saying that a call was made.
            if idaapi.is_call_insn(ea):
                for cref in crefs:
                    func_name = ida_shims.get_name(cref)
                    if func_name:
                        functions.append(func_name)
                        fuzzy.append("funcref")
            # If there are data references from the instruction, check to see
            # if any of them are strings. These are looked up in the
            # pre-generated strings dictionary.
            #
            # String values are easily identifiable, and are used as part of
            # both the fuzzy and the formal signatures.
            #
            # It is more difficult to determine if non-string values are
            # constants or not; for both fuzzy and formal signatures, just use
            # "data" to indicate that some data was referenced.
            elif drefs:
                for dref in drefs:
                    if self.strings.has_key(dref):
                        formal.append(self.strings[dref].value)
                        fuzzy.append(self.strings[dref].value)
                    else:
                        formal.append("dataref")
                        fuzzy.append("dataref")
            # If there are no data or code references from the instruction, use
            # every operand as part of the formal signature.
            #
            # Fuzzy signatures are only concerned with interesting immediate
            # values, that is, values that are greater than 65,535, are not
            # memory addresses, and are not displayed as negative values.
            elif not drefs and not crefs:
                ops = ida_shims.get_operands(insn)
                for n in range(0, len(ops)):
                    opnd_text = ida_shims.print_operand(ea, n)
                    formal.append(opnd_text)
                    if ops[n].type == idaapi.o_imm and \
                            not opnd_text.startswith('-'):
                        if ops[n].value >= 0xFFFF:
                            if ida_shims.get_full_flags(ops[n].value) == 0:
                                fuzzy.append(str(ops[n].value))
                                immediates.append(ops[n].value)

            ea = ida_shims.next_head(ea)

        return (self.sighash(''.join(formal)), self.sighash(''.join(fuzzy)),
                immediates, functions)
Ejemplo n.º 14
0
    def _profile_function(self):
        current_ea = ida_shims.get_screen_ea()
        current_function = ida_shims.get_func_name(current_ea)
        current_function_ea = ida_shims.get_name_ea_simple(current_function)

        if current_function:
            self.function = current_function

        ea = ida_shims.get_func_attr(current_function_ea, idc.FUNCATTR_START)
        end_ea = ida_shims.get_func_attr(current_function_ea, idc.FUNCATTR_END)

        self.highlighted = ida_shims.get_highlighted_identifier()

        while ea < end_ea and ea != idc.BADADDR and self.highlighted:
            i = 0
            match = False
            optype = self.READ

            insn = ida_shims.decode_insn(ea)

            mnem = ida_shims.print_insn_mnem(ea)

            if self.highlighted in mnem:
                match = True
            elif idaapi.is_call_insn(ea):
                for xref in idautils.XrefsFrom(ea):
                    if xref.type != 21:
                        name = ida_shims.get_name(xref.to)
                        if name and self.highlighted in name:
                            match = True
                            break
            else:
                while True:
                    opnd = ida_shims.print_operand(ea, i)
                    if opnd:
                        if self.highlighted in opnd:
                            canon_feature = ida_shims.get_canon_feature(insn)
                            match = True
                            if canon_feature & self.OPND_WRITE_FLAGS[i]:
                                optype = self.WRITE
                        i += 1
                    else:
                        break

            if not match:
                comment = idc.GetCommentEx(ea, 0)
                if comment and self.highlighted in comment:
                    match = True
                else:
                    comment = idc.GetCommentEx(ea, 1)
                    if comment and self.highlighted in comment:
                        match = True
                    else:
                        comment = None

            if match:
                if ea > current_ea:
                    direction = self.DOWN
                elif ea < current_ea:
                    direction = self.UP
                else:
                    direction = self.THIS

                self.xrefs[ea] = {
                    'offset': ida_shims.get_func_off_str(ea),
                    'mnem': mnem,
                    'type': optype,
                    'direction': direction,
                    'text': idc.GetDisasm(ea),
                }

            ea = ida_shims.next_head(ea)