Exemple #1
0
 def createUserTypeStruct(self, addr, name, size, self_size):
     fields = []
     sid = ida_struct.get_struc_id("structField")
     sz = ida_struct.get_struc_size(sid)
     sid_type = ida_struct.get_struc_id("type")
     fields = []
     curr_offset = 0
     idc.set_cmt(addr, name, 0)
     for i in range(size):
         fieldname = self.nameFromOffset(self.getPtr(sid, addr+i*sz,"Name"))
         type_addr = self.getPtr(sid, addr+i*sz, "typ")
         typename = self.getType(type_addr)
         size = self.getPtr(sid_type, type_addr, "size")
         if fieldname == "" or fieldname is None:
             fieldname = "unused_"+Utils.id_generator()
         offset = self.getStructFieldOffset(sid, addr+i*sz)
         print(f"Get offset: {offset:x}")
         if offset != curr_offset:
             print("Offset missmatch.Got %d expected %d. Adding padding..." % (curr_offset, offset))
             if offset < curr_offset:
                 raise("Too many bytes already")
             while offset != curr_offset:
                 fields.append(("padding", "char"))
                 curr_offset += 1
         curr_offset += size
         if size != 0:
             offset_kind = idc.get_member_offset(sid_type, "kind")
             kind_of_type = self.getKindEnumName(type_addr)
             print(kind_of_type)
             if kind_of_type == "STRUCT_": #Disabled for now
                 name_type = self.getName(type_addr)
                 while name_type[0] == "*":
                     name_type = name_type[1:]
                 name_type = Utils.relaxName(name_type)
                 name_type = "ut_" + name_type
                 #print("setting type %s" % name_type)
                 fields.append((fieldname, name_type))
             elif kind_of_type == "STRING":
                 fields.append((fieldname, "string"))
             elif kind_of_type == "SLICE":
                 fields.append((fieldname, "slice"))
             elif kind_of_type == "INTERFACE":
                 fields.append((fieldname, "__iface"))
             else:
                 fields.append((fieldname, "char [%d]" % size))
     if curr_offset != self_size:
         print("%x: Structure size mismatch: %x" % (addr, curr_offset))
         if self_size < curr_offset:
                 raise("Too many bytes already")
         while self_size != curr_offset:
             fields.append(("padding", "char"))
             curr_offset += 1    
     new_type = [(name, fields)]
     self.settings.structCreator.createTypes(new_type)
     new_type_sid = ida_struct.get_struc_id(name)
     sz = ida_struct.get_struc_size(new_type_sid)
     if sz != self_size:
         print("%x" % addr   )
         raise("Error at creating structure")
Exemple #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))
Exemple #3
0
    def data(self):
        # if idx is None this is called for the pre-apply data identity validation
        # we'll return None so data will definitely not match
        if self.idx is None:
            return None

        struc_id = ida_struct.get_struc_by_idx(self.idx)
        struct = ida_struct.get_struc(struc_id)

        # Skip TIL structures
        if struct.from_til():
            return None

        # Skip empty structures
        if not struct.memqty:
            return None

        d = {}
        d['name'] = ida_struct.get_struc_name(struc_id)
        d['comment'] = ida_struct.get_struc_cmt(struc_id, False)
        d['repeatable_comment'] = ida_struct.get_struc_cmt(struc_id, False)
        d['size'] = ida_struct.get_struc_size(struct)
        d['union'] = ida_struct.is_union(struc_id)
        # TODO: struct alignment, hidden, listed

        d['members'] = {}
        member_idx = 0
        while member_idx != idaapi.BADADDR:
            member = struct.get_member(member_idx)
            d['members'][member_idx] = self.member_data(member)
            member_idx = ida_struct.get_next_member_idx(struct, member.soff)
            # TODO: FIX issue with looping over members
            member_idx = idaapi.BADADDR

        return d
