Exemple #1
0
def make_array(ea, size):
  if ea != idc.BADADDR and ea != 0:
    flags = idc.get_full_flags(ea)
    if not idc.isByte(flags) or idc.get_item_size(ea) != 1:
      idc.del_items(ea, idc.DOUNK_SIMPLE, 1)
      idc.MakeByte(ea)
    idc.MakeArray(ea, size)
Exemple #2
0
def crefs_from(ea, only_one=False, check_fixup=True):
  flags = idc.get_full_flags(ea)
  if not idc.is_code(flags):
    return

  fixup_ea = idc.BADADDR
  seen = False
  has_one = only_one
  if check_fixup:
    fixup_ea = idc.get_fixup_target_off(ea)
    if not is_invalid_ea(fixup_ea) and is_code(fixup_ea):
      seen = only_one
      has_one = True
      yield fixup_ea

    if has_one and _stop_looking_for_xrefs(ea):
      return

  for target_ea in _xref_generator(ea, idaapi.get_first_cref_from, idaapi.get_next_cref_from):
    if target_ea != fixup_ea and not is_invalid_ea(target_ea):
      seen = only_one
      yield target_ea
      if seen:
        return

  if not seen and ea in _CREFS_FROM:
    for target_ea in _CREFS_FROM[ea]:
      seen = only_one
      yield target_ea
      if seen:
        return
Exemple #3
0
def make_head(ea):
  flags = idc.get_full_flags(ea)
  if not idc.is_head(flags):
    # idc.SetFlags(ea, flags | idc.FF_DATA)
    idc.create_data(ea, idc.FF_BYTE, 1, idc.BADADDR)
    idaapi.auto_wait()
    return is_head(ea)
  return True
Exemple #4
0
def read_bytes_slowly(start, end):
  bytestr = []
  for i in xrange(start, end):
    if idc.has_value(idc.get_full_flags(i)):
      bt = idc.get_wide_byte(i)
      bytestr.append(chr(bt))
    else:
      bytestr.append("\x00")
  return "".join(bytestr)
Exemple #5
0
def make_xref(from_ea, to_ea, data_type, xref_size):
    """Force the data at `from_ea` to reference the data at `to_ea`."""
    if not idc.get_full_flags(to_ea) or is_invalid_ea(to_ea):
        DEBUG("  Not making reference (A) from {:x} to {:x}".format(
            from_ea, to_ea))
        return False

    make_head(from_ea)

    if is_code(from_ea):
        _CREFS_FROM[from_ea].add(to_ea)
        _CREFS_TO[to_ea].add(from_ea)
    else:
        _DREFS_FROM[from_ea].add(to_ea)
        _DREFS_TO[to_ea].add(from_ea)

    # If we can't make a head, then it probably means that we're at the
    # end of the binary, e.g. the last thing in the `.extern` segment.
    # or in the middle of structure. Return False in such case
    #
    # NOTE(artem): Commenting out since this breaks recovery of C++ applications
    # with IDA7. The failure occurs when processign references in .init_array
    # when the below code is enabled, those references are not treated as
    # references because make_head fails.
    #
    #if not make_head(from_ea + xref_size):
    #  return False

    ida_bytes.del_items(from_ea, idc.DELIT_EXPAND, xref_size)

    if data_type == idc.FF_QWORD:
        data_size = 8
    elif data_type == idc.FF_DWORD:
        data_size = 4
    else:
        raise ValueError("Invalid data type")

    idc.create_data(from_ea, data_type, data_size, idaapi.BADADDR)
    if not is_code_by_flags(from_ea):
        idc.add_dref(from_ea, to_ea, idc.XREF_USER | idc.dr_O)
    else:
        DEBUG("  Not making reference (B) from {:x} to {:x}".format(
            from_ea, to_ea))

    return True
Exemple #6
0
def is_internal_code(ea):
  if is_invalid_ea(ea):
    return False

  if is_external_segment(ea):
    return False
  
  if is_code(ea):
    return True

  # find stray 0x90 (NOP) bytes in .text that IDA 
  # thinks are data items.
  flags = idc.get_full_flags(ea)
  if idaapi.is_align(flags):
    if not try_mark_as_code(ea):
      return False
    return True

  return False
