예제 #1
0
def get_overriden_func_names(union_name, offset, get_not_funcs_members=False):
    sptr = utils.get_sptr_by_name(union_name)
    res = []
    if not sptr.is_union:
        return res

    for i in range(ida_struct.get_max_offset(sptr)):
        member = ida_struct.get_member(sptr, i)
        cls = ida_struct.get_member_name(member.id)
        tinfo = utils.get_member_tinfo(member)
        log.debug("Trying %s", cls)
        if cls == get_interface_empty_vtable_name() or not tinfo.is_ptr():
            continue
        pointed_obj = tinfo.get_pointed_object()
        if not pointed_obj.is_struct():
            continue
        vtable_sptr = utils.get_sptr_by_name(pointed_obj.get_final_type_name())
        if ida_struct.get_max_offset(vtable_sptr) <= offset:
            continue
        funcptr_member = ida_struct.get_member(vtable_sptr, offset)
        funcptr_type = utils.get_member_tinfo(funcptr_member)
        func_name = ida_struct.get_member_name(funcptr_member.id)
        if not funcptr_type.is_funcptr() and not get_not_funcs_members:
            continue
        res.append((cls, func_name))
    return res
예제 #2
0
    def get_vtable_member_type(self, vtable_sptr, offset):
        vtable_struct_name = ida_struct.get_struc_name(vtable_sptr.id)
        try:
            funcptr_member = ida_struct.get_member(vtable_sptr, offset)
        except TypeError as e:
            logging.exception("0x%x: bad offset: 0x%x", self.cfunc.entry_ea,
                              offset)
            return None

        if funcptr_member is None:
            logging.debug(
                "0x%x:  %s.%d is not a valid struct member",
                self.cfunc.entry_ea,
                vtable_struct_name,
                offset,
            )
            return None

        funcptr_member_type = utils.get_member_tinfo(funcptr_member)
        if not funcptr_member_type.is_funcptr():
            logging.debug(
                "0x%x: member type (%s) isn't funcptr!",
                self.cfunc.entry_ea,
                funcptr_member_type.dstr(),
            )
            return None

        return funcptr_member_type
예제 #3
0
 def apply_member(cls, struct, data):
     ida_struct.add_struc_member(struct, data['name'], data['offset'],
                                 data['flag'], data['opinfo'], data['size'])
     member = ida_struct.get_member(struct, data['offset'])
     if 'comment' in data and data['comment']:
         ida_struct.set_member_cmt(member, data['comment'], False)
     if 'repeatable_comment' in data and data['repeatable_comment']:
         ida_struct.set_member_cmt(member, data['repeatable_comment'], True)
예제 #4
0
def push_ptr_member_to_struct(
    struct, member_name, member_type, offset=BADADDR, overwrite=False
):
    mt = None
    flag = idaapi.FF_DWORD
    member_size = WORD_LEN
    if member_type is not None and (member_type.is_struct() or member_type.is_union()):
        logging.debug("Is struct!")
        substruct = extract_struct_from_tinfo(member_type)
        if substruct is not None:
            flag = idaapi.FF_STRUCT
            mt = ida_nalt.opinfo_t()
            mt.tid = substruct.id
            logging.debug(
                f"Is struct: {ida_struct.get_struc_name(substruct.id)}/{substruct.id}"
            )
            member_size = ida_struct.get_struc_size(substruct.id)
            member_type = None
    elif WORD_LEN == 4:
        flag = idaapi.FF_DWORD
    elif WORD_LEN == 8:
        flag = idaapi.FF_QWORD

    new_member_name = member_name
    if overwrite and ida_struct.get_member(struct, offset):
        logging.debug("Overwriting!")
        ret_val = ida_struct.set_member_name(struct, offset, member_name)
        i = 0
        while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME:
            new_member_name = "%s_%d" % (member_name, i)
            i += 1
            if i > 250:
                return
            ret_val = ida_struct.set_member_name(struct, offset, new_member_name)

    else:
        ret_val = ida_struct.add_struc_member(
            struct, new_member_name, offset, flag, mt, member_size
        )
        i = 0
        while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME:
            new_member_name = "%s_%d" % (member_name, i)
            i += 1
            if i > 250:
                return
            ret_val = ida_struct.add_struc_member(
                struct, new_member_name, offset, flag, mt, member_size
            )
        if ret_val != 0:
            logging.debug(f"ret_val: {ret_val}")
    member_ptr = ida_struct.get_member_by_name(struct, new_member_name)
    if member_ptr is None:
        logging.debug("member is None")
    if member_type is not None and member_ptr is not None:
        ida_struct.set_member_tinfo(
            struct, member_ptr, 0, member_type, idaapi.TINFO_DEFINITE
        )
    return member_ptr