Exemple #4
0
def main():
    tid = get_guid_tid()
    for type_name, type_prefix, filepath in GUID_LIST:
        print('[*] scanning {}'.format(type_name))
        fp = open(filepath, 'r')
        for line in fp.readlines():
            line = line.strip()
            if line == "":
                continue
            guid, guid_name = line.split(' ')
            guid_name = type_prefix + guid_name
            binary_pattern = make_binary_pattern(guid)

            ea = 0
            while True:
                ea = idc.find_binary(
                    ea, ida_search.SEARCH_DOWN | ida_search.SEARCH_NEXT
                    | ida_search.SEARCH_NOSHOW, binary_pattern)
                if ea == idaapi.BADADDR:
                    break

                idc.del_items(ea, 16, 0)
                ida_bytes.create_struct(ea, ida_struct.get_struc_size(tid),
                                        tid)
                if idc.set_name(ea, guid_name, ida_name.SN_NOWARN) != 1:
                    for i in range(0, 100):
                        if idc.set_name(ea, guid_name + "_" + str(i),
                                        ida_name.SN_NOWARN) == 1:
                            break
                    else:
                        print("[!] 0x{:X}: failed to apply {}".format(
                            ea, guid_name))
                print("[*] 0x{:X}: {}".format(ea, guid_name))

    print("[*] finished")
Exemple #5
0
def set_all_structures(dictionary,
                       overwrite=False,
                       conflicts=None,
                       retry_len=-1):
    retry = {}
    for name, new_struct_def in dictionary.iteritems():
        cur_sid = ida_struct.get_struc_id(name)
        if cur_sid != idc.BADADDR:  # A structure exists with this name

            cur_struct = ida_struct.get_struc(cur_sid)
            cur_struct_size = ida_struct.get_struc_size(cur_sid)

            cur_struct_def = psida_common.get_struct_def(cur_struct.ordinal)

            if cur_struct_def == new_struct_def:  #Skip if they're the same
                continue
            else:  # Otherwise create a conflict
                conflicts[name] = (cur_struct.ordinal, cur_struct_size,
                                   new_struct_def)
                continue

        success = psida_common.create_struct(name, new_struct_def)
        if not success:
            retry[name] = new_struct_def

    if retry and retry_len != len(retry.keys()):
        print "Retrying structures: {}".format(retry.keys())
        set_all_structures(retry,
                           overwrite,
                           conflicts,
                           retry_len=len(retry.keys()))
Exemple #6
0
def force_make_struct(ea, struct_name):
    sptr = get_sptr_by_name(struct_name)
    if sptr == BADADDR:
        return False
    s_size = ida_struct.get_struc_size(sptr)
    ida_bytes.del_items(ea, ida_bytes.DELIT_SIMPLE, s_size)
    return ida_bytes.create_struct(ea, s_size, sptr.id)
def _read_struct_member(struct, sid, union, ea, offset, name, size, asobject):
    """Read a member into a struct for read_struct."""
    flags = idc.get_member_flag(sid, offset)
    assert flags != -1
    # Extra information for parsing a struct.
    member_sid, member_ssize = None, None
    if ida_bytes.is_struct(flags):
        member_sid = idc.get_member_strid(sid, offset)
        member_ssize = ida_struct.get_struc_size(member_sid)
    # Get the address of the start of the member.
    member = ea
    if not union:
        member += offset
    # Now parse out the value.
    array = []
    processed = 0
    while processed < size:
        value, read = _read_struct_member_once(member + processed, flags, size,
                                               member_sid, member_ssize,
                                               asobject)
        assert size % read == 0
        array.append(value)
        processed += read
    if len(array) == 1:
        value = array[0]
    else:
        value = array
    struct[name] = value
