def downloadFuncs():
    funcs = list()
    func = FunctionInfo()
    i = 0
    j = 0
    k = 0
    line = ""
    startEA, endEA = 0, 0
    for segEA in idautils.Segments():
        print "[%d] Segment EA : %016x" % (i, segEA)
        i += 1
        j = 0
        for fnEA in idautils.Functions(segEA, SegEnd(segEA)):
            print "[%d] Function EA : %016x" % (j, fnEA)
            j += 1
            fnName = idc.GetFunctionName(fnEA)
            func = FunctionInfo()
            func.m_startAddr = fnEA
            func.m_funcName = fnName
            k = 0
            for (startEA, endEA) in idautils.Chunks(fnEA):
                print "[%d] Chunks" % (k)
                k += 1
                for head in idautils.Heads(startEA, endEA):
                    # s = "%s : %x : %s" % (fnName, head, GetDisasm(head))
                    # print s
                    line = "%016x|%s" % (head, GetDisasm(head))
                    func.m_ins.append(line)
            func.m_endAddr = endEA
            funcs.append(func)
    return funcs
Ejemplo n.º 2
0
    def jumps_to(f, t):
        f_ea = idc.LocByName(f)
        t_ea = idc.LocByName(t)

        for start, end in idautils.Chunks(f_ea):
            ea = start
            while (ea < end):
                i = idautils.DecodeInstruction(ea)

                #Functions have data chunks in them, these are offsets and dwords. skipping 4 ahead seems like a safe choice.
                if type(i) == type(None):
                    ea += 4
                    continue

                #detect if instruction is a jump to t_ea
                m = idc.GetMnem(ea)
                if idc.GetMnem(ea) == "LDR" and idc.GetOpnd(
                        ea, 0) == "PC" and t in idc.GetOpnd(ea, 1):
                    return True
                elif idc.GetMnem(ea) == "BX" and idc.GetOpnd(ea, 0) == t:
                    return True

                try:
                    ea += i.size
                except:
                    print "0x%08x" % ea
                    print "DecodeInstruction failed!"
                    print i.size

        return False
Ejemplo n.º 3
0
def parse_strings():
    strings_added = 0
    retry = []
    text_seg = common.get_text_seg()
    if text_seg is None:
        common._debug('Failed to get text segment')
        return strings_added

    # This may be inherently flawed as it will only search for defined functions
    # and as of IDA Pro 6.95 it fails to autoanalyze many GO functions, currently
    # this works well since we redefine/find (almost) all the functions prior to
    # this being used. Could be worth a strategy rethink later one or on diff archs
    for addr in idautils.Functions(text_seg.startEA, text_seg.endEA):
        name = idc.GetFunctionName(addr)

        end_addr = idautils.Chunks(addr).next()[1]
        if (end_addr < addr):
            common._error('Unable to find good end for the function %s' % name)
            pass

        common._debug('Found function %s starting/ending @ 0x%x 0x%x' %
                      (name, addr, end_addr))

        while addr <= end_addr:
            if parse_str_ptr(addr):
                strings_added += 1
                addr = idc.FindCode(addr, idaapi.SEARCH_DOWN)
            elif is_string_patt(addr):
                if 'rodata' not in idc.get_segm_name(
                        addr) and 'text' not in idc.get_segm_name(addr):
                    common._debug('Should a string be in the %s section?' %
                                  idc.get_segm_name(addr))
                string_addr = idc.GetOperandValue(addr, 1)
                addr_3 = idc.FindCode(idc.FindCode(addr, idaapi.SEARCH_DOWN),
                                      idaapi.SEARCH_DOWN)
                string_len = idc.GetOperandValue(addr_3, 1)
                if string_len > 1:
                    if create_string(string_addr, string_len):
                        if create_offset(addr):
                            strings_added += 1
                    else:
                        # There appears to be something odd that goes on with IDA making some strings, always works
                        # the second time, so lets just force a retry...
                        retry.append((addr, string_addr, string_len))

                # Skip the extra mov lines since we know it won't be a load on any of them
                addr = idc.FindCode(addr_3, idaapi.SEARCH_DOWN)
            else:
                addr = idc.FindCode(addr, idaapi.SEARCH_DOWN)

    for instr_addr, string_addr, string_len in retry:
        if create_string(string_addr, string_len):
            if create_offset(instr_addr):
                strings_added += 1
        else:
            common._error(
                'Unable to make a string @ 0x%x with length of %d for usage in function @ 0x%x'
                % (string_addr, string_len, instr_addr))

    return strings_added