예제 #5
0
def main():
    is_selected, sel_start, sel_end = ida_kernwin.read_selection()
    if not is_selected:
        logger.error('range must be selected')
        return -1

    sel_end = ida_bytes.next_head(sel_end)

    buf = ida_bytes.get_bytes(sel_start, sel_end - sel_start)
    if buf is None:
        logger.error('failed to fetch instruction bytes')
        return -1

    f = ida_funcs.get_func(sel_start)
    if f != ida_funcs.get_func(sel_end):
        logger.error('range must be within a single function')
        return -1

    # find mappings from "$localN" to "custom_name"
    regvars = {}
    for i in range(0x1000):
        regvar = ida_frame.find_regvar(f, sel_start, '$local%d' % i)
        if regvar is None:
            continue
        regvars[regvar.canon] = regvar.user

        if len(regvars) >= f.regvarqty:
            break

    globals_ = {}
    for i, offset in netnode.Netnode('$ wasm.offsets').get('globals',
                                                           {}).items():
        globals_['$global' + i] = ida_name.get_name(offset)

    frame = {}
    if f.frame != ida_idaapi.BADADDR:
        names = set([])
        for i in range(ida_struct.get_struc_size(f.frame)):
            s = ida_struct.get_struc(f.frame)
            if not s:
                continue
            m = ida_struct.get_member(s, i)
            if not m:
                continue
            name = ida_struct.get_member_name(m.id)
            if name in names:
                continue
            frame[i] = name
            names.add(name)

    emu = Emulator(buf)
    emu.run()
    print(
        emu.render(ctx={
            'regvars': regvars,
            'frame': frame,
            'globals': globals_,
        }))
예제 #6
0
    def create_structs(self):
        self.struct_id = ida_struct.add_struc(BADADDR, self.name)
        self.struct_ptr = ida_struct.get_struc(self.struct_id)
        if self.struct_ptr is None:
            logging.exception("self.struct_ptr is None at %s", self.name)
        previous_parent_offset = 0
        previous_parent_size = 0
        previous_parent_struct_id = BADADDR
        for _, parent_name, parent_offset in self.parents:
            if (
                parent_offset - previous_parent_offset > previous_parent_size
                and previous_parent_struct_id != BADADDR
            ):
                utils.expand_struct(
                    previous_parent_struct_id, parent_offset - previous_parent_offset
                )
            baseclass_id = ida_struct.get_struc_id(parent_name)
            baseclass_size = ida_struct.get_struc_size(baseclass_id)
            if baseclass_id == BADADDR or baseclass_size == 0:
                logging.warning(
                    "bad struct id or size: %s(0x%x:%s) - %s, %d",
                    self.name,
                    parent_offset,
                    parent_name,
                    baseclass_id,
                    baseclass_size,
                )
            member_name = cpp_utils.get_base_member_name(parent_name, parent_offset)
            idc.add_struc_member(
                self.struct_id,
                member_name,
                parent_offset,
                idaapi.FF_STRUCT,
                baseclass_id,
                baseclass_size,
            )
            previous_parent_offset = parent_offset
            previous_parent_size = baseclass_size
            previous_parent_struct_id = baseclass_id

        for _, parent_name, parent_offset in self.parents:
            ida_struct.get_member(
                self.struct_ptr, parent_offset
            ).props |= ida_struct.MF_BASECLASS