Exemple #8
0
 def makeInterface(self, offset):
     idc.SetType(offset, "interfaceType")
     ifaceid = ida_struct.get_struc_id("interfaceType")
     meth_offs = idc.get_member_offset(ifaceid, "methods")
     slice_id = ida_struct.get_struc_id("slice")
     size_off = idc.get_member_offset(slice_id, "len")
     size = self.stepper.ptr(offset + meth_offs + size_off)
     if size != 0:
         addr = self.getPtr(slice_id, offset + meth_offs, "data")
         idc.SetType(addr, "imethod")
         sz = ida_struct.get_struc_size(ida_struct.get_struc_id("imethod"))
         self.make_arr(addr, size, sz, "imethod")
         names = self.processIMethods(addr, size)
         # For now only for go1.7
         if names is None:
             return
         name = self.getName(offset)
         while name[0] == "*":
             name = name[1:]
         name = Utils.relaxName(name)
         name = "user_interface_" + name
         # TODO: this is for go1.7 need additional check for other versions
         fields = [("inter", "void *"), ("type", "void *"), ("link", "void *"), ("bad", "__int32"),
                   ("unused", "__int32")]
         for i in names:
             fields.append((i, "void *"))
         itype = [(name, fields)]
         self.settings.structCreator.createTypes(itype)
Exemple #9
0
 def processIMethods(self, offst, size):
     sz = ida_struct.get_struc_size(ida_struct.get_struc_id("imethod"))
     comm = []
     for i in xrange(size):
         comm.append(self.processIMethod(offst + i * sz))
     idc.set_cmt(offst, "\n".join(comm), 0)
     return comm
Exemple #10
0
 def fix_member_idx(self, idx_cexpr):
     num = 0
     if idx_cexpr:
         # wrong vtable*, so it might be too short struct, like:
         #   .vtable.PdmAcqServiceIf[1].___cxa_pure_virtual_2
         if idx_cexpr.y.op != ida_hexrays.cot_num:
             logging.debug(
                 "0x%x: idx doesn't contains a num but %s",
                 self.cfunc.entry_ea,
                 idx_cexpr.y.opname,
             )
             return -1
         num = idx_cexpr.y.get_const_value()
         if not (idx_cexpr.type and idx_cexpr.type.is_struct()):
             logging.debug("0x%x idx type isn't struct %s",
                           self.cfunc.entry_ea, idx_cexpr.type)
             return -1
         idx_struct = utils.get_struc_from_tinfo(idx_cexpr.type)
         if idx_struct is None:
             logging.debug(
                 "0x%x idx type isn't pointing to struct %s",
                 self.cfunc.entry_ea,
                 idx_cexpr.type,
             )
             return -1
         struct_size = ida_struct.get_struc_size(idx_struct)
         num *= struct_size
     return num
Exemple #11
0
def _populate_wrapper_struct__slices(sid, classinfo):
    """Fill in the members of the wrapper struct."""
    # First add the vtable pointer.
    offset = 0
    vtable_ptr_type = '{}::vtable *'.format(classinfo.classname)
    ret = idau.struct_add_ptr(sid, 'vtable', offset, type=vtable_ptr_type)
    if ret not in (0, idc.STRUC_ERROR_MEMBER_OFFSET):
        _log(0, 'Could not create {}.vtable: {}', classinfo.classname, ret)
        return False
    # Now add all the ::fields structs.
    offset += idau.WORD_SIZE
    for ci in classinfo.ancestors(inclusive=True):
        # Get the sid of the ::fields struct.
        fields_sid = idau.struct_open(ci.classname + '::fields')
        if fields_sid is None:
            _log(0, 'Could not find {}::fields', ci.classname)
            return False
        # If this is a 0-length struct (no fields), skip it.
        size = ida_struct.get_struc_size(fields_sid)
        if size == 0:
            continue
        # If this is already in the wrapper struct, skip it. This avoids weird
        # STRUC_ERROR_MEMBER_VARLAST errors.
        if idc.get_member_offset(sid, ci.classname) != -1:
            continue
        # Add the ::fields struct to the wrapper.
        ret = idau.struct_add_struct(sid, ci.classname, offset, fields_sid)
        if ret != 0:
            _log(0, 'Could not create {}.{}: {}', classinfo.classname, ci.classname, ret)
            return False
        offset += size
    return True