Exemple #7
0
def make_xref(from_ea, to_ea, data_type, xref_size):
  """Force the data at `from_ea` to reference the data at `to_ea`."""
  if not idc.get_full_flags(to_ea) or is_invalid_ea(to_ea):
    DEBUG("  Not making reference (A) from {:x} to {:x}".format(from_ea, to_ea))
    return False

  make_head(from_ea)

  if is_code(from_ea):
    _CREFS_FROM[from_ea].add(to_ea)
    _CREFS_TO[to_ea].add(from_ea)
  else:
    _DREFS_FROM[from_ea].add(to_ea)
    _DREFS_TO[to_ea].add(from_ea)

  # If we can't make a head, then it probably means that we're at the
  # end of the binary, e.g. the last thing in the `.extern` segment.
  # or in the middle of structure. Return False in such case
  #
  # NOTE(artem): Commenting out since this breaks recovery of C++ applications
  # with IDA7. The failure occurs when processign references in .init_array
  # when the below code is enabled, those references are not treated as
  # references because make_head fails.
  #
  #if not make_head(from_ea + xref_size):
  #  return False

  ida_bytes.del_items(from_ea, idc.DELIT_EXPAND, xref_size)

  if data_type == idc.FF_QWORD:
    data_size = 8
  elif data_type == idc.FF_DWORD:
    data_size = 4
  else:
    raise ValueError("Invalid data type")

  idc.create_data(from_ea, data_type, data_size, idaapi.BADADDR)
  if not is_code_by_flags(from_ea):
    idc.add_dref(from_ea, to_ea, idc.XREF_USER|idc.dr_O)
  else: 
    DEBUG("  Not making reference (B) from {:x} to {:x}".format(from_ea, to_ea))

  return True
Exemple #8
0
def is_internal_code(ea):
    if is_invalid_ea(ea):
        return False

    if is_external_segment(ea):
        return False

    if is_code(ea):
        return True

    # find stray 0x90 (NOP) bytes in .text that IDA
    # thinks are data items.
    flags = idc.get_full_flags(ea)
    if idaapi.is_align(flags):
        if not try_mark_as_code(ea):
            return False
        return True

    return False
Exemple #9
0
def get_ea_from_highlight():
    view = idaapi.get_current_viewer()
    thing = ida_kernwin.get_highlight(view)
    if thing and thing[1]:
        # we have a highligh, is it a valid name ?
        ea = idc.get_name_ea_simple(thing[0])
        if ea != idaapi.BADADDR:
            return ea
        else:
            # Try to get full highlight name
            place = idaapi.get_custom_viewer_place(view, False)
            if place and len(place) == 3:   # (plate_t, x, y)
                ea = place[0].toea()
                far_code_refs = [xref.to for xref in idautils.XrefsFrom(ea, ida_xref.XREF_FAR) \
                                 if idc.is_code(idc.get_full_flags(xref.to))]
                if far_code_refs:
                    return far_code_refs[0]

    # Reach now, we do not have any valid name, return current screen ea
    return idc.get_screen_ea()
Exemple #10
0
def check_vtable(start, end=None):
    # We recognize a vtable by looking for an array of at least 2 pointers to code followed by a
    # NULL.
    # If no end was specified, go until the end of the segment.
    if end is None:
        end = idc.get_segm_end(start)
    # Check each address in the table. Stop once we've found something other than a pointer to
    # code.
    ended_with_zero = False
    ea = start
    while ea < end:
        method = idc.get_qword(ea)
        if method == 0:
            ended_with_zero = True
            break
        if not idc.is_code(idc.get_full_flags(method)):
            break
        ea += 8
    # Compute the length.
    length = (ea - start) / 8
    possible_vtable = ended_with_zero and length >= 2
    return possible_vtable, length
