def getNamedFunc(name):
    func = sark.Function(name=name)
    if func:
        # if func just jump to another, return jump target.
        for line in func.lines:
            for xref in line.xrefs_from:
                func = sark.Function(xref.to)
                break
            break
    return func
Exemple #2
0
def build_exports_cfg(bb_list):
    base = idaapi.get_imagebase()

    _first_ = bb_list[0].start + base
    fn = sark.Function(_first_)
    opti_bb_list = [(_first_, demangle_name(fn.name))]
    for bb in bb_list:
        va = bb.start + base
        try:
            fn = sark.Function(va)
            fn_name = demangle_name(fn.name)
            if fn_name != opti_bb_list[-1][1]:
                opti_bb_list.append((va, demangle_name(fn.name)))
        except:
            opti_bb_list.append((va, "_unknown_"))

    exported_apis = get_dll_export_entries().values()

    # start cfg building
    root = cfg_fn_node(0)
    cur_node = root

    i = 0
    for entry in opti_bb_list:
        va, name = entry
        if cur_node.have_call_to(va):
            cur_node = cfg_fn_node(va, name, cur_node)
        else:
            # two_options? call to this 'va' in parent or it is a indirect call we don't have caller info,
            check_node = cur_node
            while check_node != root:
                check_node = check_node.parent
                if check_node.have_call_to(va):
                    cur_node = cfg_fn_node(va, name, check_node)
                    break
                elif check_node.name == name:
                    cur_node = check_node
                    break

            if check_node == root:
                if name in exported_apis:
                    cur_node = cfg_fn_node(va, name, root)
                else:
                    print "[*] indirect call unlinked %d %08x %s %s" % (
                        i, va, name, cur_node.name)

        i += 1

    return root
def get_control_flow_graph(imagebase, bb_collection_gen, verbose=False):
    exported_apis_addresses = get_dll_export_entries().keys()
    root = fn_node()
    cur_fn = root
    last_bb, last_size = 0, 0
    for bb in bb_collection_gen:
        va = bb.start + imagebase
        fn = sark.Function(va)

        if fn.startEA == va:
            note = ""
            last_asm_code = last_bb > 0 and sark.Line(
                last_bb + last_size - 1).disasm or "call _external_"
            if "ret" in last_asm_code:
                if cur_fn.is_bb_part_of_fn(va):
                    cur_fn.add_bb(va)
                    continue
                while cur_fn.parent and not cur_fn.has_call_to(va):
                    cur_fn = cur_fn.parent
                if cur_fn == root:
                    if not (va in exported_apis_addresses):
                        note = "[_unlinked_] "
            cur_fn = fn_node(fn, cur_fn)
            cur_fn.note = note
        else:
            if cur_fn.is_bb_part_of_fn(va):
                cur_fn.add_bb(va)
            else:
                while cur_fn.parent and not cur_fn.is_bb_part_of_fn(va):
                    cur_fn = cur_fn.parent
                cur_fn.add_bb(va)

        last_bb, last_size = va, bb.size
    return root
    def record(self, line):
        """Record the given code / data line.

        Args:
            line (line): (sark) code line
        """
        is_illegal = not self._analyzer.isLegalInsn(line)
        self._unknown_count += line.size if line.is_unknown else 0
        self._illegal_count += line.size if is_illegal else 0
        # don't count functions that contain illegal instructions
        if (not is_illegal) and (not line.is_unknown):
            try:
                self._current_function = sark.Function(line.startEA)
                if line.startEA == self._current_function.startEA:
                    self._seen_function_start = line.startEA
                # Time to check if this is a contained function.
                # Note: could be one liner functions, so use "if" and not "elif"
                if line.endEA == self._current_function.endEA and self._current_function.startEA == self._seen_function_start:
                    self._contains_functions = True
            except Exception:
                self._current_function = None
        else:
            self._current_function = None
        # now check for an alignment
        if self._measure_align:
            if self._analyzer.isAlignment(line):
                self._align_start = True
            elif self._align_start:
                self._align_metric = CodeMetric(self._analyzer, line.startEA)
                self._align_metric.start(line)
                self._align_start = False
            elif self._align_metric is not None:
                self._align_metric.record(line)