def struct_add_struct(sid, name, offset, msid, count=1):
    """Add a structure member to a structure.

    If sid is a union, offset must be -1.
    """
    size = ida_struct.get_struc_size(msid)
    return idc.add_struc_member(sid, name, offset, idc.FF_DATA | idc.FF_STRU,
                                msid, size * count)
Exemple #13
0
 def parseFuncType(self, offset):
     return
     sid = ida_struct.get_struc_id("funcType")
     in_size = idc.Word(offset + idc.get_member_offset(sid, "incount"))
     out_size = idc.Word(offset + idc.get_member_offset(sid, "outcount"))
     sz = ida_struct.get_struc_size(sid)
     for i in xrange(in_size + out_size):
         idc.SetType(offset + sz + i * self.stepper.size, "type *")
Exemple #14
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
Exemple #15
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_,
        }))
Exemple #16
0
def structs():
    _structs = {}
    for struct_item in idautils.Structs():
        idx, sid, name = struct_item[:]
        sptr = ida_struct.get_struc(sid)
        size = ida_struct.get_struc_size(sptr)
        _structs[name] = Struct(name, size, {})

    return _structs
Exemple #17
0
    def ida_struct_changed(self,
                           sid: int,
                           old_name=None,
                           new_name=None,
                           deleted=False):
        """
        A utility function to catch all changes that can happen to a struct:
        1. Renames
        2. Member Changes
        3. Deletes

        Currently, any change to a struct will cause the main-thread to re-copy the entire struct from the local
        state into the remote state. This is done so we don't need to have multiple cases for single member changes.

        @param sid:         Struct ID (IDA Thing)
        @param old_name:    Old struct name (before rename)
        @param new_name:    New struct name (after rename)
        @param deleted:     True only when the entire struct has been deleted.
        @return:
        """
        # parse the info of the current struct
        s_name = new_name if new_name else ida_struct.get_struc_name(sid)

        # back out if a stack variable snuck in
        if s_name.startswith("$"):
            return 0

        sptr = ida_struct.get_struc(sid)
        s_size = ida_struct.get_struc_size(sptr)

        # if deleted, finish early
        if deleted:
            self.binsync_state_change(self.controller.push_artifact,
                                      Struct(s_name, None, {}))
            return 0

        # convert the ida_struct into a binsync_struct
        binsync_struct = Struct(s_name, s_size, {})
        for mptr in sptr.members:
            mid = mptr.id
            m_name = ida_struct.get_member_name(mid)
            m_off = mptr.soff
            m_type = ida_typeinf.idc_get_type(mptr.id) if mptr.has_ti() else ""
            m_size = ida_struct.get_member_size(mptr)
            binsync_struct.add_struct_member(m_name, m_off, m_type, m_size)

        # make the controller update the local state and push
        old_s_name = old_name if old_name else s_name
        self.binsync_state_change(self.controller.push_artifact,
                                  binsync_struct)
        return 0
Exemple #18
0
def get_structs():
    """
    Get structures from IDA database

    :return: Dict containing structure info
    """

    structs = OrderedDict()
    for idx, sid, name in idautils.Structs():
        struct = ida_struct.get_struc(sid)
        structs[name] = {}
        structs[name]['size'] = ida_struct.get_struc_size(struct)
        structs[name]['members'] = get_struct_members(struct, sid)

    return structs
Exemple #19
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)
Exemple #20
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
    )
Exemple #21
0
def struct(name):
    sid = ida_struct.get_struc_id(name)
    if sid == 0xffffffffffffffff:
        return None

    sptr = ida_struct.get_struc(sid)
    size = ida_struct.get_struc_size(sptr)
    _struct = Struct(name, size, {}, last_change=int(time()))
    for mptr in sptr.members:
        mid = mptr.id
        m_name = ida_struct.get_member_name(mid)
        m_off = mptr.soff
        m_type = ida_typeinf.idc_get_type(mptr.id) if mptr.has_ti() else ""
        m_size = ida_struct.get_member_size(mptr)
        _struct.add_struct_member(m_name, m_off, m_type, m_size)

    return _struct
