Beispiel #1
0
 def expanding_struc(self, sptr, offset, delta):
     sname = ida_struct.get_struc_name(sptr.id)
     self._send_packet(evt.ExpandingStrucEvent(sname, offset, delta))
     return 0
Beispiel #2
0
def is_struct_vtable(struct):
    if struct is None:
        return False
    struct_name = ida_struct.get_struc_name(struct.id)
    return VTABLE_POSTFIX in struct_name
Beispiel #3
0
 def frame(self):
     frame_id = get_func_attr(self.__start, FUNCATTR_FRAME)
     if frame_id is not None:
         return FunctionFrame(get_struc_name(frame_id), create_new=False)
Beispiel #4
0
def install_vtables_union(class_name, class_vtable_member=None, vtable_member_tinfo=None, offset=0):
    # pylint: disable=too-many-locals
    # TODO: this function is too big and must be refactored
    log.debug(
        "install_vtables_union(%s, %s, %s)",
        class_name,
        class_vtable_member,
        str(vtable_member_tinfo),
    )
    if class_vtable_member and vtable_member_tinfo:
        old_vtable_sptr = utils.extract_struct_from_tinfo(vtable_member_tinfo)
        old_vtable_class_name = ida_struct.get_struc_name(old_vtable_sptr.id)
    else:
        old_vtable_class_name = get_class_vtable_struct_name(class_name, offset)
        old_vtable_sptr = utils.get_sptr_by_name(old_vtable_class_name)
    vtables_union_name = old_vtable_class_name
    if old_vtable_sptr and not ida_struct.set_struc_name(
        old_vtable_sptr.id, old_vtable_class_name + "_orig"
    ):
        # FIXME: why log exception?
        log.exception(
            "Failed changing %s->%s_orig",
            old_vtable_class_name,
            old_vtable_class_name,
        )
        # FIXME: why -1 and not None?
        return -1
    vtables_union_id = utils.get_or_create_struct_id(vtables_union_name, True)
    vtable_member_tinfo = utils.get_typeinf(old_vtable_class_name + "_orig")
    if vtables_union_id == BADADDR:
        log.exception(
            "Cannot create union vtable for %s()%s",
            class_name,
            vtables_union_name,
        )
        # FIXME: why -1 and not None?
        return -1

    vtables_union = ida_struct.get_struc(vtables_union_id)
    if not vtables_union:
        log.exception("Could retrieve vtables union for %s", class_name)
        # FIXME: return -1?
    if vtable_member_tinfo is not None:
        vtables_union_vtable_field_name = get_class_vtables_field_name(class_name)
    else:
        vtables_union_vtable_field_name = get_interface_empty_vtable_name()
    utils.add_to_struct(vtables_union, vtables_union_vtable_field_name, vtable_member_tinfo)
    parent_struct = utils.get_sptr_by_name(class_name)
    flag = idaapi.FF_STRUCT
    mt = idaapi.opinfo_t()
    mt.tid = vtables_union_id
    struct_size = ida_struct.get_struc_size(vtables_union_id)
    vtables_union_ptr_type = utils.get_typeinf_ptr(vtables_union_name)
    if class_vtable_member:
        member_ptr = class_vtable_member
    else:
        # FIXME: add_struc_member returns error code, not member id
        member_id = ida_struct.add_struc_member(
            parent_struct,
            get_class_vtable_field_name(class_name),
            offset,
            flag,
            mt,
            struct_size,
        )
        # FIXME: get_member_by_id returns tuple, not member ptr
        member_ptr = ida_struct.get_member_by_id(member_id)
    ida_struct.set_member_tinfo(
        parent_struct,
        member_ptr,
        0,
        vtables_union_ptr_type,
        idaapi.TINFO_DEFINITE,
    )
    # FIXME: might be None! Is this OK, considering we return -1 everywhere else?
    return vtables_union
Beispiel #5
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,
        )
Beispiel #6
0
 def struc_member_deleted(self, sptr, off1, off2):
     sname = ida_struct.get_struc_name(sptr.id)
     self._send_packet(evt.StrucMemberDeletedEvent(sname, off2))
     return 0
Beispiel #7
0
def get_operand_struct_name(inst, op_no):
    path_len = 1
    path = ida_pro.tid_array(path_len)
    if ida_bytes.get_stroff_path(path.cast(), None, inst.ea, op_no):
        return ida_struct.get_struc_name(path[0])
    return ''
 def __str__(self):
     return "%s.%s @ 0x%X" % (get_struc_name(
         self._sid), self.name, self.offset)
 def __repr__(self):
     return "StructureMember(%s, 0x%X)" % (get_struc_name(
         self._sid), self._offset)