Ejemplo n.º 4
0
def GetDataXrefString(ea):
    name = idc.GetFunctionName(ea)
    ea = idc.LocByName(name)

    f_start = ea
    f_end = idc.GetFunctionAttr(ea, idc.FUNCATTR_END)

    ret = []
    for chunk in idautils.Chunks(ea):
        astart = chunk[0]
        aend = chunk[1]
        for head in idautils.Heads(astart, aend):
            # If the element is an instruction
            if idc.isCode(idc.GetFlags(head)):
                refs = list(idautils.DataRefsFrom(head))
                for ref in refs:
                    s = idc.GetString(ref, -1, idc.ASCSTR_C)
                    if not s or len(s) <= 4:
                        s = idc.GetString(ref, -1, idc.ASCSTR_UNICODE)

                    if s:
                        if len(s) > 4:
                            ret.append(repr(s))

    if len(ret) > 0:
        return "\n\n" + "\n".join(ret)
    else:
        return ""
Ejemplo n.º 5
0
Archivo: ida.py Proyecto: w00kong/sdk
def parse_func(pfn):
    try:
        hf = idaapi.hexrays_failure_t()
        cfunc = idaapi.decompile(pfn.start_ea, hf)
        mbr = idaapi.mba_ranges_t(pfn)
        mba = idaapi.gen_microcode(
            mbr,
            hf,
            None,
            idaapi.DECOMP_NO_WAIT | idaapi.DECOMP_NO_CACHE,
            idaapi.MMAT_GLBOPT3
        )
    except Exception:
        return
    if mba is None:
        return

    G = Graph()
    ctree_state, ctree_expr, ctree_int, ctree_str, micro_int = [], [], [], [], []

    # node level
    for i in range(mba.qty):
        mb = mba.get_mblock(i)
        minsn = mb.head
        blk = []
        while minsn:
            ins = parse_minsn(minsn, micro_int)
            blk.append(ins)
            minsn = minsn.next

        vp = idaapi.qstring_printer_t(None, True)
        mb._print(vp)

        G.add_node(mb.serial, feat=blk, raw_data=vp.s)
        for succ in mb.succset:
            G.add_edge(mb.serial, succ)
    G.remove_featempty_nodes()

    if not G.have_nodes():
        return

    # add a fake edge if there is no edge
    if not G.have_edges():
        G.add_edge(G.graph['nodes'][0]['id'], G.graph['nodes'][0]['id'])

    # graph level
    ctree_fea = CtreeFeature(ctree_state, ctree_expr, ctree_int, ctree_str)
    ctree_fea.apply_to(cfunc.body, None)

    G.graph['graph']['c_state'], G.graph['graph']['c_expr'], G.graph['graph']['c_int'], G.graph['graph'][
        'c_str'], G.graph['graph']['m_int'] = ctree_state, ctree_expr, ctree_int, ctree_str, micro_int
    G.graph['graph']['arg_num'] = len(cfunc.argidx)

    func_bytes = b''
    for start, end in idautils.Chunks(pfn.start_ea):
        fb = idaapi.get_bytes(start, end-start)
        func_bytes += fb
    G.graph['graph']['hash'] = hashlib.md5(func_bytes).hexdigest()

    return G.graph