def read_struct(ea, struct=None, sid=None, members=None, asobject=False):
    """Read a structure from the given address.

    This function reads the structure at the given address and converts it into a dictionary or
    accessor object.

    Arguments:
        ea: The linear address of the start of the structure.

    Options:
        sid: The structure ID of the structure type to read.
        struct: The name of the structure type to read.
        members: A list of the names of the member fields to read. If members is None, then all
            members are read. Default is None.
        asobject: If True, then the struct is returned as a Python object rather than a dict.

    One of sid and struct must be specified.
    """
    # Handle sid/struct.
    if struct is not None:
        sid2 = ida_struct.get_struc_id(struct)
        if sid2 == idc.BADADDR:
            raise ValueError('Invalid struc name {}'.format(struct))
        if sid is not None and sid2 != sid:
            raise ValueError('Invalid arguments: sid={}, struct={}'.format(
                sid, struct))
        sid = sid2
    else:
        if sid is None:
            raise ValueError('Invalid arguments: sid={}, struct={}'.format(
                sid, struct))
        if ida_struct.get_struc_name(sid) is None:
            raise ValueError('Invalid struc id {}'.format(sid))
    # Iterate through the members and add them to the struct.
    union = idc.is_union(sid)
    struct = {}
    for offset, name, size in idautils.StructMembers(sid):
        if members is not None and name not in members:
            continue
        _read_struct_member(struct, sid, union, ea, offset, name, size,
                            asobject)
    if asobject:
        struct = objectview(struct, ea, ida_struct.get_struc_size(sid))
    return struct
Exemple #23
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
Exemple #24
0
    def __process_structs(self):
        structs = []

        st_idx = ida_struct.get_first_struc_idx()
        while st_idx != ida_idaapi.BADADDR:

            st_id = ida_struct.get_struc_by_idx(st_idx)
            st_obj = ida_struct.get_struc(st_id)

            st_name = ida_struct.get_struc_name(st_id)

            structs.append({
                'type': self.__describe_struct_type(st_obj.props),
                'name': st_name,
                'size': int(ida_struct.get_struc_size(st_obj)),
                'members': self.__process_struct_members(st_obj)
            })

            st_idx = ida_struct.get_next_struc_idx(st_idx)

        return structs
Exemple #25
0
    def create_structs(self):
        self.struct_id = utils.add_struc_retry(self.name)
        if self.struct_id == BADADDR:
            return False
        self.name = idc.get_struc_name(self.struct_id)
        self.struct_ptr = ida_struct.get_struc(self.struct_id)
        if self.struct_ptr is None:
            log.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.updated_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:
                log.warning(
                    "bad struct id or size: %s(0x%X:%s) - 0x%X, %d",
                    self.name,
                    parent_offset,
                    parent_name,
                    baseclass_id,
                    baseclass_size,
                )

            cpp_utils.add_baseclass(self.name, parent_name, parent_offset)
            previous_parent_offset = parent_offset
            previous_parent_size = baseclass_size
            previous_parent_struct_id = baseclass_id
        if self.updated_parents:
            utils.refresh_struct(self.struct_ptr)

        return True
Exemple #26
0
def get_member_params(member_tif, is_offs):
    """@return: tuple(flag, mt, member_size)"""

    substruct_ptr = get_struc_from_tinfo(member_tif)
    if substruct_ptr:
        flag = idaapi.FF_STRUCT
        mt = ida_nalt.opinfo_t()
        mt.tid = substruct_ptr.id
        member_size = ida_struct.get_struc_size(substruct_ptr.id)
    else:
        flag = idaapi.FF_QWORD if WORD_LEN == 8 else idaapi.FF_DWORD
        mt = None
        member_size = WORD_LEN

    if is_offs:
        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

    return flag, mt, member_size