Exemple #5
0
def show_current_function_meaningful():
    try:
        function = sark.Function(idc.here())
        show_meaningful_in_function(function)

    except sark.exceptions.SarkNoFunction:
        idaapi.msg("[FunctionStrings] No function at 0x{:08X}.\n".format(idc.here()))
Exemple #6
0
def fix_noret_func(func=None):
    """Fix function that was created as noret func"""
    if not func:
        func = sark.Function()
    if func.is_noret:
        new_flags = func.flags ^ idaapi.FUNC_NORET
        idc.set_func_flags(func.ea, new_flags)
Exemple #7
0
def run():
    try:
        current_function = sark.Function()
    except sark.exceptions.SarkNoFunction:
        log("Cannot xref registers outside of functions.")
        return

    #register_name = idaapi.get_highlighted_identifier()
    
    # TypeError: in method 'get_highlight', argument 1 of type 'TWidget *'
    register_name = idaapi.get_highlighted_identifier(idaapi.get_current_tform()) # ida7.0 must give TWidget*

    try:
        register_id = get_register_identifier(register_name)
    except sark.exceptions.SarkInvalidRegisterName:
        log("Highlight a register to xref")
        return

    choose = RegisterReferencesView(current_function.name, register_name)

    for line in current_function.lines:
        if has_register_reference(line.insn, register_id):
            choose.add_xref(line.ea)

    choose.show()
 def is_bb_part_of_fn(self, bb_va):
     if self.fn:
         if bb_va >= self.fn.startEA and bb_va <= self.fn.endEA:
             return True
         va_fn = sark.Function(bb_va)
         if va_fn.startEA == self.fn.startEA:
             return True
Exemple #9
0
def _get_best_name(ea):
    try:
        return sark.Function(ea).demangled
    except exceptions.SarkNoFunction:
        name = idc.GetTrueName(ea)
        if name:
            return name
        return '0x{:X}'.format(ea)
Exemple #10
0
def is_import_or_lib_func(ea):
    """
    Is ea part of an imported function or a known library?
    @param ea: any ea within the function scope
    @return: True if function is either imported or a known library function.
    """

    return sark.Function(ea).flags & (idaapi.FUNC_LIB | idaapi.FUNC_THUNK)
Exemple #11
0
def hint_function(ea):
    try:
        function = sark.Function(ea)
    except sark.exceptions.SarkNoFunction:
        return
    base_name = get_base_name(function)
    function.lines.next().comments.posterior = 'Base name: {}'.format(
        base_name)
Exemple #12
0
    def run(self):
        # All the colors that signify unreachable blocks
        unreachable_cols = [
            col_t2ida(self.plugin.col_unreachable),
            col_t2ida(self.plugin.col_invariant),
            col_t2ida(self.plugin.col_contextual)
        ]

        # helper lambdas
        cb_in_list = lambda cb, l: any(cb.startEA == x.startEA for x in l)
        not_colored_unreach = lambda cb: not cb.color or cb.color not in unreachable_cols

        # Get the current function in IDA
        f = sark.Function()

        # Find all yellow, cyan and purple blocks (i.e. already determined unreachable)
        unreachable_blocks = get_all_blocks_of_color(f, unreachable_cols)

        # Start with all white successors of the initial blocks
        possibly_unreachable = []
        for cb in unreachable_blocks:
            for succ in filter(
                    not_colored_unreach,
                    filter(lambda succ: succ.startEA > cb.startEA,
                           cb.succs())):
                possibly_unreachable.append(succ)

        while len(possibly_unreachable) > 0:
            # Pop one from the queue of possibly unreachable blocks
            cb = possibly_unreachable.pop()

            if not not_colored_unreach(cb):
                continue

            # If all our predecessors are unreachable, we're unreachable
            preds_no_backedges = filter(lambda pred: pred.startEA < cb.startEA,
                                        cb.preds())
            if all(
                    cb_in_list(pred, unreachable_blocks)
                    for pred in preds_no_backedges):
                self.log_signal.emit(
                    "all preds unreachable, changing color of {:x}\n".format(
                        cb.startEA))
                #cb.color = 0xFF00FF
                unreachable_blocks.append(cb)
                # Continue looking at our successors
                for succ in filter(
                        not_colored_unreach,
                        filter(lambda succ: succ.startEA > cb.startEA,
                               cb.succs())):
                    possibly_unreachable.append(succ)

        # Return results to GUI thread
        unreachable_addrs = map(lambda b: b.startEA, unreachable_blocks)
        self.log_signal.emit(
            "Unreachable blocks: {}".format(unreachable_addrs))
        self.result_signal.emit(unreachable_addrs)