Ejemplo n.º 6
0
def get_branch_table_instrs():
    """
    Return all jsr or jmp instructions with pc in the operand

    :return: List of PC-relative jmp and jsr dispatch instructions
    """

    instrs = []
    # Iterate instructions in functions
    for funcea in idautils.Functions():
        for (startea, endea) in idautils.Chunks(funcea):
            for head in idautils.Heads(startea, endea):
                instr = idc.GetDisasm(head).split()
                if instr[0] == 'jsr' or instr[0] == 'jmp':
                    if 'pc' in instr[1]:
                        instrs.append(instr)

    # Iterate instructions not in a function
    addr = idaapi.find_not_func(0, 1)
    while addr != idc.BADADDR:
        instr = idc.GetDisasm(addr).split()
        if instr[0] == 'jsr' or instr[0] == 'jmp':
            if 'pc' in instr[1]:
                instrs.append(instr)
        addr = idaapi.find_not_func(addr, 1)

    return instrs
Ejemplo n.º 7
0
def getListOfFunctions():
    res = []
    for segea in idautils.Segments():
        for funcea in idautils.Functions(segea, idc.SegEnd(segea)):
            functionName = idc.GetFunctionName(funcea)
            for (startea, endea) in idautils.Chunks(funcea):
                res.append(Function(functionName, startea, endea))
    return res
Ejemplo n.º 8
0
 def clear_function_instructions(self, address):
     """Clear paint from a function instructions."""
     for start_ea, end_ea in idautils.Chunks(address):
         for ea in idautils.Heads(start_ea, end_ea):
             color = self._get_paint_instruction(ea)
             # Clear it only if it hasn't been colorized by the user
             color = color if color != self._bg_color else self.DEFCOLOR
             self._set_paint_instruction(ea, color)
Ejemplo n.º 9
0
    def init_func_from_ida(self):
        # get current address
        # and get the function address from current address
        current_addr = idc.here()
        self.func_name = idc.GetFunctionName(current_addr)
        for chunk in idautils.Chunks(idc.LocByName(self.func_name)):
            self.func_addr = chunk

            return self.func_name, self.func_addr
Ejemplo n.º 10
0
 def paint_function_instructions(self, address):
     """Paint a function's instructions with the user color."""
     for start_ea, end_ea in idautils.Chunks(address):
         for ea in idautils.Heads(start_ea, end_ea):
             color = self._get_paint_instruction(ea)
             # Only color instructions that aren't colored yet to keep
             # an existing user-defined color
             if color == self.DEFCOLOR:
                 self._set_paint_instruction(ea, self._bg_color)
Ejemplo n.º 11
0
  def calc_file_version_hash():
    version_obj = {}
    version_obj['functions'] = {offset: list(idautils.Chunks(offset))
                                  for offset in idautils.Functions()}
    version_str = repr(version_obj)
    version_hash = hashlib.md5(version_str).hexdigest()

    log('match_action').info("file version string: %s", version_str)
    log('match_action').info("file version hash: %s", version_hash)
    return version_hash
Ejemplo n.º 12
0
    def clear_function_instructions(self, address):
        """
        Clear function instructions

        :param address: an address within the function
        """
        for start_ea, end_ea in idautils.Chunks(address):
            for ea in idautils.Heads(start_ea, end_ea):
                color = self.get_paint_instruction(ea)
                # clear only if it's not colorized by user
                color = color if color != self.bg_color else self.DEFCOLOR
                self.set_paint_instruction(ea, color)
def find_switch(func_ea):
    # get all chunks that belong to a function, because apparently they're not contiguous or some shit
    for (start_ea, end_ea) in idautils.Chunks(func_ea):
        for head in idautils.Heads(start_ea, end_ea):
            switch = idaapi.get_switch_info_ex(head)

            if switch != None:
                log('found switch @ %x, cases: %d' %
                    (head, switch.get_jtable_size()))
                return (head, switch)

    return (None, None)