Exemple #27
0
    def _get_frame(self):
        result = False
        sp = get_sp_val()
        ip = get_ip_val()

        if ip and sp:
            f = get_func(ip)
            if f:
                frame = get_frame(f)
                if frame:
                    self.framesize = get_struc_size(frame)
                    n = frame.memqty
                    frame_offs = f.frregs + f.frsize
                    self.ea = sp - get_spd(f, ip) - frame_offs
                    for i in xrange(n):
                        m = frame.get_member(i)
                        if m:
                            lvar_name = get_member_name(m.id)
                            lvar_ea = self.ea + m.soff
                            lvar_size = m.eoff - m.soff
                            self.members[lvar_ea] = (lvar_name, m.soff, lvar_size, frame_offs)
                    result = True
        return result
Exemple #28
0
    def makeStructType(self, offset):
        idc.SetType(offset, "structType")
        sid = ida_struct.get_struc_id("structType")
        slice_id = ida_struct.get_struc_id("slice")
        offset_elem = idc.get_member_offset(sid, "fields")
        inner_offset = idc.get_member_offset(slice_id, "data")
        addr = self.stepper.ptr(offset_elem + offset + inner_offset)

        inner_offset = idc.get_member_offset(slice_id, "len")
        size = self.stepper.ptr(offset+offset_elem+inner_offset)
        if size == 0:
            return
        idc.SetType(addr, "structField")
        sz = ida_struct.get_struc_size(ida_struct.get_struc_id("structField"))
        self.make_arr(addr, size, sz, "structField")
        sid_type = ida_struct.get_struc_id("type")
        size_new_struct = self.getPtr(sid_type, offset, "size")
        for i in xrange(size):
            self.processStructField(addr, i*sz)
        name = self.getName(offset)
        name = Utils.relaxName(name)
        name = "ut_" + name
        self.createUserTypeStruct(addr, name, size, size_new_struct)
Exemple #29
0
    def _validate_ida_type(self):
        # type ID
        if self.tid is None or self.tid is BADADDR:
            self.log.warn("validate_ida_type: tid=%s is invalid",
                          str(self.tid))
            return False

        # struc_t pointer
        ida_sptr = ida_struct.get_struc(self.tid)
        if ida_sptr.id != self.sptr.id:
            self.log.warn(
                "validate_ida_type: sptr.id mismatch. Got %s but expected %s",
                str(ida_sptr.id), str(self.sptr.id))
            return False

        # Size
        ida_size = ida_struct.get_struc_size(ida_sptr)
        if ida_size != self.size:
            self.log.warn(
                "validate_ida_type: size mismatch. Got %s but expected %s",
                str(ida_size), str(self.size))
            return False

        # members
        count = 0
        ida_memb = self.sptr.members  # first member
        while True:
            found = False
            ida_name = ida_struct.get_member_name(ida_memb.id)

            for memb in self.members_array:
                if memb.name != ida_name:
                    continue

                found = True

                memb._set_mptr(ida_memb)
                if not memb._validate_ida_type():
                    self.log.warn(
                        "validate_ida_type: field '%s' failed validation",
                        memb.name)
                    return False

            if not found:
                self.log.warn(
                    "validate_ida_type: found unexpected member '%s'",
                    str(ida_name))
                return False

            count += 1

            next_idx = ida_struct.get_next_member_idx(
                self.sptr, ida_memb.soff)  # next member index
            if next_idx == -1:
                break

            ida_memb = self.sptr.get_member(next_idx)  # next member

        # member count
        if count != len(self.members_array):
            self.log.warn(
                "validate_ida_type: incorrect number of members. Got %d, expected %d",
                count, len(self.members_array))
            return False

        self.log.debug("validate_ida_type: found match for '%s'",
                       self.hierarchy)
        return True
Exemple #30
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,
        )