Exemple #11
0
def make_xref(from_ea, to_ea, data_type, xref_size):
    """Force the data at `from_ea` to reference the data at `to_ea`."""
    if not idc.get_full_flags(to_ea) or is_invalid_ea(to_ea):
        DEBUG("  Not making reference (A) from {:x} to {:x}".format(
            from_ea, to_ea))
        return False

    make_head(from_ea)

    if is_code(from_ea):
        _CREFS_FROM[from_ea].add(to_ea)
        _CREFS_TO[to_ea].add(from_ea)
    else:
        _DREFS_FROM[from_ea].add(to_ea)
        _DREFS_TO[to_ea].add(from_ea)

    # If we can't make a head, then it probably means that we're at the
    # end of the binary, e.g. the last thing in the `.extern` segment.
    # or in the middle of structure. Return False in such case
    if not make_head(from_ea + xref_size):
        return False

    ida_bytes.del_items(from_ea, idc.DELIT_EXPAND, xref_size)

    if data_type == idc.FF_QWORD:
        data_size = 8
    elif data_type == idc.FF_DWORD:
        data_size = 4
    else:
        raise ValueError("Invalid data type")

    idc.create_data(from_ea, data_type, data_size, idaapi.BADADDR)
    if not is_code_by_flags(from_ea):
        idc.add_dref(from_ea, to_ea, idc.XREF_USER | idc.dr_O)
    else:
        DEBUG("  Not making reference (B) from {:x} to {:x}".format(
            from_ea, to_ea))

    return True
Exemple #12
0
def get_symbol_name(from_ea, ea=None, allow_dummy=False):
    if ea is None:
        ea = from_ea

    global _FORCED_NAMES
    if ea in _FORCED_NAMES:
        return _FORCED_NAMES[ea]

    flags = idc.get_full_flags(ea)
    if not allow_dummy and idaapi.has_dummy_name(flags):
        return ""

    name = ""
    try:
        name = name or idc.get_name(ea, 0)  #calc_gtn_flags(from_ea, ea))
    except:
        pass

    try:
        name = name or idc.get_func_name(ea)
    except:
        pass

    return name
Exemple #13
0
def ida_make_functions(location, require_term=True):
    """
    Description:
        Attempts to create functions based on the assumption that there should be continuous contiguous
        functions defined since the previous function or align. Stops creating functions once a function
        containing <location> is created or the next created function would be past <location>.
        Only identifies potential start EAs and lets IDA find the ends.

    Input:
        location - The EA at which IDA should attempt to make a function.
        require_term - When True, requires the last instruction in all defined functions to be retn or jmp

    Output:
        True if it made a function or a function was already present, False otherwise.
    """
    sanity = sanity_checks(location)
    if sanity is None:  # There was already a function
        return True
    elif sanity is False:  # There was something preventing function creation
        return False

    target_location = location
    function_start = location
    ea = location
    while not (idaapi.get_func(ea) or idc.is_align(idc.get_full_flags(ea))):
        function_start = ea
        ea = idc.prev_head(ea)
    function_start = trim_func(function_start, idc.next_head)

    if try_make_function(function_start, require_term=require_term):
        if not idaapi.get_func(target_location):
            return ida_make_functions(target_location, require_term)
        else:
            return True
    else:
        return False
Exemple #14
0
def get_value_type(ea):
    addr_type = T_VALUE

    if not idaapi.is_loaded(ea):
        return addr_type

    segm_name = idc.get_segm_name(ea)
    segm = idaapi.getseg(ea)
    flags = idc.get_full_flags(ea)
    is_code = idc.is_code(flags)

    if "stack" in segm_name.lower() or \
    (dbg.stack_segm and dbg.stack_segm.start_ea == segm.start_ea):
        addr_type = T_STACK

    elif "heap" in segm_name.lower():
        addr_type = T_HEAP

    elif segm is not None:
        if not is_code and segm.perm & idaapi.SEGPERM_READ and \
        segm.perm & idaapi.SEGPERM_WRITE and \
        segm.perm & idaapi.SEGPERM_EXEC:
            addr_type = T_RWX

        elif is_code or \
        (segm.perm & idaapi.SEGPERM_READ and segm.perm & idaapi.SEGPERM_EXEC):
            addr_type = T_CODE

        elif segm.perm & idaapi.SEGPERM_READ and \
        segm.perm & idaapi.SEGPERM_WRITE:
            addr_type = T_DATA

        elif segm.perm & idaapi.SEGPERM_READ:
            addr_type = T_RODATA

    return addr_type