Ejemplo n.º 14
0
    def paint_function_instructions(self, address):
        """
        Paint function instructions with the user-defined background color

        :param address: an address within the function
        """
        for start_ea, end_ea in idautils.Chunks(address):
            for ea in idautils.Heads(start_ea, end_ea):
                color = self.get_paint_instruction(ea)
                # color only instructions that aren't colored yet to keep
                # user-defined color
                if color == self.DEFCOLOR:
                    self.set_paint_instruction(ea, self.bg_color)
Ejemplo n.º 15
0
def imp_cb(ea, name, ord):
    for xref in XrefsTo(ea, True):
        for func_ea in Functions():
            for (startea, endea) in idautils.Chunks(func_ea):
                if startea < xref.frm < endea:
                    if name:
                        export_tag = {
                            'offset': (func_ea - idaapi.get_imagebase()),
                            'tag': name,
                            'feeder': 'TagApi'
                        }
                        tags.append(export_tag)
    return True
Ejemplo n.º 16
0
def _convert_address_to_function(func):
    """Convert an address that IDA has classified incorrectly into a proper function."""
    # If everything goes wrong, we'll try to restore this function.
    orig = idc.first_func_chunk(func)
    # If the address is not code, let's undefine whatever it is.
    if not ida_bytes.is_code(ida_bytes.get_full_flags(func)):
        if not is_mapped(func):
            # Well, that's awkward.
            return False
        item = ida_bytes.get_item_head(func)
        itemend = ida_bytes.get_item_end(func)
        if item != idc.BADADDR:
            _log(1, 'Undefining item {:#x} - {:#x}', item, itemend)
            ida_bytes.del_items(item, ida_bytes.DELIT_EXPAND)
            idc.create_insn(func)
            # Give IDA a chance to analyze the new code or else we won't be able to create a
            # function.
            #ida_auto.auto_wait()
            autoanalyze()
            idc.plan_and_wait(item, itemend)
    else:
        # Just try removing the chunk from its current function. IDA can add it to another function
        # automatically, so make sure it's removed from all functions by doing it in loop until it
        # fails.
        for i in range(1024):
            if not idc.remove_fchunk(func, func):
                break
    # Now try making a function.
    if ida_funcs.add_func(func) != 0:
        return True
    # This is a stubborn chunk. Try recording the list of chunks, deleting the original function,
    # creating the new function, then re-creating the original function.
    if orig != idc.BADADDR:
        chunks = list(idautils.Chunks(orig))
        if ida_funcs.del_func(orig) != 0:
            # Ok, now let's create the new function, and recreate the original.
            if ida_funcs.add_func(func) != 0:
                if ida_funcs.add_func(orig) != 0:
                    # Ok, so we created the functions! Now, if any of the original chunks are not
                    # contained in a function, we'll abort and undo.
                    if all(idaapi.get_func(start) for start, end in chunks):
                        return True
            # Try to undo the damage.
            for start, _ in chunks:
                ida_funcs.del_func(start)
    # Everything we've tried so far has failed. If there was originally a function, try to restore
    # it.
    if orig != idc.BADADDR:
        _log(0, 'Trying to restore original function {:#x}', orig)
        ida_funcs.add_func(orig)
    return False
Ejemplo n.º 17
0
def is_function_switch_statement(f):
    """ check a function for switch statement indicators

        adapted from:
        https://reverseengineering.stackexchange.com/questions/17548/calc-switch-cases-in-idapython-cant-iterate-over-results?rq=1

        arg:
            f (IDA func_t)
    """
    for (start, end) in idautils.Chunks(f.start_ea):
        for head in idautils.Heads(start, end):
            if idaapi.get_switch_info(head):
                return True
    return False
Ejemplo n.º 18
0
    def calc_file_version_hash():
        version_obj = []
        version_obj.append(
            ('functions', [(offset, list(idautils.Chunks(offset)))
                           for offset in idautils.Functions()]))
        # TODO: This is a  little hackish way of getting the version of all vectors
        # of an instance. cannot make version a classmethod because vector sets are
        # only built by __init__ methods
        version_obj.append(('vectors', FunctionInstance(None, None).version()))

        version_str = repr(version_obj)
        version_hash = hashlib.md5(version_str).hexdigest()

        log('match_action').info("file version string: %s", version_str)
        log('match_action').info("file version hash: %s", version_hash)
        return version_hash