Beispiel #10
0
def install_vtables_union(
    class_name, class_vtable_member=None, vtable_member_tinfo=None, offset=0
):
    logging.debug(
        "install_vtables_union(%s, %s, %s)",
        class_name,
        class_vtable_member,
        str(vtable_member_tinfo),
    )
    if class_vtable_member and vtable_member_tinfo:
        old_vtable_sptr = utils.extract_struct_from_tinfo(vtable_member_tinfo)
        old_vtable_class_name = ida_struct.get_struc_name(old_vtable_sptr.id)
    else:
        old_vtable_class_name = get_class_vtable_struct_name(class_name, offset)
        old_vtable_sptr = utils.get_sptr_by_name(old_vtable_class_name)
    vtables_union_name = old_vtable_class_name
    if old_vtable_sptr and not ida_struct.set_struc_name(
        old_vtable_sptr.id, old_vtable_class_name + "_orig"
    ):
        logging.exception(
            f"Failed changing {old_vtable_class_name}->"
            f"{old_vtable_class_name+'orig'}"
        )
        return -1
    vtables_union_id = utils.get_or_create_struct_id(vtables_union_name, True)
    vtable_member_tinfo = utils.get_typeinf(old_vtable_class_name + "_orig")
    if vtables_union_id == BADADDR:
        logging.exception(
            f"Cannot create union vtable for {class_name}(){vtables_union_name}"
        )
        return -1

    vtables_union = ida_struct.get_struc(vtables_union_id)
    if not vtables_union:
        logging.exception(f"Could retrieve vtables union for {class_name}")
    if vtable_member_tinfo is not None:
        vtables_union_vtable_field_name = get_class_vtables_field_name(class_name)
    else:
        vtables_union_vtable_field_name = get_interface_empty_vtable_name()
    utils.add_to_struct(
        vtables_union, vtables_union_vtable_field_name, vtable_member_tinfo
    )
    parent_struct = utils.get_sptr_by_name(class_name)
    flag = idaapi.FF_STRUCT
    mt = idaapi.opinfo_t()
    mt.tid = vtables_union_id
    struct_size = ida_struct.get_struc_size(vtables_union_id)
    vtables_union_ptr_type = utils.get_typeinf_ptr(vtables_union_name)
    if class_vtable_member:
        member_ptr = class_vtable_member
    else:
        member_id = ida_struct.add_struc_member(
            parent_struct,
            get_class_vtable_field_name(class_name),
            offset,
            flag,
            mt,
            struct_size,
        )
        member_ptr = ida_struct.get_member_by_id(member_id)
    ida_struct.set_member_tinfo(
        parent_struct, member_ptr, 0, vtables_union_ptr_type, idaapi.TINFO_DEFINITE
    )
    return vtables_union
Beispiel #11
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,
):
    is_first_member = True
    if this_type is None:
        this_type = utils.get_typeinf_ptr(class_name)
    if not add_func_this:
        this_type = None
    func, next_func = get_next_func_callback(
        functions_ea, ignore_list=ignore_list, pure_virtual_name=pure_virtual_name
    )
    dummy_i = 1
    while func is not None:
        new_func_name, is_name_changed = update_func_name_with_class(func, class_name)
        func_ptr = None
        if ida_hexrays.init_hexrays_plugin():
            if is_name_changed:
                func_type = update_func_this(func, this_type)
            else:
                func_type = update_func_this(func, None)
            if func_type is not None:
                func_ptr = utils.get_typeinf_ptr(func_type)
        else:
            func_ptr = make_funcptr_pt(func, this_type)
        if add_dummy_member:
            utils.add_to_struct(vtable_struct, f"dummy_{dummy_i}", func_ptr)
            dummy_i += 1
        if is_first_member:
            # We did an hack for vtables contained in union vtable with one dummy member
            ptr_member = utils.add_to_struct(
                vtable_struct, new_func_name, func_ptr, 0, overwrite=True
            )
            is_first_member = False
        else:
            ptr_member = utils.add_to_struct(
                vtable_struct, new_func_name, func_ptr, is_offset=True
            )
        if ptr_member is None:
            logging.exception(
                "Couldn't add %s(%s) to %d",
                new_func_name,
                str(func_ptr),
                vtable_struct.id,
            )
        ida_xref.add_dref(ptr_member.id, func, ida_xref.XREF_USER | ida_xref.dr_I)
        func, 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 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
    utils.set_name_retry(vtable_head, get_vtable_instance_name(class_name, parent_name))