def main():
    main_function = sark.Function(name='main')

    print(main_function.comments)
    dump_attrs(main_function.comments)

    for line in main_function.lines:
        print(line.comments)
        dump_attrs(line.comments)
Exemple #14
0
    def analyzeFunctionBlock(self, block_ea):
        """Return pairs indicating function calls (or fptr refs) from the lines in the basic block instance.

        Args:
            block_ea (int): basic block ea

        Return Value:
            (ordered) list of tuples: [<address of function ref (src), referenced address of the function (dest)>, ]
        """
        function_calls = []
        try:
            func_start = sark.Function(block_ea).start_ea
            block_lines = sark.CodeBlock(block_ea).lines
        except Exception:
            return function_calls
        # scan each of the lines
        for line in block_lines:
            instr_pos = line.ea
            call_candidates = set()
            # Data Refs (strings, fptrs)
            for ref in line.drefs_from:
                # Check for a string (finds un-analyzed strings too)
                str_const = self.disas.stringAt(ref)
                if str_const is not None and len(str_const) >= MIN_STR_SIZE:
                    continue
                # Check for an fptr
                try:
                    call_candidates.add(sark.Function(ref).start_ea)
                except sark.exceptions.SarkNoFunction:
                    continue
            # Check for a function call
            for cref in line.crefs_from:
                try:
                    if (cref == func_start and line.insn.is_call
                        ) or sark.Function(cref).start_ea != func_start:
                        call_candidates.add(sark.Function(cref).start_ea)
                except sark.exceptions.SarkNoFunction:
                    continue
            # handle each ref
            for ref in call_candidates:
                # record the call
                function_calls.append((instr_pos, sark.Function(ref).start_ea))
        # return the result
        return function_calls
def findMetadataCacheInitialize():
    def checkTarget(func):
        #check write to global values' count.
        hitcount = 0
        for xref in func.xrefs_from:
            segment = idaapi.getseg(xref.to)
            if idaapi.get_visible_segm_name(segment) == '.bss' and repr(
                    xref.type) == "Data_Write":
                hitcount += 1
        if hitcount >= 8 and hitcount < 12:
            return 1
        return 0

    # find addr of "global-metadata.dat"
    global_metadata = None
    s = idaapi.string_info_t()
    for i in range(0, idaapi.get_strlist_qty()):
        idaapi.get_strlist_item(s, i)
        if idaapi.get_ascii_contents(s.ea, s.length,
                                     s.type) == "global-metadata.dat":
            global_metadata = s.ea
            break

    # xref of "global-metadata.dat"
    for xref in sark.Line(global_metadata).xrefs_to:
        if sark.Function.is_function(xref.frm):
            target_func = sark.Function(xref.frm)
            if checkTarget(target_func):
                # print "find MetadataCache::Initialize at", hex(int(target_func.startEA))
                idc.set_name(target_func.startEA, "MetadataCache_Initialize",
                             SN_NOWARN | SN_NOCHECK)
                return
            else:
                for txref in target_func.xrefs_to:
                    if sark.Function.is_function(txref.frm):
                        caller = sark.Function(txref.frm)
                        if checkTarget(caller):
                            # print "find MetadataCache::Initialize at", hex(int(caller.startEA))
                            idc.set_name(caller.startEA,
                                         "MetadataCache_Initialize",
                                         SN_NOWARN | SN_NOCHECK)
                            return
    print "can't find MetadataCache_Initialize"