Exemple #15
0
def get_symbol_name(from_ea, ea=None, allow_dummy=False):
  if ea is None:
    ea = from_ea

  global _FORCED_NAMES
  if ea in _FORCED_NAMES:
    return _FORCED_NAMES[ea]

  flags = idc.get_full_flags(ea)
  if not allow_dummy and idaapi.has_dummy_name(flags):
    return ""

  name = ""
  try:
    name = name or idc.get_name(ea, 0) #calc_gtn_flags(from_ea, ea))
  except:
    pass

  try:
    name = name or idc.get_func_name(ea)
  except:
    pass

  return name
Exemple #16
0
def is_code_by_flags(ea):
    if not is_code(ea):
        return False

    flags = idc.get_full_flags(ea)
    return idc.is_code(flags)
Exemple #17
0
def is_user_name(ea):
  f = idc.get_full_flags(ea)
  return idc.hasUserName(f)
def is_unknown(va):
    return ida_bytes.is_unknown(idc.get_full_flags(va))
def is_head(va):
    return ida_bytes.is_head(idc.get_full_flags(va))
Exemple #20
0
    #
    #    extern:0000000000023558 ; Segment type: Externs
    #    extern:0000000000023558 ; extern
    #    extern:0000000000023558 ; const __int32_t **_ctype_toupper_loc(void)
    #    extern:0000000000023558                 extrn __ctype_toupper_loc:near
    #
    #    Python>idautils.DecodeInstruction(0x23558).get_canon_mnem()
    #    'retn'
    if idc.get_segm_attr(seg, SEGATTR_TYPE) == idc.SEG_XTRN:
        #print("skipping segment ", idc.get_segm_name(seg))
        continue
    for fn in idautils.Functions(seg, idc.get_segm_end(seg)):
        #func_name = idc.get_name(fn)
        for (chunk_start, chunk_end) in idautils.Chunks(fn):
            for head in idautils.Heads(chunk_start, chunk_end):
                flags = idc.get_full_flags(head)
                if not is_code(flags):
                    # Skip non-code heads. These may appear in functions containing
                    # inlined jump tables or alignment directives.
                    continue
                #inst = idc.GetDisasm(head)
                inst_addr = head
                insts[inst_addr] = True

for inst_addr in insts:
    inst_addrs.append(inst_addr)
inst_addrs.sort()

inst_addrs_json = "["
for inst_addr in inst_addrs:
    inst_addrs_json += "\n\t\"0x%08X\"," % (inst_addr)
Exemple #21
0
def is_head(ea):
  return idc.is_head(idc.get_full_flags(ea))
Exemple #22
0
 def cmd_get_flags(self, a):
     return "0x{:08X}".format(idc.get_full_flags(int(a, 0)))