Beispiel #12
0
 def struc_member_deleted(self, sptr, off1, off2):
     sname = ida_struct.get_struc_name(sptr.id)
     return 0
Beispiel #13
0
 def expanding_struc(self, sptr, offset, delta):
     sname = ida_struct.get_struc_name(sptr.id)
     return 0
Beispiel #14
0
def expand_struct(struct_id, new_size):
    struct = ida_struct.get_struc(struct_id)
    if struct is None:
        log.warning("Struct id 0x%X wasn't found", struct_id)
        return
    log.debug(
        "Expanding struc %s, size: 0x%X -> 0x%X",
        ida_struct.get_struc_name(struct_id),
        ida_struct.get_struc_size(struct_id),
        new_size,
    )
    if ida_struct.get_struc_size(struct_id) > new_size - WORD_LEN:
        return
    fix_list = []
    xrefs = idautils.XrefsTo(struct.id)
    for xref in xrefs:
        if xref.type == ida_xref.dr_R and xref.user == 0 and xref.iscode == 0:
            res = ida_struct.get_member_by_id(xref.frm)
            if not res or not res[0]:
                log.warning("Xref from %08X wasn't struct_member", xref.frm)
                continue
            member = res[0]
            x_struct = ida_struct.get_member_struc(ida_struct.get_member_fullname(member.id))
            assert x_struct
            old_name = ida_struct.get_member_name(member.id)
            offset = member.soff
            # FIXME: why use random here?
            marker_name = "marker_%d" % random.randint(0, 0xFFFFFF)
            # FIXME: check if add_struc_member actually added a member
            idc.add_struc_member(
                x_struct.id,
                marker_name,
                member.soff + new_size,
                idaapi.FF_DATA | idaapi.FF_BYTE,
                -1,
                0,
            )
            log.debug(
                "Delete member (0x%X-0x%X)",
                member.soff,
                member.soff + new_size - 1,
            )
            # FIXME: check if struc member actually deleted
            ida_struct.del_struc_members(x_struct, member.soff, member.soff + new_size - 1)
            fix_list.append(
                [
                    x_struct.id,
                    old_name,
                    offset,
                    idaapi.FF_STRUCT | idaapi.FF_DATA,
                    struct_id,
                    new_size,
                ]
            )

    ret = add_to_struct(ida_struct.get_struc(struct_id), None, None, new_size - WORD_LEN)
    log.debug("Now fix args:")
    for fix_args in fix_list:
        ret = idc.add_struc_member(*fix_args)
        log.debug("%s = %d", fix_args, ret)
        x_struct_id = fix_args[0]
        idc.del_struc_member(x_struct_id, ida_struct.get_struc_size(x_struct_id))
Beispiel #15
0
 def struc_created(self, tid):
     name = ida_struct.get_struc_name(tid)
     is_union = ida_struct.is_union(tid)
     self._send_packet(evt.StrucCreatedEvent(tid, name, is_union))
     return 0
Beispiel #16
0
 def name(self):
     return get_struc_name(self._sid)
Beispiel #17
0
 def deleting_struc(self, sptr):
     sname = ida_struct.get_struc_name(sptr.id)
     self._send_packet(evt.StrucDeletedEvent(sname))
     return 0
Beispiel #18
0
 def dependency_name(self):
     struc_id = ida_struct.get_struc_by_idx(self.idx)
     return ida_struct.get_struc_name(struc_id)
Beispiel #19
0
 def renaming_struc_member(self, sptr, mptr, newname):
     sname = ida_struct.get_struc_name(sptr.id)
     offset = mptr.soff
     self._send_packet(evt.StrucMemberRenamedEvent(sname, offset, newname))
     return 0
Beispiel #20
0
# https://github.com/csnover/ida-misc
#
# Sorts all the structs in a database in case-insensitive alphabetical order.

import ida_struct
from idaapi import BADADDR

structs = []

idx = ida_struct.get_first_struc_idx()
while idx != BADADDR:
    id = ida_struct.get_struc_by_idx(idx)
    name = ida_struct.get_struc_name(id)
    structs.append((name, ida_struct.get_struc(id)))
    idx = ida_struct.get_next_struc_idx(idx)

structs.sort(key=lambda t: t[0].lower())

for i, t in enumerate(structs):
    ida_struct.set_struc_idx(t[1], i)