예제 #1
0
def main():
    # Get current ea
    ea = ida_kernwin.get_screen_ea()

    # Get segment class
    seg = ida_segment.getseg(ea)

    # Loop from segment start to end
    func_ea = seg.start_ea

    # Get a function at the start of the segment (if any)
    func = ida_funcs.get_func(func_ea)
    if func is None:
        # No function there, try to get the next one
        func = ida_funcs.get_next_func(func_ea)

    seg_end = seg.end_ea
    while func is not None and func.start_ea < seg_end:
        funcea = func.start_ea
        print("Function %s at 0x%x" %
              (ida_funcs.get_func_name(funcea), funcea))

        ref = ida_xref.get_first_cref_to(funcea)

        while ref != ida_idaapi.BADADDR:
            print("  called from %s(0x%x)" %
                  (ida_funcs.get_func_name(ref), ref))
            ref = ida_xref.get_next_cref_to(funcea, ref)

        func = ida_funcs.get_next_func(funcea)
예제 #2
0
def getFuncRanges():
    funcs_addr = []
    start = 0
    next_func = ida_funcs.get_next_func(start)
    while next_func:
        size = next_func.size()
        if (size) < MIN_FUNC_SIZE:
            next_func = ida_funcs.get_next_func(next_func.start_ea)
            continue
        elif size > MAX_FUNC_SIZE:
            size = MAX_FUNC_SIZE
        yield (next_func.start_ea, size)
        funcs_addr.append(next_func.start_ea - start)
        next_func = ida_funcs.get_next_func(next_func.start_ea)
예제 #3
0
def RenameMod(orig, new):
    i = ida_funcs.get_next_func(0)
    while (i != ida_idaapi.BADADDR):
        n = ida_funcs.get_func_name(i)
        if n.startswith(orig+"_"):
            RenameFuncWithNewMod(i,new)
        i = NextFunction(i)
예제 #4
0
파일: idautils.py 프로젝트: zhangji1810/src
def Functions(start=None, end=None):
    """
    Get a list of functions

    @param start: start address (default: inf.min_ea)
    @param end:   end address (default: inf.max_ea)

    @return: list of heads between start and end

    @note: The last function that starts before 'end' is included even
    if it extends beyond 'end'. Any function that has its chunks scattered
    in multiple segments will be reported multiple times, once in each segment
    as they are listed.
    """
    if not start: start = ida_ida.cvar.inf.min_ea
    if not end:   end = ida_ida.cvar.inf.max_ea

    # find first function head chunk in the range
    chunk = ida_funcs.get_fchunk(start)
    if not chunk:
        chunk = ida_funcs.get_next_fchunk(start)
    while chunk and chunk.start_ea < end and (chunk.flags & ida_funcs.FUNC_TAIL) != 0:
        chunk = ida_funcs.get_next_fchunk(chunk.start_ea)
    func = chunk

    while func and func.start_ea < end:
        startea = func.start_ea
        yield startea
        func = ida_funcs.get_next_func(startea)
예제 #5
0
def _get_function_bounds(func, seg_ref):
    """Get the bounds of the function containing `ea`. We want to discover jump
  table targets that are missed by IDA, and it's possible that they aren't
  marked as being part of the current function, and perhaps are after the
  assumed range of the current function. Ideally they will fall before the
  beginning of the next function, though.

  We need to be pretty careful with the case that one function tail-calls
  another. IDA will sometimes treat the end of the tail-called function
  (e.g. a thunk) as if it is the end of the caller. For this reason, we start
  with loose bounds using the prev/next functions, then try to narrow with
  the bounds of the function containing `ea`.

  NOTE(pag): This does not handle function chunks.
  """
    ea = func.start_ea
    seg = _find_segment_containing_ea(ea, seg_ref)
    if not seg:
        return ea, ea

    seg_start, seg_end = seg.start_ea, seg.end_ea
    min_ea = seg_start
    max_ea = seg_end

    if not _is_executable_seg(seg):
        return ea, ea

    # Get an upper bound using the next function.
    has_upper = False
    next_func = ida_funcs.get_next_func(ea)
    if next_func:
        next_func_seg = _find_segment_containing_ea(next_func.start_ea,
                                                    seg_ref)
        if next_func_seg and _is_executable_seg(next_func_seg):
            max_ea = min(next_func.start_ea, max_ea)
            has_upper = True

    # Get a lower bound using the previous function.
    has_lower = False
    prev_func = ida_funcs.get_prev_func(ea)
    if prev_func:
        prev_func_seg = _find_segment_containing_ea(prev_func.start_ea,
                                                    seg_ref)
        if prev_func_seg and _is_executable_seg(prev_func_seg):
            min_ea = max(prev_func.end_ea, min_ea)
            has_lower = True

    # Try to tighten the bounds using the function containing `ea`.
    if not has_lower:
        min_ea = max(min_ea, func.start_ea)

    if not has_upper:
        max_ea = min(max_ea, func.end_ea)

    return min_ea, max_ea