Ejemplo n.º 19
0
def build_a2fmap():
    a2fmap = {}

    print "Generating address to functon map..."
    min_ea = idaapi.cvar.inf.minEA
    max_ea = idaapi.cvar.inf.maxEA
    for fea in idautils.Functions(min_ea, max_ea):
        ida_auto.show_addr(fea)
        for (startea, endea) in idautils.Chunks(fea):
            for addr in range(startea, endea):
                if addr in a2fmap:
                    a2fmap[addr].append(fea)
                else:
                    a2fmap[addr] = [fea]
    print "Address to function map generation complete!"
    return a2fmap
Ejemplo n.º 20
0
def ida_iter_functions():
    for addr in idautils.Functions():
        func = idaapi.get_func(addr)

        blocks = []
        for block in idaapi.FlowChart(func):
            blocks.append(
                BasicBlockTuple(
                    startEA=block.startEA,
                    endEA=block.endEA,
                    FAKE_FIELD_preds=[b.startEA for b in block.preds()],
                    FAKE_FIELD_succs=[b.startEA for b in block.succs()]))

        yield FunctionTuple(startEA=func.startEA,
                            endEA=func.endEA,
                            FAKE_FIELD_chunks=list(idautils.Chunks(addr)),
                            FAKE_FIELD_blocks=blocks)
Ejemplo n.º 21
0
def _convert_address_to_function(func):
    """Convert an address that IDA has classified incorrectly into a proper function."""
    # If everything goes wrong, we'll try to restore this function.
    orig = idc.FirstFuncFchunk(func)
    # If the address is not code, let's undefine whatever it is.
    if not idc.isCode(idc.GetFlags(func)):
        if not is_mapped(func):
            # Well, that's awkward.
            return False
        item = idc.ItemHead(func)
        itemend = idc.ItemEnd(func)
        if item != idc.BADADDR:
            _log(1, 'Undefining item {:#x} - {:#x}', item, itemend)
            idc.MakeUnkn(item, idc.DOUNK_EXPAND)
            idc.MakeCode(func)
            # Give IDA a chance to analyze the new code or else we won't be able to create a
            # function.
            idc.Wait()
            idc.AnalyseArea(item, itemend)
    else:
        # Just try removing the chunk from its current function.
        idc.RemoveFchunk(func, func)
    # Now try making a function.
    if idc.MakeFunction(func) != 0:
        return True
    # This is a stubborn chunk. Try recording the list of chunks, deleting the original function,
    # creating the new function, then re-creating the original function.
    if orig != idc.BADADDR:
        chunks = list(idautils.Chunks(orig))
        if idc.DelFunction(orig) != 0:
            # Ok, now let's create the new function, and recreate the original.
            if idc.MakeFunction(func) != 0:
                if idc.MakeFunction(orig) != 0:
                    # Ok, so we created the functions! Now, if any of the original chunks are not
                    # contained in a function, we'll abort and undo.
                    if all(idaapi.get_func(start) for start, end in chunks):
                        return True
            # Try to undo the damage.
            for start, _ in chunks:
                idc.DelFunction(start)
    # Everything we've tried so far has failed. If there was originally a function, try to restore
    # it.
    if orig != idc.BADADDR:
        _log(0, 'Trying to restore original function {:#x}', orig)
        idc.MakeFunction(orig)
    return False
Ejemplo n.º 22
0
def __patch_indirect_call_instructions():
    for seg in idautils.Segments():
        for func in idautils.Functions(seg):
            function_name = idc.get_func_name(func)
            print('[+] Checking function "{}"'.format(function_name))
            for (startea, endea) in idautils.Chunks(func):
                for head in idautils.Heads(startea, endea):
                    m = idc.print_insn_mnem(head)
                    if m == 'call':
                        op = idc.get_operand_type(head, 0)
                        if op == idc.o_displ:
                            print('{}: 0x{:08x}: {}'.format(
                                function_name, head,
                                idc.generate_disasm_line(head, 0)))
                            ida_bytes.patch_word(head, 0x15ff)
                            print('{}: 0x{:08x}: {}'.format(
                                function_name, head,
                                idc.generate_disasm_line(head, 0)))