Exemple #23
0
def update_vtable_struct(
    functions_ea,
    vtable_struct,
    class_name,
    this_type=None,
    get_next_func_callback=get_vtable_line,
    vtable_head=None,
    ignore_list=None,
    add_dummy_member=False,
    pure_virtual_name=None,
    parent_name=None,
    add_func_this=True,
    force_rename_vtable_head=False,  # rename vtable head even if it is already named by IDA
    # if it's not named, then it will be renamed anyway
):
    # pylint: disable=too-many-arguments,too-many-locals,too-many-branches
    # TODO: refactor
    if this_type is None:
        this_type = utils.get_typeinf_ptr(class_name)
    if not add_func_this:
        this_type = None
    func_ea, next_func = get_next_func_callback(
        functions_ea,
        ignore_list=ignore_list,
        pure_virtual_name=pure_virtual_name,
    )
    dummy_i = 1
    offset = 0
    while func_ea is not None:
        new_func_name, _ = update_func_name_with_class(func_ea, class_name)
        func_ptr = None
        if ida_hexrays.init_hexrays_plugin():
            fix_userpurge(func_ea, idc.TINFO_DEFINITE)
            update_func_this(func_ea, this_type, idc.TINFO_DEFINITE)
            func_ptr = utils.get_typeinf_ptr(utils.get_func_tinfo(func_ea))
        else:
            func_ptr = make_funcptr_pt(func_ea, this_type)  # TODO: maybe try to get or guess type?
        if add_dummy_member:
            utils.add_to_struct(vtable_struct, "dummy_%d" % dummy_i, func_ptr)
            dummy_i += 1
            offset += utils.WORD_LEN
        ptr_member = utils.add_to_struct(
            vtable_struct, new_func_name, func_ptr, offset, overwrite=True, is_offs=True
        )
        if ptr_member is None:
            log.error(
                "Couldn't add %s(%s) to vtable struct 0x%X at offset 0x%X",
                new_func_name,
                str(func_ptr),
                vtable_struct.id,
                offset,
            )
        offset += utils.WORD_LEN
        if not ida_xref.add_dref(ptr_member.id, func_ea, ida_xref.XREF_USER | ida_xref.dr_I):
            log.warn(
                "Couldn't create xref between member %s and func %s",
                ida_struct.get_member_name(ptr_member.id),
                idc.get_name(func_ea),
            )
        func_ea, next_func = get_next_func_callback(
            next_func,
            ignore_list=ignore_list,
            pure_virtual_name=pure_virtual_name,
        )

    vtable_size = ida_struct.get_struc_size(vtable_struct)

    if vtable_head is None:
        vtable_head = functions_ea
    # ida_bytes.del_items(vtable_head, ida_bytes.DELIT_SIMPLE, vtable_size)
    ida_bytes.create_struct(vtable_head, vtable_size, vtable_struct.id)
    if not idc.hasUserName(idc.get_full_flags(vtable_head)) or force_rename_vtable_head:
        if parent_name is None and this_type:
            parent = utils.deref_struct_from_tinfo(this_type)
            parent_name = ida_struct.get_struc_name(parent.id)
            if parent_name == class_name:
                parent_name = None
        idc.set_name(
            vtable_head,
            get_vtable_instance_name(class_name, parent_name),
            ida_name.SN_CHECK | ida_name.SN_FORCE,
        )
Exemple #24
0
 def is_offset(self, ea):
     return idc.is_off0(idc.get_full_flags(ea))
Exemple #25
0
def is_head(ea):
    return idc.is_head(idc.get_full_flags(ea))
Exemple #26
0
def make_func_sigs(config):
    logger = logging.getLogger("idb2pat:make_func_sigs")
    sigs = []
    if config.mode == USER_SELECT_FUNCTION:
        f = idaapi.choose_func("Choose Function:", idc.BADADDR)
        if f is None:
            logger.error("No function selected")
            return []
        idc.jumpto(f.start_ea)
        if not idaapi.has_any_name(idc.get_full_flags(f.start_ea)):
            logger.error("Function doesn't have a name")
            return []

        try:
            sigs.append(make_func_sig(config, f))
        except Exception as e:
            logger.exception(e)
            logger.error("Failed to create signature for function at %s (%s)",
                         hex(f.start_ea),
                         idc.get_func_name(f.start_ea) or "")

    elif config.mode == NON_AUTO_FUNCTIONS:
        for f in get_functions():
            # HTC - remove check FUNC_LIB flag to include library functions
            if idaapi.has_name(idc.get_full_flags(f.start_ea)):
                # and f.flags & idc.FUNC_LIB == 0:
                try:
                    sigs.append(make_func_sig(config, f))
                except FuncTooShortException:
                    pass
                except Exception as e:
                    logger.exception(e)
                    logger.error(
                        "Failed to create signature for function at %s (%s)",
                        hex(f.start_ea),
                        idc.get_name(f.start_ea) or "")

    elif config.mode == LIBRARY_FUNCTIONS:
        for f in get_functions():
            if idaapi.has_name(idc.get_full_flags(
                    f.start_ea)) and f.flags & idc.FUNC_LIB != 0:
                try:
                    sigs.append(make_func_sig(config, f))
                except FuncTooShortException:
                    pass
                except Exception as e:
                    logger.exception(e)
                    logger.error(
                        "Failed to create signature for function at %s (%s)",
                        hex(f.start_ea),
                        idc.get_name(f.start_ea) or "")

    elif config.mode == PUBLIC_FUNCTIONS:
        for f in get_functions():
            if idaapi.is_public_name(f.start_ea):
                try:
                    sigs.append(make_func_sig(config, f))
                except FuncTooShortException:
                    pass
                except Exception as e:
                    logger.exception(e)
                    logger.error(
                        "Failed to create signature for function at %s (%s)",
                        hex(f.start_ea),
                        idc.get_name(f.start_ea) or "")

    elif config.mode == ENTRY_POINT_FUNCTIONS:
        for i in zrange(idaapi.get_func_qty()):
            f = idaapi.get_func(idaapi.get_entry(idaapi.get_entry_ordinal(i)))
            if f is not None:
                try:
                    sigs.append(make_func_sig(config, f))
                except FuncTooShortException:
                    pass
                except Exception as e:
                    logger.exception(e)
                    logger.error(
                        "Failed to create signature for function at %s (%s)",
                        hex(f.start_ea),
                        idc.get_name(f.start_ea) or "")

    elif config.mode == ALL_FUNCTIONS:
        n = idaapi.get_func_qty()
        for i, f in enumerate(get_functions()):
            try:
                logger.info("[ %d / %d ] %s %s", i + 1, n,
                            idc.get_name(f.start_ea), hex(f.start_ea))
                sigs.append(make_func_sig(config, f))
            except FuncTooShortException:
                pass
            except Exception as e:
                logger.exception(e)
                logger.error(
                    "Failed to create signature for function at %s (%s)",
                    hex(f.start_ea),
                    idc.get_name(f.start_ea) or "")

    return sigs