예제 #7
0
def find_vtable_at_offset(struct_ptr, vtable_offset):
    current_struct = struct_ptr
    current_offset = 0
    member = ida_struct.get_member(current_struct, vtable_offset)
    if member is None:
        return None
    parents_vtables_classes = []
    current_offset += member.get_soff()
    while current_offset < vtable_offset and member is not None:
        current_struct = utils.get_member_substruct(member)
        if current_struct is None:
            return
        parents_vtables_classes.append(
            [
                ida_struct.get_struc_name(current_struct.id),
                vtable_offset - current_offset,
            ]
        )
        member = ida_struct.get_member(current_struct, vtable_offset - current_offset)
        if member is None:
            logging.exception(
                "Couldn't find vtable at offset %d for %d",
                vtable_offset - current_offset,
                struct_ptr.id,
            )
        current_offset += member.get_soff()

    if current_offset != vtable_offset:
        return None

    while member is not None:
        if is_member_vtable(member):
            return member, current_struct, parents_vtables_classes
        current_struct = utils.get_member_substruct(member)
        if current_struct is None:
            return None
        parents_vtables_classes.append(
            [ida_struct.get_struc_name(current_struct.id), 0]
        )
        member = ida_struct.get_member(current_struct, 0)

    return None
예제 #8
0
    def get_struc_name(self):

        x = self.target.operands['x']
        m = self.target.operands['m']

        xtype = x.type
        xtype.remove_ptr_or_array()
        typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, xtype, '', '')

        sid = ida_struct.get_struc_id(typename)
        sptr = ida_struct.get_struc(sid)
        member = ida_struct.get_member(sptr, m)

        return '%s::%s' % (typename, member)
예제 #9
0
def add_child_vtable(parent_name, child_name, child_vtable_id, offset):
    logging.debug(
        "add_child_vtable (%s, %s, %s)",
        parent_name,
        child_name,
        child_vtable_id,
    )
    parent_vtable_member = ida_struct.get_member(
        utils.get_sptr_by_name(parent_name), offset
    )
    vtable_member_tinfo = utils.get_member_tinfo(parent_vtable_member)
    parent_vtable_struct = utils.get_sptr_by_name(
        get_class_vtable_struct_name(parent_name, offset)
    )
    if parent_vtable_struct is None:
        return None
    pointed_struct = utils.extract_struct_from_tinfo(vtable_member_tinfo)
    logging.debug("pointed_struct: %s", str(pointed_struct))
    if (
        (pointed_struct is None)
        or (not is_struct_vtable(pointed_struct))
        or (parent_vtable_struct.id != pointed_struct.id)
    ):
        parent_vtable_member = None
        logging.debug("Not a struct vtable: %s", str(vtable_member_tinfo))

    # TODO: Check that struct is a valid vtable by name
    if not parent_vtable_struct.is_union():
        logging.debug("%s vtable isn't union -> unionize it!", parent_name)
        parent_vtable_struct = install_vtables_union(
            parent_name, parent_vtable_member, vtable_member_tinfo, offset
        )

    child_vtable_name = ida_struct.get_struc_name(child_vtable_id)
    child_vtable = utils.get_typeinf(child_vtable_name)
    logging.debug(
        "add_to_struct %s %s", parent_vtable_struct.id, str(child_vtable)
    )
    if ida_struct.get_struc_size(child_vtable_id) == 0:
        utils.add_to_struct(
            ida_struct.get_struc(child_vtable_id), "dummy", None
        )
    new_member = utils.add_to_struct(
        parent_vtable_struct, get_class_vtables_field_name(child_name), child_vtable
    )
    ida_xref.add_dref(
        new_member.id, child_vtable_id, ida_xref.XREF_USER | ida_xref.dr_O
    )