예제 #6
0
def fix_func_prolog(ea, end_ea=idc.BADADDR):
    global FUNC_BY_LS

    func_cnt = 0
    func = ida_funcs.get_fchunk(ea)
    if func is None:
        func = ida_funcs.get_next_func(ea)
    ea = func.start_ea

    while func is not None and ea < end_ea:
        # if current function is small enough and there exists a function right
        # next to current function
        if (func.size() <= 8 and idc.get_func_attr(
                func.end_ea, idc.FUNCATTR_START) != idc.BADADDR):
            # If the next function can be connected, there must be a basic block reference.
            # xref.type == 21 means 'fl_F', which is an ordinary flow.
            if all(
                (func.start_ea <= xref.frm < func.end_ea) and xref.type == 21
                    for xref in XrefsTo(func.end_ea)):
                if func_cnt > 0 and func_cnt % 1000 == 0:
                    print("%x <- %x: prolog merging (%d)." %
                          (func.start_ea, func.end_ea, func_cnt))
                ida_bytes.del_items(func.end_ea, ida_bytes.DELIT_EXPAND)
                ida_bytes.del_items(func.start_ea, ida_bytes.DELIT_EXPAND)
                ida_auto.auto_wait()

                status = idc.add_func(func.start_ea)
                if not status:
                    print("Error merging 0x%x <- 0x%x" %
                          (func.start_ea, func.end_ea))
                else:
                    func_cnt += 1
                    FUNC_BY_LS.discard(func.end_ea)
                ida_auto.auto_wait()

        func = ida_funcs.get_next_func(ea)
        if func:
            ea = func.start_ea

    print("Fixed %d functions" % func_cnt)
예제 #7
0
    def __process_functions(self):
        functions = list()

        start = ida_ida.cvar.inf.min_ea
        end = ida_ida.cvar.inf.max_ea

        # find first function head chunk in the range
        chunk = ida_funcs.get_fchunk(start)

        if not chunk:
            chunk = ida_funcs.get_next_fchunk(start)
        while chunk and chunk.start_ea < end and (chunk.flags
                                                  & ida_funcs.FUNC_TAIL) != 0:
            chunk = ida_funcs.get_next_fchunk(chunk.start_ea)

        func = chunk

        while func and func.start_ea < end:
            start_ea = func.start_ea

            func_flags = ida_bytes.get_full_flags(start_ea)
            func_name = ida_funcs.get_func_name(start_ea)
            func_name_demangled = ida_name.get_demangled_name(
                start_ea, 0xFFFF, 0, 0)
            func_autonamed = func_flags & ida_bytes.FF_LABL != 0
            func_public = ida_name.is_public_name(start_ea)

            function = {
                'start_rva': start_ea - self._base,
                'name': func_name,
                'name_demangled': func_name_demangled,
                'is_public': func_public,
                'is_autonamed': func_autonamed
            }

            # PE32/PE32+ only support binaries up to 2GB
            if function['start_rva'] >= 2**32:
                print('RVA out of range for function: ' + function['name'],
                      file=sys.stderr)

            self.__process_function_typeinfo(function, func)

            function['labels'] = self.__process_function_labels(func)

            functions.append(function)

            func = ida_funcs.get_next_func(start_ea)

        return functions
예제 #8
0
def processFunctions():
    functions = list()

    start = ida_ida.cvar.inf.min_ea
    end = ida_ida.cvar.inf.max_ea

    # find first function head chunk in the range
    chunk = ida_funcs.get_fchunk(start)

    if not chunk:
        chunk = ida_funcs.get_next_fchunk(start)
    while chunk and chunk.start_ea < end and (chunk.flags
                                              & ida_funcs.FUNC_TAIL) != 0:
        chunk = ida_funcs.get_next_fchunk(chunk.start_ea)

    func = chunk

    while func and func.start_ea < end:
        start_ea = func.start_ea

        flags = ida_bytes.get_full_flags(start_ea)

        function = {
            'start_ea': start_ea,
            'name': ida_funcs.get_func_name(start_ea),
            'is_public': ida_name.is_public_name(start_ea),
            'is_autonamed': flags & ida_bytes.FF_LABL != 0
        }

        processFunctionTypeinfo(function)

        functions.append(function)

        func = ida_funcs.get_next_func(start_ea)

    return functions