Exemple #27
0
def is_code_ptr(ea):
    return is_mapped_data(ea, 4) and idc.is_code(
        idc.get_full_flags(idc.get_qword(ea)))
Exemple #28
0
def is_code_by_flags(ea):
  if not is_code(ea):
    return False

  flags = idc.get_full_flags(ea)
  return idc.is_code(flags)
Exemple #29
0
 def is_code(self, ea):
     flags = idc.get_full_flags(ea)
     return idc.is_code(flags)
Exemple #30
0
def is_code_ea(ea):
    if idaapi.cvar.inf.procname == "ARM":
        flags = idc.get_full_flags(ea & -2)  # flags_t
    else:
        flags = idc.get_full_flags(ea)
    return idc.is_code(flags)
Exemple #31
0
def find_function_ends(location, end_mnem_bytes=None):
    """
    Description:
        Identifies all possible function ends before the next function or Align.

    Input:
        location - The EA to search after
        end_mnem_bytes - Try to end functions on a particular instruction
                         Instructions are entered as space separated bytes (i.e. 'C2' for 'retn')
                         The specified pattern will be used first, then the defaults will be used
                         If no pattern is specified, the defaults will be used, which prefers 'retn'

    Output:
        ends - A list of function end EAs sorted: end_mnem_bytes, retn, jmp
    """
    # foreach target bytes:
    #  step instructions down
    #  if instruction matches the target bytes, add to the corresponding output list
    #  if we hit a function or an align, quit
    # return ends in the order:
    #  end_nmem_bytes
    #  retn
    #  jmp
    #  others, sorted ascending

    max_location = None
    ea = location
    while max_location is None:
        ea = idc.next_head(ea)
        if idaapi.get_func(ea) or idc.is_align(idc.get_full_flags(ea)):
            max_location = ea
        elif ea == idc.BADADDR:
            max_location = idaapi.getseg(location).end_ea
    max_location = min(max_location, idaapi.getseg(location).end_ea)

    targets = ['C3', 'C2', 'E9', 'EA', 'EB']
    if end_mnem_bytes:
        targets.insert(0, end_mnem_bytes)

    ends = {}
    for target in targets:
        function_ends = []
        ea = find_binary_instruction_start(location,
                                           idc.SEARCH_DOWN,
                                           target,
                                           max_location=max_location)
        while ea != idc.BADADDR:
            if ea > max_location:
                break
            else:
                function_ends.append(ea)
            ea = find_binary_instruction_start(ea + 11,
                                               idc.SEARCH_DOWN,
                                               target,
                                               max_location=max_location)
        ends[target] = function_ends

    return [
        end + idc.get_item_size(end) for end in (
            (ends[end_mnem_bytes] if end_mnem_bytes else []) +
            sorted(ends['C3'] + ends['C2']) + sorted(
                itertools.chain.from_iterable(ends[target]
                                              for target in targets[-3:])))
    ]