Ejemplo n.º 23
0
    def paint_function_instructions(self, address):
        """
        Paint function instructions with the user-defined background color

        :param address: an address within the function
        """
        for start_ea, end_ea in idautils.Chunks(address):
            for ea in idautils.Heads(start_ea, end_ea):
                color = self.get_paint_instruction(ea)
                # color only instructions that aren't colored yet to keep
                # user-defined color
                if color == self.DEFCOLOR:
                    self.set_paint_instruction(ea, self.bg_color)
                else:
                    #
                    # TODO: IDA doesn't provide a way to hook painting, with
                    # this we can propagate user-defined colors between users.
                    #
                    pass
Ejemplo n.º 24
0
    def calc_file_version_hash():
        version_obj = []
        version_obj.append(
            ('functions', [(offset, list(idautils.Chunks(offset)))
                           for offset in idautils.Functions()]))
        # TODO: This is a little hackish way of getting the version of all vectors
        # of an instance. cannot make version a classmethod because vector sets are
        # only built by __init__ methods
        func_vector_versions = FunctionInstance(None, None).version()
        version_obj.append(('function_vector_versions', func_vector_versions))
        # TODO: Add function annotations as part of the version, because they're
        # also changing.
        # TODO: Add universal instance related versions

        version_str = repr(version_obj)
        version_hash = hashlib.md5(version_str).hexdigest()

        log('upload_action').info("file version string: %s", version_str)
        log('upload_action').info("file version hash: %s", version_hash)
        return version_hash
Ejemplo n.º 25
0
def generate_data_from_offset(
        offset):  # credits to ferhat, or whoever wrote this
    found_values = {}
    chunks = idautils.Chunks(offset)

    for begin, end in chunks:
        name = ""
        offset = -1
        ea = begin

        while ea != end:
            mnem = idc.GetMnem(ea)
            opnd = idc.GetOpnd(ea, 0)
            stack_value = idc.GetOperandValue(ea, 0)

            if mnem == "jz" or mnem == "jl":
                name = ""
                offset = -1

            if offset == -1 and (mnem == "add" or mnem == "lea"
                                 or mnem == "sub"):
                offset = idc.GetOperandValue(ea, 1)
                if mnem == "sub":
                    offset = 0x100000000 - offset

            if mnem == "push" and "offset" in opnd and "pNodeName" not in opnd:
                name = idc.GetString(stack_value, -1, idc.ASCSTR_C)

            if is_user_name(stack_value):  # this should crash? wtf
                name = idc.NameEx(idc.BADADDR, stack_value)

            if mnem == "call" or mnem == "jmp":
                #print("{} at {}").format(name, dec_to_hex(offset))
                if name:
                    found_values[offset] = name
                    name = ""
                offset = -1

            ea = idc.NextNotTail(ea)

    return found_values
Ejemplo n.º 26
0
def get_upload_func_info(ea):
    """
    get function upload info by IDA Pro

    Args:
        ea(ea_t): function address

    Returns:
        func_info(dict): function info
    """
    func_info = {}
    try:
        hf = idaapi.hexrays_failure_t()
        if idaapi.IDA_SDK_VERSION >= 730:
            cfunc = idaapi.decompile(ea, hf, idaapi.DECOMP_NO_WAIT)
        else:
            cfunc = idaapi.decompile(ea, hf)
        func_info['feature'] = str(cfunc)
        func_info['pseudo_code'] = str(cfunc)
    except Exception as e:
        print(str(e))
        return None

    func_info['binary_file'] = idaapi.get_root_filename()
    binary_sha256 = idaapi.retrieve_input_file_sha256()
    binary_sha256 = binary_sha256.hex() if isinstance(binary_sha256,
                                                      bytes) else binary_sha256
    func_info['binary_sha256'] = binary_sha256
    func_info['binary_offset'] = idaapi.get_fileregion_offset(ea)
    func_info['platform'] = get_platform_info()
    func_info['name'] = idaapi.get_func_name(ea)

    func_bytes = b''
    for start, end in idautils.Chunks(idaapi.get_func(ea).start_ea):
        fb = idaapi.get_bytes(start, end - start)
        func_bytes += fb
    func_bytes = func_bytes.hex() if isinstance(func_bytes,
                                                bytes) else func_bytes
    func_info['func_bytes'] = func_bytes

    return func_info