Exemple #16
0
def _get_call_ea(ea):
    func_eas = []
    for xref in sark.Line(ea).xrefs_from:
        #if it is not a code xref, skip
        if xref.iscode == False:
            continue
        #if we reference somewhere outside the func - it is a call
        if sark.Function(xref.to).start_ea != sark.Function(ea).start_ea:
            func_eas += [xref.to]

    num_refs = len(func_eas)
    if num_refs == 0:
        return None
    elif num_refs == 1:
        return func_eas[0]
    else:
        # weird - expected only one xref outside the func.
        print "Err: < %x > Found more than one reference outside the func. Isn't supposed to happen." % ea
        return None
Exemple #17
0
    def __init__(self, ea, iatEA=None, library_name=None):
        """
        Ctor
        """
        self.logger = logging.getLogger(__name__)

        self.ea = ea  # Effective Address of the function
        self.iatEA = iatEA  # If imported function, the address in the IAT

        try:
            function = sark.Function(ea)
        except sark.exceptions.SarkNoFunction:
            raise DIE.Lib.DIE_Exceptions.DieNoFunction(
                "No Function at 0x%08X" % (ea, ))

        self.funcName = get_function_name(function.ea)
        self.func_start = function.startEA
        self.func_end = function.endEA

        self.proto_ea = self.getFuncProtoAdr()  # Address of function prototype
        self.typeInfo = idaapi.tinfo_t()  # Function type info
        self.funcInfo = idaapi.func_type_data_t()  # Function info
        self.argNum = 0  # Number of input arguments

        self.args = []  # Function argument list
        self.retArg = None  # Return argument

        self.library_name = library_name  # If library function, name of containing library
        self.isLibFunc = False
        if self.iatEA:
            self.isLibFunc = True  # Is this a library function

        elif sark.Function(ea).flags & (idaapi.FUNC_LIB | idaapi.FUNC_THUNK):
            self.isLibFunc = True

        try:
            self.getArguments()

        except Exception as ex:
            self.logger.error(
                "Failed to get function arguments for function %s: %s",
                self.funcName, ex)
def highlight_calls_in_function(ea):
    highlighted_lines = set()
    for line in sark.Function(ea).lines:
        if not line.insn.is_call:
            continue

        # Refrain from painting over someone else...
        if line.color is None:
            line.color = HIGHLIGHT_COLOR
            highlighted_lines.add(line.ea)
    return highlighted_lines
Exemple #19
0
def does_fn_have_call_to(src_va, dst_va):
    fn = None
    if src_va in sark_fn_cache:
        fn = sark_fn_cache[src_va]
    else:
        fn = sark.Function(src_va)
        sark_fn_cache[src_va] = fn
    for xref in fn.xrefs_from:
        if xref.to == dst_va:
            return True
    return False
Exemple #20
0
def _get_min_block_ranges(rgs, reg):
    if len(rgs) == 0:
        return rgs

    debug('Ranges before:')
    for s, e in rgs:
        debug('\t%x:%x' % (s, e))

    rgs_d = {}
    rgs_new = []
    rgs_new2 = []
    #assumption - rgs is sorted
    s_first_blk, _ = rgs[0]
    func_start = sark.Function(s_first_blk).start_ea

    #if range between ranges (or between function start and first range) doesn't contain the reg - add it as range
    curr_s = func_start
    for s_blk, e_blk in rgs:
        dontextend = False
        for l in sark.lines(curr_s, s_blk):
            if (oregami_gen.proc_ops.is_load(l.ea, reg)
                    or oregami_gen.proc_ops.is_store(l.ea, reg)
                ):  #reg was used in line - range cannot include this
                dontextend = True
                break

        if not dontextend:
            rgs_new += [(curr_s, s_blk)]

        rgs_new += [(s_blk, e_blk)]
        curr_s = e_blk

    #if ranges are right after each other - make them one range
    while len(rgs_new) > 0:
        #print rgs_new
        s_blk, e_blk = rgs_new[0]
        rgs_new = rgs_new[1:]

        #while next ranges are consecutive, eat them up
        while len(rgs_new) > 0:
            s_blk2, e_blk2 = rgs_new[0]
            if e_blk != s_blk2:
                break

            e_blk = e_blk2
            rgs_new = rgs_new[1:]

        rgs_new2 += [(s_blk, e_blk)]

    debug('Ranges after:')
    for s, e in rgs_new2:
        debug('\t%x:%x' % (s, e))

    return rgs_new2