예제 #10
0
def create_struct(name, fields, size):

    struct_id = idaapi.get_struc_id(name)
    # print struct_id
    if struct_id != idaapi.BADADDR:
        i = ida_kernwin.ask_yn(
            0,
            "A class structure for %s already exists. Are you sure you want to remake it?"
            % name)
        if i == idaapi.BADADDR:
            return
        if i == 1:
            idaapi.del_struc_members(idaapi.get_struc(struct_id), 0,
                                     idaapi.get_struc_size(struct_id))
            # struct_id = idc.AddStrucEx(idaapi.BADADDR, name + "_vtbl", 0)
    else:
        struct_id = idaapi.add_struc(idaapi.BADADDR, name, 0)
    if struct_id == idaapi.BADADDR:
        Warning(
            "Could not create the class structure!.\nPlease check something.")
        return
    sptr = idaapi.get_struc(struct_id)
    for off in fields:
        off, type_name, type_kind, field_name = fields[off]
        print(
            "Process field. Off = 0x%04X, type_name = %s (%d: %s), field_name = %s"
            %
            (off, type_name, type_kind, type_sizes[type_kind][0], field_name))
        type_size = type_sizes[type_kind][1]
        ret = ida_struct.add_struc_member(sptr, field_name.decode(), off,
                                          flags_dict[type_size], None,
                                          type_size)
        if ret != 0:
            ida_kernwin.warning("Unknown error! Err = %d" % ret)
            return
        mptr = ida_struct.get_member(sptr, off)
        ida_struct.set_member_cmt(
            mptr, " --> %s (%d: %s)" %
            (type_name.decode(), type_kind, type_sizes[type_kind][0]), False)
    struct_size = ida_struct.get_struc_size(sptr)
    if size < struct_size:
        ida_kernwin.warning(
            "Struct create error! final size (%d) > instanse size (%d)" %
            (struct_size, size))
    elif size > struct_size:
        for i in range(size - struct_size):
            ida_struct.add_struc_member(sptr, "dummy%d" % i, idaapi.BADADDR,
                                        idaapi.FF_BYTE, None, 1)
예제 #11
0
 def view_dblclick(self, viewer, point):
     widget_type = ida_kernwin.get_widget_type(viewer)
     if not (widget_type == 48 or widget_type == 28):
         return
     # Decompiler or Structures window
     func_cand_name = None
     place, x, y = ida_kernwin.get_custom_viewer_place(viewer, False)
     if place.name() == "structplace_t":  # Structure window:
         structplace = ida_kernwin.place_t_as_structplace_t(place)
         if structplace is not None:
             s = ida_struct.get_struc(ida_struct.get_struc_by_idx(structplace.idx))
             if s:
                 member = ida_struct.get_member(s, structplace.offset)
                 if member:
                     func_cand_name = ida_struct.get_member_name(member.id)
     if func_cand_name is None:
         line = utils.get_curline_striped_from_viewer(viewer)
         func_cand_name = cpp_utils.find_valid_cppname_in_line(line, x)
     if func_cand_name is not None:
         func_cand_ea = ida_name.get_name_ea(BADADDR, func_cand_name)
         if func_cand_ea is not None and utils.is_func_start(func_cand_ea):
             idc.jumpto(func_cand_ea)
예제 #12
0
def add_to_struct(
    struct_ptr,
    member_name,
    member_tif=None,
    offset=BADADDR,
    is_offs=False,
    overwrite=False,
):
    """@return: member_ptr, or None if failed"""
    member_ptr = ida_struct.get_member(struct_ptr, offset)

    if member_ptr:
        # pylint: disable=too-many-function-args
        if not _update_member_name(member_ptr, member_name, overwrite):
            return None
    else:
        member_ptr = _add_new_member(struct_ptr, offset, member_name, member_tif, is_offs)
        if not member_ptr:
            return None

    _update_member_type(struct_ptr, member_ptr, member_tif)

    return member_ptr