Ejemplo n.º 27
0
def GetCodeRefsFrom(ea):
    name = idc.GetFunctionName(ea)
    ea = idc.LocByName(name)

    f_start = ea
    f_end = idc.GetFunctionAttr(ea, idc.FUNCATTR_END)

    ret = []
    for chunk in idautils.Chunks(ea):
        astart = chunk[0]
        aend = chunk[1]
        for head in idautils.Heads(astart, aend):
            # If the element is an instruction
            if idc.isCode(idc.GetFlags(head)):
                refs = idautils.CodeRefsFrom(head, 0)
                for ref in refs:
                    loc = idc.LocByName(idc.GetFunctionName(ref))
                    if loc not in ret and loc != f_start:
                        ret.append(ref)

    return ret
Ejemplo n.º 28
0
 def countChunks(self):
     return len(list(idautils.Chunks(self.addr)))
Ejemplo n.º 29
0
def def_functions(s_start):

    num_added_functions = 0

    s_addr = s_start
    s_end = idc.GetSegmentAttr(s_start, SEGATTR_END)  #idc.SegEnd(segm)
    print "0x%08x 0x%08x" % (s_start, s_end)

    while (s_addr < s_end):

        print "Testing address 0x%08x" % s_addr

        #optimization assumes that function chunks are consecutive (no "function-in-function" monkey business)
        if (idaapi.get_func(s_addr)):

            next_func = idc.NextFunction(s_addr)

            ea = s_addr
            for c in idautils.Chunks(s_addr):
                #only use chunks in lookahead that do not jump over the next function and that are not smaller than where we are atm.
                if (c[1] > ea) and (c[1] <= next_func):
                    ea = c[1]
            if ea == s_addr:
                s_addr += 2
            else:
                s_addr = ea
            #s_addr += 4
            continue

        else:
            #This is not a good optimization, there WILL be data refs to function start addresses sometimes.
            '''
            if sum(1 for _ in (CodeRefsTo(s_addr, 1))) != 0:
                s_addr += 4
                continue
            '''
            #also add STMFD
            if ((idc.GetMnem(s_addr) == "STM") and
                ("SP!" in idc.GetOpnd(s_addr, 0)) and
                ("LR" in idc.GetOpnd(s_addr, 1))) or (
                    ((idc.GetMnem(s_addr) == "PUSH") or
                     (idc.GetMnem(s_addr) == "PUSH.W") or
                     (idc.GetMnem(s_addr) == "STR.W")) and
                    ("LR" in idc.GetOpnd(s_addr, 0))):
                print "Found function at 0x%08x" % s_addr
                idc.MakeFunction(s_addr)
                f = idaapi.get_func(s_addr)
                if (type(f) == type(None)):
                    print "Failed to create function! Undefined instructions?"
                    s_addr += 2
                else:
                    num_added_functions += 1
                    ea = -1
                    for c in idautils.Chunks(s_addr):
                        if c[1] > ea:
                            ea = c[1]
                    if ea != -1:
                        s_addr = ea
                    #failed?
                    else:
                        s_addr += 2
            else:
                s_addr += 2

    print "finished segment"
    return num_added_functions
Ejemplo n.º 30
0
 def Chunks(self, start):
     """Returns list of Chunks in the Function that starts at start"""
     return idautils.Chunks(start)