Exemple #21
0
    def btn_branch_opaque_clicked(self):
        self.btn_branch_opaque.setEnabled(False)
        
        # Only have it look at the currently selected code-block
        addr_trace = [get_current_codeblock().startEA]

        f = IDAFunctionCodeBlocks(sark.Function())
        self.spawn_worker_thread(
            OpaquePredicateFinder(self.plugin, f, addr_trace, self.checkbox_all_symbolic.isChecked()),
            result_signal=self.opaque_results
        )
Exemple #22
0
def show_highlighted_function_strings():
    identifier = idaapi.get_highlighted_identifier()
    if not identifier:
        return

    try:
        function = sark.Function(name=identifier)
        show_function_strings(function)

    except sark.exceptions.SarkNoFunction:
        idaapi.msg("[FunctionStrings] {!r} is not a function.\n".format(identifier))
Exemple #23
0
    def searchIslands(self, func_ea, range_start, range_end):
        """Search a given function for "Islands" from a specific code range.

        Args:
            func_ea (int): effective address of the wanted function
            range_start (int): effective address of the start of the island range
            range_end (int): effective address of the end of the island range

        Return Value:
            Ordered list of code blocks for the found island, or None if found nothing
        """
        island_guess = None
        func = sark.Function(func_ea)
        flow = idaapi.FlowChart(func.func_t)
        for block in flow:
            if range_start <= block.start_ea and block.end_ea <= range_end:
                if island_guess is None or block.start_ea < island_guess.start_ea:
                    island_guess = block
        # quit if found nothing
        if island_guess is None:
            return None
        # make sure that the island is indeed an island, and not a well known function
        if sark.Function(
                island_guess.start_ea).start_ea == island_guess.start_ea:
            return None
        # find the contained flow, that island_guess is the start of
        island_blocks = []
        candidate_list = [island_guess]
        while len(candidate_list) != 0:
            new_candidate_list = []
            for candidate_block in candidate_list:
                if candidate_block in island_blocks:
                    continue
                island_blocks.append(candidate_block)
                new_candidate_list += [
                    s for s in candidate_block.succs()
                    if range_start <= s.start_ea and s.end_ea <= range_end
                ]
            candidate_list = new_candidate_list
        # return the results
        return island_blocks
    def start(self, line):
        """Start the measurement for the code region.

        Args:
            line (line): (sark) code line
        """
        try:
            self._starting_function = sark.Function(line.startEA)
        except Exception:
            self._starting_function = None
        # now record this line
        self.record(line)
Exemple #25
0
    def isFuncStart(self, ea):
        """Check if the given effective address is the start of a known function.

        Args:
            ea (int): effective address to be checked

        Return Value:
            True iff the given address is the start of a known function
        """
        try:
            return ea == sark.Function(ea).start_ea
        except sark.exceptions.SarkNoFunction:
            return False