예제 #13
0
def get_member_type(struct, idx):
    """
    Retrieve the type information for the struct member

    :return: Type string
    """

    member = ida_struct.get_member(struct, idx)
    tif = idaapi.tinfo_t()
    ida_struct.get_member_tinfo(tif, member)
    elements = str(tif).split(' ')
    typ = None
    if len(elements) == 2 and elements[0] == 'unsigned':
        if elements[1] == '__int8':
            typ = 'uint8_t'
        elif elements[1] == '__int16':
            typ = 'uint16_t'
        elif elements[1] == '__int32':
            typ = 'uint32_t'
        elif elements[1] == '__int64':
            typ = 'uint64_t'
        elif elements[1] != '':
            typ = elements[1]
    elif len(elements) == 1:
        if elements[0] == '__int8':
            typ = 'int8_t'
        elif elements[0] == '__int16':
            typ = 'int16_t'
        elif elements[0] == '__int32':
            typ = 'int32_t'
        elif elements[0] == '__int64':
            typ = 'int64_t'
        elif elements[0] != '':
            typ = str(tif)

    return typ
예제 #14
0
def update_form(update):
    """ Processes an incoming update by adding it to the form.

    Args:
        update (IdbUpdate) - The message received from the ZMQ server, as a class that inherits IdbUpdate
    """
    try:
        g_item_list_mutex.lock()
        message_type = update.update_type
        address = update.address
        current_data = None

        if message_type == idb_push_ops.UpdateTypes.Name:
            current_data = psida_common.get_non_default_name(address, update.is_local)
            if current_data == update.data:
                return

        elif message_type == idb_push_ops.UpdateTypes.Comment:
            current_data = psida_common.get_comment(address)
            if current_data == update.data:
                return

        elif message_type == idb_push_ops.UpdateTypes.RepeatableComment:
            current_data = psida_common.get_repeated_comment(address)
            if current_data == update.data:
                return

        elif message_type in [idb_push_ops.UpdateTypes.AnteriorLine, idb_push_ops.UpdateTypes.PosteriorLine]:
            current_data = idc.get_extra_cmt(address, update.line_index)
            if current_data == update.data:
                return

        elif message_type == idb_push_ops.UpdateTypes.LookHere:
            current_data = psida_common.get_non_default_name(address)

        elif message_type == idb_push_ops.UpdateTypes.StackVariableRenamed:
            func_frame = ida_frame.get_frame(address)
            update.func_frame_pointer = func_frame
            member = ida_struct.get_member(func_frame, update.offset)
            current_data = None
            if member is not None:
                current_data = ida_struct.get_member_name(member.id)

            if current_data == update.data:
                return

            if current_data is not None:
                update.new = False
            else:
                update.new = True

        elif message_type in [idb_push_ops.UpdateTypes.MakeData, idb_push_ops.UpdateTypes.MakeCode,
                              idb_push_ops.UpdateTypes.MakeFunc]:
            current_data = update.get_conflict()
            if current_data == '':
                return

        else:
            if CONFIGURATION[DEBUG]:
                print 'DEBUG - UI - Unrecognized/Unimplemented type %d: in message %s' % (message_type, update.to_dict())
            return

        update.data_at_address = current_data
        add_item(update)
    except:
        if CONFIGURATION['debug']:
            traceback.print_exc()
        print 'ERROR - UI - General error while updating form'

    finally:
        g_item_list_mutex.unlock()