예제 #9
0
def ProgramAddrRange() :
    return ida_funcs.get_prev_func(ida_idaapi.BADADDR) - ida_funcs.get_next_func(0)
예제 #10
0
def reanalyze_range_end(ea):
    return ida_funcs.get_next_func(ea).start_ea - 1
예제 #11
0
    "jns", "jnz", "jo", "jp", "js", "jz"
]
jump_pairs = [("ja", "jbe"), ("jb", "jnb"), ("jg", "jle"), ("jl", "jge"),
              ("jo", "jno"), ("jp", "jnp"), ("js", "jns"), ("jz", "jnz")]
movs = ["mov", "xchg"]

ida_api_is_new = False
try:
    import ida_auto
    ida_api_is_new = True
except ImportError:
    pass

user_pos = ida_kernwin.get_screen_ea()
after_function_before_user_pos = ida_funcs.get_prev_func(user_pos).end_ea + 1
before_function_after_user_pos = ida_funcs.get_next_func(user_pos).start_ea - 1
hopefully_a_sane_start_of_function = (after_function_before_user_pos
                                      & ~0x0F) + 0x10
make_fun_pos = None
if ida_bytes.is_code(ida_bytes.get_flags(hopefully_a_sane_start_of_function)):
    make_fun_pos = hopefully_a_sane_start_of_function


def re_analyze_relevant_range():
    ida_bytes.del_items(
        after_function_before_user_pos, 0,
        before_function_after_user_pos - after_function_before_user_pos)
    if not make_fun_pos is None:
        assume_code_at(make_fun_pos)
    else:
        run_autoanalysis(after_function_before_user_pos,
예제 #12
0
def save_x(unique_name=None, start=None, size=None):
    ea = ida_kernwin.get_screen_ea()

    # signature
    if not unique_name:
        if not start:
            seg = ida_segment.getseg(ea)
            start = seg.start_ea
        sig_bytes = ida_bytes.get_bytes(start, SIGNATURE_SIZE)
        sig_hash = hashlib.md5(sig_bytes).hexdigest()
        unique_name = sig_hash

    if not start or not size:
        seg = ida_segment.getseg(ea)
        start = seg.start_ea
        size = seg.size()

    # (start_addr, end_addr, names, comms)
    saved_data = {}
    if MD5_hash_data_file and os.path.isfile(MD5_hash_data_file):
        with open(MD5_hash_data_file, "rb") as ifile:
            received_data = pickle.loads(ifile.read())
            if received_data:
                saved_data = received_data

    # save names (func_names, labels, etc)
    # (addr, name, is_code)
    names_addr_name = []
    names = idautils.Names()
    for addr, name in names:
        if start <= addr <= start + size:
            flags = ida_bytes.get_flags(addr)
            names_addr_name.append(
                (addr - start, name, ida_bytes.is_code(flags)))

    # save comments
    comms_addr_type_comm = []
    # (addr, TYPE, comment)
    # type 0:comment 1:rpt_comment
    end = start + size
    for i in range(start, end + 1):
        if ida_bytes.get_cmt(i, 0):  # 0 Comment
            comms_addr_type_comm.append((i - start, 0, ida_bytes.get_cmt(i,
                                                                         0)))
        if ida_bytes.get_cmt(i, 1):  # 1 RptCmt
            comms_addr_type_comm.append((i - start, 1, ida_bytes.get_cmt(i,
                                                                         1)))

    # breakpoints
    bpts_addr_size_type = []
    bpt = ida_dbg.bpt_t()
    global remove_on_exit_bpts
    for i in range(start, end + 1):
        if ida_dbg.get_bpt(i, bpt):
            bpts_addr_size_type.append((i - start, bpt.size, bpt.type))
            remove_on_exit_bpts.append(i)

    # functions
    funcs_addr = []
    flag = ida_bytes.get_flags(start)
    if ida_bytes.is_func(flag):
        funcs_addr.append(0)  # start addr
    next_func = ida_funcs.get_next_func(start)
    while next_func:
        funcs_addr.append(next_func.start_ea - start)
        next_func = ida_funcs.get_next_func(next_func.start_ea)

    # SAVE
    saved_data[unique_name] = (start, start + end, names_addr_name,
                               comms_addr_type_comm, bpts_addr_size_type,
                               funcs_addr)

    if MD5_hash_data_file:
        with open(MD5_hash_data_file, "wb") as ifile:
            serial_data = pickle.dumps(saved_data)
            ifile.write(serial_data)
            print("dumpDyn::save:\n\
            Name: {}\n\
            Start address: {}".format(unique_name, hex(start)))