def findGetTypeInfoFromTypeIndex():
    global GetTypeInfoFromTypeIndex
    finit = getNamedFunc("MetadataCache_Initialize")
    for xref in sark.Line(s_TypeInfoTable).xrefs_to:
        if sark.Function.is_function(xref.frm):
            func = sark.Function(xref.frm)
            if func.startEA == finit.startEA:
                continue
            # print "find findGetTypeInfoFromTypeIndex at", hex(int(func.startEA))
            idc.set_name(func.startEA, "GetTypeInfoFromTypeIndex",
                         SN_NOWARN | SN_NOCHECK)
            GetTypeInfoFromTypeIndex = int(func.startEA)
            return
Exemple #27
0
    def btn_opaque_clicked(self):
        self.btn_opaque.setEnabled(False)

        # Retrieve the addr_trace from colored code-blocks
        f = IDAFunctionCodeBlocks(sark.Function())
        cbs = get_all_blocks_of_color(f, col_t2ida(self.plugin.col_visited))
        addr_trace = [cb.startEA for cb in cbs]

        # Spawn the worker thread
        self.spawn_worker_thread(
            OpaquePredicateFinder(self.plugin, f, addr_trace, self.checkbox_all_symbolic.isChecked()),
            result_signal=self.opaque_results
        )
Exemple #28
0
    def _make_function_ea_item(self, function_context):
        """
        Build a tree item for a function_ea node (level-1)
        @param function_context: a dbFunction_Context object
        @return: QStandradItemModel item for the function context
        """
        calling_function_start = None
        with ignored(sark.exceptions.SarkNoFunction):
            calling_function_start = sark.Function(
                function_context.calling_ea).startEA

        if calling_function_start is not None:
            call_offset = function_context.calling_ea - calling_function_start
            func_ea_txt = "%s+%s" % (function_context.calling_func_name,
                                     hex(call_offset))
        else:
            func_ea_txt = "[%s]:%s" % (function_context.calling_func_name,
                                       hex(function_context.calling_ea))

        item_func_context_ea = QtGui.QStandardItem(func_ea_txt)
        item_func_context_ea.setEditable(False)
        item_func_context_ea.setData(hex(function_context.calling_ea),
                                     role=QtCore.Qt.ToolTipRole)
        item_func_context_ea.setData(function_context,
                                     role=DIE.UI.FunctionContext_Role)
        item_func_context_ea.setData(
            id(function_context),
            role=DIE.UI.ContextId_Role)  # Used for module look-ups

        item_func_is_indirect = QtGui.QStandardItem()
        item_func_is_indirect.setEditable(False)
        if function_context.is_indirect:
            item_func_is_indirect.setIcon(self.die_icons.icon_v)

        item_func_is_new = QtGui.QStandardItem()
        item_func_is_new.setEditable(False)
        if function_context.is_new_func:
            item_func_is_new.setIcon(self.die_icons.icon_v)

        item_list = [
            item_func_context_ea,
            QtGui.QStandardItem(), item_func_is_indirect, item_func_is_new,
            QtGui.QStandardItem(),
            QtGui.QStandardItem(),
            QtGui.QStandardItem(),
            QtGui.QStandardItem(),
            QtGui.QStandardItem(),
            QtGui.QStandardItem()
        ]

        return item_list
Exemple #29
0
def sort_by_xrefs(functions):
    """
    Sort by the number of Xrefs to the fucntion
    @param functions: List of db_DataTypes.dbFunction objects
    @return: a sorted list of db_DataTypes.dbFunction objects by Xref count.
    """
    xref_counts = []
    for f in functions:
        try:
            xref_counts.append((f, (len(list(sark.Function(ea=f.function_start).xrefs_to)))))
        except sark.exceptions.SarkNoFunction:
            pass
    sorted_funcs = sorted(xref_counts, key=lambda x: x[1], reverse=True)
    return [count[0] for count in sorted_funcs]
Exemple #30
0
    def isFuncEnd(self, ea):
        """Check if the given effective address is the end of a known function.

        Args:
            ea (int): effective address to be checked

        Return Value:
            True iff the given address is the end of a known function
        """
        prev_line = sark.Line(ea).prev
        try:
            return ea == sark.Function(prev_line.start_ea).end_ea
        except sark.exceptions.SarkNoFunction:
            return False