예제 #15
0
def replace_dword_in_struct(idx, ctx):
    print '%x' % idx.ea
    struct_expr = ctx.get_expr('struct_part')[0]
    var = ctx.get_var("struct_var")
    values = ctx.get_expr('values')[0]
    offset = struct_expr.m
    vals = []
    N = extract_number(values)
    typename = struct_expr.x.type.dstr()
    s_id = ida_struct.get_struc_id(typename)
    if s_id == idc.BADADDR:
        return
    sptr = ida_struct.get_struc(s_id)
    is_suits = True
    fields = []
    inner_offset = 0
    while inner_offset < 4:
        memb = ida_struct.get_member(sptr, offset + inner_offset)
        if memb is None:
            print "Not enought members!"
            is_suits = False
            break
        size = ida_struct.get_member_size(memb)
        if inner_offset + size > 4:
            print "Size fail!(%d bytes lenft but member size is %d)" % (
                4 - inner_offset, size)
            is_suits = False
            break
        if size == 1:
            val = N & 0xff
            N = N >> 8
        elif size == 2:
            val = N & 0xffff
            N = N >> 16
        else:
            print "Unkn size"
            is_suits = False
            break
        fields.append((inner_offset, val))
        inner_offset += size

    if is_suits is False:
        print "Not suitable!"
        return
    inslist = []
    for i in fields:
        ins = make_asgn_refvar_number(idx.ea, var, offset + i[0], i[1])
        inslist.append(ins)
    #########
    # Not foldable
    #########
    blk = make_cblk(inslist)
    cblk = make_cblock_insn(idx.ea, blk)
    idx.cleanup()
    idaapi.qswap(idx, cblk)
    del cblk
    ##########################
    # Foldable - not working - IDA crashes at exit idk why;[
    ##########################
    #fake_cond =  make_helper_expr("fold")
    #blk = make_cblk(inslist)
    #cblk = make_cblock_insn(idx.ea, blk)
    #cif = make_if(idx.ea, fake_cond, cblk)
    #idx.cleanup()
    #idaapi.qswap(idx, cif)
    #del cif
    return True
예제 #16
0
파일: utils.py 프로젝트: zohht/ida_medigate
def add_to_struct(
    struct,
    member_name,
    member_type=None,
    offset=BADADDR,
    is_offset=False,
    overwrite=False,
):
    mt = None
    flag = idaapi.FF_DWORD
    member_size = WORD_LEN
    if member_type is not None and (member_type.is_struct()
                                    or member_type.is_union()):
        logging.debug("Is struct!")
        substruct = extract_struct_from_tinfo(member_type)
        if substruct is not None:
            flag = idaapi.FF_STRUCT
            mt = ida_nalt.opinfo_t()
            mt.tid = substruct.id
            logging.debug(
                f"Is struct: {ida_struct.get_struc_name(substruct.id)}/{substruct.id}"
            )
            member_size = ida_struct.get_struc_size(substruct.id)
    elif WORD_LEN == 4:
        flag = idaapi.FF_DWORD
    elif WORD_LEN == 8:
        flag = idaapi.FF_QWORD
    if is_offset:
        flag |= idaapi.FF_0OFF
        mt = ida_nalt.opinfo_t()
        r = ida_nalt.refinfo_t()
        r.init(
            ida_nalt.get_reftype_by_size(WORD_LEN) | ida_nalt.REFINFO_NOBASE)
        mt.ri = r

    new_member_name = member_name
    member_ptr = ida_struct.get_member(struct, offset)
    if overwrite and member_ptr:
        if ida_struct.get_member_name(member_ptr.id) != member_name:
            logging.debug("Overwriting!")
            ret_val = ida_struct.set_member_name(struct, offset, member_name)
            i = 0
            while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME:
                new_member_name = "%s_%d" % (member_name, i)
                i += 1
                if i > 250:
                    logging.debug("failed change name")
                    return
                ret_val = ida_struct.set_member_name(struct, offset,
                                                     new_member_name)

    else:
        ret_val = ida_struct.add_struc_member(struct, new_member_name, offset,
                                              flag, mt, member_size)
        i = 0
        while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME:
            new_member_name = "%s_%d" % (member_name, i)
            i += 1
            if i > 250:
                return
            ret_val = ida_struct.add_struc_member(struct, new_member_name,
                                                  offset, flag, mt,
                                                  member_size)
        if ret_val != 0:
            logging.debug(f"ret_val: {ret_val}")
        member_ptr = ida_struct.get_member_by_name(struct, new_member_name)
    if member_type is not None and member_ptr is not None:
        ida_struct.set_member_tinfo(struct, member_ptr, 0, member_type,
                                    idaapi.TINFO_DEFINITE)
    return member_ptr
예제 #17
0
 def _member(self):
     return ida_struct.get_member(self._struc, self.stack_offset)