Esempio n. 1
0
def get_mptr_by_member_id(mid):
    if mid is None or mid == BADADDR:
        return None
    res = ida_struct.get_member_by_id(mid)
    if not res:
        return None
    return res[0]
Esempio n. 2
0
def expand_struct(struct_id, new_size):
    struct = ida_struct.get_struc(struct_id)
    if struct is None:
        logging.warning("Struct id 0x%x wasn't found", struct_id)
        return
    logging.debug(
        "Expanding struc %s 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:
            member, full_name, x_struct = ida_struct.get_member_by_id(xref.frm)
            if x_struct is not None:
                old_name = ida_struct.get_member_name(member.id)
                offset = member.soff
                marker_name = "marker_%d" % random.randint(0, 0xFFFFFF)
                idc.add_struc_member(
                    x_struct.id,
                    marker_name,
                    member.soff + new_size,
                    idaapi.FF_DATA | idaapi.FF_BYTE,
                    -1,
                    0,
                )
                logging.debug(
                    "Delete member (0x%x-0x%x)", member.soff, member.soff + new_size - 1
                )
                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,
                    ]
                )
            else:
                logging.warning("Xref wasn't struct_member 0x%x", xref.frm)

    ret = push_ptr_member_to_struct(
        ida_struct.get_struc(struct_id), None, None, new_size - WORD_LEN
    )
    logging.debug("Now fix args:")
    for fix_args in fix_list:
        ret = idc.add_struc_member(*fix_args)
        logging.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))
Esempio n. 3
0
def get_member_by_id(mid):
    # Replacement for the ida_struct.get_member_by_id(),
    # which in IDA7.0 returns incorrect sptr
    res = ida_struct.get_member_by_id(mid)
    if not res:
        return None
    mptr, member_fullname, _ = res
    sptr = ida_struct.get_member_struc(ida_struct.get_member_fullname(mptr.id))
    return mptr, member_fullname, sptr
Esempio n. 4
0
def post_func_name_change(new_name, ea):
    xrefs = idautils.XrefsTo(ea, ida_xref.XREF_USER)
    xrefs = filter(lambda x: x.type == ida_xref.dr_I and x.user == 1, xrefs)
    args_list = []
    for xref in xrefs:
        member, old_name, struct = ida_struct.get_member_by_id(xref.frm)
        if member is not None and struct is not None:
            args_list.append([struct, member.get_soff(), new_name])

    return utils.set_member_name, args_list
Esempio n. 5
0
 def ti_changed(self, ea, typeinf, fnames):
     res = ida_struct.get_member_by_id(ea)
     if res is not None:
         m, name, sptr = res
         if sptr.is_frame():
             func = ida_funcs.get_func(ida_frame.get_func_by_frame(sptr.id))
             if func is not None:
                 return self.func_updated(func)
     elif utils.is_func(ea):
         return self.func_updated(ida_funcs.get_func(ea))
     return 0
Esempio n. 6
0
def post_func_type_change(pfn):
    ea = pfn.start_ea
    xrefs = idautils.XrefsTo(ea, ida_xref.XREF_USER)
    xrefs = list(filter(lambda x: x.type == ida_xref.dr_I and x.user == 1, xrefs))
    args_list = []
    if len(xrefs) == 0:
        return None, []
    try:
        xfunc = ida_hexrays.decompile(ea)
        func_ptr_typeinf = utils.get_typeinf_ptr(xfunc.type)
        for xref in xrefs:
            member, old_name, struct = ida_struct.get_member_by_id(xref.frm)
            if member is not None and struct is not None:
                args_list.append(
                    [struct, member, 0, func_ptr_typeinf, idaapi.TINFO_DEFINITE]
                )
    except Exception:
        pass
    return ida_struct.set_member_tinfo, args_list
Esempio n. 7
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
Esempio n. 8
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
Esempio n. 9
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))