Example #1
0
def SetStrucmember(struc_id, member_name, offset, flag, typeid, nitems, member_type=ya.OBJECT_TYPE_STRUCT_MEMBER,
                   name_offset=0):
    if member_name is None:
        member_name = get_default_struc_member_name(member_type, offset, name_offset)

    ret = idc.SetMemberName(struc_id, offset, member_name)
    if not ret:
        logger.debug("Error while naming sub strucmember (struc) : " +
                     "%d (struc=%s, member=%s, offset=0x%08X"
                     % (ret, idc.GetStrucName(struc_id), member_name, offset))
    else:
        ret = idc.SetMemberType(struc_id, offset, flag, typeid, nitems)
        if ret == 0:
            logger.debug("Error while setting sub strucmember type (struc) :" +
                         " %d (struc=%s, member=%s, offset=0x%08X, mflags=%d, nitems=%d, tid=0x%016X" %
                         (ret, idc.GetStrucName(struc_id), member_name, offset, flag, nitems, typeid))
Example #2
0
    def fix_struc_in_prototype(self, proto, struc_ids):
        current_pos = 0
        while proto.find("/*%", current_pos) != -1:
            start_comm = proto.find("/*%", current_pos)
            end_comm = proto.find("%*/", start_comm + 3)
            sharp = proto.find("#", start_comm + 3)
            struc_name = proto[start_comm + 3:sharp]
            object_id_str = proto[sharp + 1:end_comm]
            object_id = ya.YaToolObjectId_From_String(object_id_str)

            try:
                struc_id = struc_ids[object_id]
            except KeyError:
                logger.error(
                    "Bad object id str for struc in prototype : %s (in '%s')" %
                    (object_id_str, proto))
                return proto
            new_struc_name = idc.GetStrucName(struc_id)
            if new_struc_name != struc_name:
                orig_proto = proto
                proto = proto.replace(struc_name, new_struc_name)
                logger.debug("Updated proto from '%s' to '%s'" %
                             (orig_proto, proto))
                current_pos = 0
            else:
                current_pos = end_comm + 2

        return proto
Example #3
0
def get_struc_offset(ea, opn):
    path = idaapi.tid_array(1)
    delta = idaapi.sval_pointer()
    idaapi.get_stroff_path(ea, opn, path.cast(), delta.cast())
    struct = path[0]
    if idaapi.decode_insn(ea) == 0:
        print 'error in {0}'.format(GetDisasm(ea))
    else:
        op = idaapi.cmd.Operands[opn]
        offset = op.value
        result = []
        idaapi.get_stroff_path(ea, opn, path.cast(), delta.cast())
        struct = path[0]
        while offset:
            member_id = idc.GetMemberId(struct, offset)
            member_name = idc.GetMemberName(member_id)
            field_struct_id = idc.GetMemberStrId(struct, offset)
            if field_struct_id != idc.BADADDR:
                result.append(
                    [field_struct_id,
                     idc.GetStrucName(field_struct_id)])
            else:
                result.append([member_name, idc.GetMemberFlag(struct, offset)])
                return result
            offset -= idc.GetMemberOffset(member_name)
Example #4
0
def get_structures():
    """ Populate dictionaries with imported structures infomation"""
    structure_ids = {}
    if idc.GetStrucQty() == 0:
        return None

    index = None
    for i in xrange(0, idc.GetStrucQty()):
        if i == 0:
            index = idc.GetFirstStrucIdx()
        else:
            index = idc.GetNextStrucIdx(index)

        if index == idaapi.BADADDR:
            continue

        sid = idc.GetStrucId(index)
        if sid == idaapi.BADADDR:
            continue

        name = idc.GetStrucName(sid)
        if not name:
            continue

        structure_ids[sid] = name

    return structure_ids
Example #5
0
def get_object_id_of_union_member_id(hash_provider, member_id):
    try:
        return union_member_object_ids[member_id]
    except KeyError:

        idx = idc.GetFirstStrucIdx()
        while idx != idc.BADADDR:
            struc_id = idc.GetStrucId(idx)
            if idc.IsUnion(struc_id):

                offset = idc.GetFirstMember(struc_id)

                while offset != idc.BADADDR:
                    smember_id = idc.GetMemberId(struc_id, offset)
                    if smember_id == member_id:
                        name = idc.GetMemberName(struc_id, offset)
                        if name is not None:
                            struc_name = idc.GetStrucName(struc_id)
                            logger.debug("found member id 0x%016X in union %s/%s" % (member_id, struc_name, name))
                            return hash_provider.get_struc_member_id_for_name(struc_name, offset)

                    # next member
                    offset = idc.GetStrucNextOff(struc_id, offset)
            idx = idc.GetNextStrucIdx(idx)

        logger.error("Could not find member id 0x%016X in unions" % member_id)

        return None
Example #6
0
    def struc_created(self, struc):
        self.pre_hook()

        if LOG_IDB_EVENTS:
            self.debug_event("struc_created : 0x%08X (%s)" % (struc, idc.GetStrucName(struc)))
        hooks.ida.struc_updated(struc)
        return idaapi.IDB_Hooks.struc_created(self, struc)
Example #7
0
File: hooks.py Project: Spl3en/ipad
 def struc_renamed(self, struct):
     sid = struct.id
     idx = idc.GetStrucIdx(sid)
     sname = idc.GetStrucName(sid)
     self.ctrl._handle_action({
         'action': 'struct_renamed',
         'struct': idx,
         'sname': sname
     })
     return 0
def create_struct_fields(sid=None,
                         name=None,
                         accesses=None,
                         create=False,
                         base=0):
    """Create an IDA struct with fields corresponding to the specified access pattern.

    Given a sequence of (offset, size) tuples designating the valid access points to the struct,
    create fields in the struct at the corresponding positions.

    Options:
        sid: The struct id, if the struct already exists.
        name: The name of the struct to update or create.
        accesses: The set of (offset, size) tuples representing the valid access points in the
            struct.
        create: If True, then the struct will be created with the specified name if it does not
            already exist. Default is False.
        base: The base offset for the struct. Offsets smaller than this are ignored, otherwise the
            field is created at the offset minus the base. Default is 0.

    Either sid or name must be specified.
    """
    # Get the struct id.
    if sid is None:
        sid = idau.struct_open(name, create=True)
        if sid is None:
            _log(0, 'Could not open struct {}', name)
            return False
    else:
        name = idc.GetStrucName(sid)
        if name is None:
            _log(0, 'Invalid struct id {}', sid)
            return False
    # Now, for each (offset, size) pair, create a struct member. Right now we completely ignore the
    # possibility that some members will overlap (for various reasons; it's actually more common
    # than I initially thought, though I haven't investigated why).
    # TODO: In the future we should address this by either automatically generating sub-unions or
    # choosing the most appropriate member when permissible (e.g. (0, 8), (0, 2), (4, 4) might
    # create (0, 2), (2, 2), (4, 4)). I think the most reasonable default policy is to create the
    # biggest members that satisfy all accesses.
    success = True
    for offset, size in accesses:
        if offset < base:
            continue
        member = field_name(offset)
        ret = idau.struct_add_word(sid, member, offset - base, size)
        if ret != 0:
            if ret == idc.STRUC_ERROR_MEMBER_OFFSET:
                _log(2, 'Could not add {}.{} for access ({}, {})', name,
                     member, offset, size)
            else:
                success = False
                _log(1, 'Could not add {}.{} for access ({}, {}): {}', name,
                     member, offset, size, ret)
    return success
Example #9
0
def Structs():
    """
    Get a list of structures

    @return: List of tuples (idx, sid, name)
    """
    idx = idc.GetFirstStrucIdx()
    while idx != idaapi.BADADDR:
        sid = idc.GetStrucId(idx)
        yield (idx, sid, idc.GetStrucName(sid))
        idx = idc.GetNextStrucIdx(idx)
Example #10
0
File: hooks.py Project: Spl3en/ipad
 def struc_cmt_changed(self, sid):
     idx = idc.GetStrucIdx(sid)
     sname = idc.GetStrucName(sid)
     cmt = idc.GetEnumCmt(sid, 0)
     self.ctrl._handle_action({
         'action': 'struct_cmt_changed',
         'struct': idx,
         'sname': sname,
         'cmt': cmt
     })
     return 0
Example #11
0
File: hooks.py Project: Spl3en/ipad
 def struc_member_deleted(self, struct, mid, moff):
     sid = struct.id
     idx = idc.GetStrucIdx(sid)
     sname = idc.GetStrucName(sid)
     self.ctrl._handle_action({
         'action': 'struct_member_deleted',
         'struct': idx,
         'sname': sname,
         'member': mid,
         'off': moff
     })
     return 0
Example #12
0
File: hooks.py Project: Spl3en/ipad
 def struc_expanded(self, struct):
     sid = struct.id
     sname = idc.GetStrucName(sid)
     size = idc.GetStrucSize(sid)
     idx = idc.GetStrucIdx(sid)
     self.ctrl._handle_action({
         'action': 'struct_expanded',
         'struct': idx,
         'sname': sname,
         'size': size
     })
     return 0
Example #13
0
File: hooks.py Project: Spl3en/ipad
 def struc_created(self, struct):
     ### we have to maintain our own struct db
     ## becuse ida sux...
     sname = idc.GetStrucName(struct)
     union = idc.IsUnion(struct)
     idx = idc.GetStrucIdx(struct)
     self.ctrl._handle_action({
         'action': 'struct_created',
         'struct': idx,
         'sname': sname,
         'union': union
     })
     self.ctrl.db.struct_add(struct, idx)
     return 0
Example #14
0
File: hooks.py Project: Spl3en/ipad
 def struc_member_renamed(self, struct, membr):
     sid = struct.id
     mid = membr.id
     moff = membr.soff
     idx = idc.GetStrucIdx(sid)
     sname = idc.GetStrucName(sid)
     mname = idc.GetMemberName(sid, moff)
     self.ctrl._handle_action({
         'action': 'struct_member_renamed',
         'struct': idx,
         'member': mid,
         'sname': sname,
         'mname': mname,
         'off': moff
     })
     return 0
Example #15
0
 def __init__(self, name):
     if isinstance(name, (int, long)):
         name = str(name)
     self.align = 8
     self.name = name
     self.id = idc.GetStrucIdByName(name)
     if self.id == idc.BADADDR:
         try:
             self.id = int(name)
             self.name = idc.GetStrucName(self.id)
             if not self.name:
                 raise ""
         except Exception:
             raise Struct.StructNotFoundError(name)
     self._xrefs = None
     self._fields = None
     self._inst = None
     self._showFields = None
Example #16
0
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 = idc.GetStrucIdByName(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 idc.GetStrucName(sid) is None:
            raise ValueError('Invalid struc id {}'.format(sid))
    # Iterate through the members and add them to the struct.
    union = idc.IsUnion(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, idc.GetStrucSize(sid))
    return struct
Example #17
0
def struct_member_error(err, sid, name, offset, size):
    """Create and format a struct member exception.

    Args:
        err: The error value returned from struct member creation
        sid: The struct id
        name: The member name
        offset: Memeber offset
        size: Member size

    Returns:
        A ``SarkErrorAddStructMemeberFailed`` derivative exception, with an
        informative message.
    """
    exception, msg = STRUCT_ERROR_MAP[err]
    struct_name = idc.GetStrucName(sid)
    return exception(
        ('AddStructMember(struct="{}", member="{}", offset={}, size={}) '
         'failed: {}').format(struct_name, name, offset, size, msg))
Example #18
0
File: hooks.py Project: Spl3en/ipad
 def struc_member_created(self, struct, membr):
     sid = struct.id
     mid = membr.id
     moff = membr.soff
     flag = membr.flag
     size = idc.GetMemberSize(sid, moff)
     sname = idc.GetStrucName(sid)
     mname = idc.GetMemberName(sid, moff)
     idx = idc.GetStrucIdx(sid)
     self.ctrl._handle_action({
         'action': 'struct_member_created',
         'struct': idx,
         'member': mid,
         'sname': sname,
         'mname': mname,
         'off': moff,
         'flag': flag,
         'size': size
     })
     return 0
Example #19
0
 def add_auto_comment(self, ea, text):
     if ea is not None:
         prefix = ""
         if idaapi.get_struc(ea) is not None:
             if idc.GetStrucIdx(ea) == idc.BADADDR:
                 prefix = "stackframe '%s'" % idc.GetFunctionName(
                     idaapi.get_func_by_frame(ea))
             else:
                 prefix = "structure '%s'" % idc.GetStrucName(ea)
         elif idc.GetEnumIdx(ea) != idc.BADADDR:
             prefix = "enum '%s'" % idc.GetEnumName(ea)
         else:
             foffset = idc.GetFuncOffset(ea)
             if foffset is None:
                 prefix = yatools.ea_to_hex(ea)
             else:
                 prefix = "%s,%s" % (yatools.ea_to_hex(ea), foffset)
         self.auto_comments.add((prefix, text))
     else:
         self.auto_comments.add(("", text))
Example #20
0
    def save_strucs(self, memory_exporter):
        """
        Structures : export modified structures and delete those who have been deleted
        """
        for struc_id in self.structures_to_process:
            self.ida_model.clear_exported_struc_enum_id(struc_id)
            sidx = idc.GetStrucIdx(struc_id)
            if sidx is None or sidx == idc.BADADDR:
                # it is a deleted structure or a stackframe
                # in this last case we need to export the parent (function)
                eaFunc = idaapi.get_func_by_frame(struc_id)
                if eaFunc != idc.BADADDR:
                    # OK, it is a stackframe
                    self.ida_model.accept_struc(
                        memory_exporter, 0, struc_id, ya.OBJECT_TYPE_STACKFRAME, ya.OBJECT_TYPE_STACKFRAME_MEMBER,
                        stackframe_func_addr=eaFunc)
                    self.ida_model.accept_ea(memory_exporter, 0, eaFunc)
                else:
                    # it is a deleted structure
                    self.ida_model.accept_deleted_struc(memory_exporter, struc_id)
            else:

                self.ida_model.accept_struc(memory_exporter, 0, struc_id)

        logger.debug("Walking members")
        """
        Structure members : update modified ones, and remove deleted ones
        We iterate over members :
            -if the parent struc has been deleted, delete the member
            -otherwise, detect if the member has been updated or removed
                -updated : accept struc_member + accept_struc if not already exported!
                -removed : accept struc_member_deleted
        """
        for (struc_id, member_set) in self.strucmember_to_process.iteritems():
            ida_struc = idaapi.get_struc(struc_id)
            logger.debug("Walking struc 0x%08X" % struc_id)
            sidx = idc.GetStrucIdx(struc_id)
            is_stackframe = False
            struc_deleted = False
            if sidx is None or sidx == idc.BADADDR:
                f = idaapi.get_func_by_frame(struc_id)
                if f is not None and f != idc.BADADDR:
                    is_stackframe = True
                else:
                    struc_deleted = True

            if is_stackframe:
                strucmember_type = ya.OBJECT_TYPE_STACKFRAME_MEMBER
                struc_name = None
                struc_type = ya.OBJECT_TYPE_STACKFRAME
                eaFunc = idaapi.get_func_by_frame(struc_id)
                stackframe_func_addr = eaFunc
                func = idaapi.get_func(eaFunc)
                self.ida_model.accept_function(memory_exporter, 0, eaFunc, func)
            else:
                strucmember_type = ya.OBJECT_TYPE_STRUCT_MEMBER
                struc_type = ya.OBJECT_TYPE_STRUCT
                stackframe_func_addr = None
                if not struc_deleted:
                    struc_name = idc.GetStrucName(struc_id)

            if struc_deleted:
                # The structure has been deleted : we need to delete the members
                # Note: at first sight, it is not a stackframe
                # TODO: handle function->stackframe deletion here
                for (member_id, offset) in member_set:
                    self.ida_model.accept_deleted_strucmember(memory_exporter, struc_id, None, offset)
            else:
                # The structure or stackframe has been modified
                is_union = ida_struc.is_union()

                for (member_id, offset) in member_set:
                    ida_member = idaapi.get_member(ida_struc, offset)
                    if ida_member is None:
                        new_member_id = -1
                    else:
                        new_member_id = ida_member.id
                    logger.debug("exporting member %s at offset 0x%02X (mid=0x%016X)" %
                                 (strucmember_type, offset, member_id))
                    self.ida_model.clear_exported_struc_member_id(new_member_id)

                    if new_member_id == -1:
                        # the member has been deleted : delete it
                        self.ida_model.accept_deleted_strucmember(
                            memory_exporter, struc_id, struc_name, offset, struc_type, strucmember_type)
                    elif offset > 0 and idc.GetMemberId(struc_id, offset - 1) == new_member_id:
                        # the member was deleted, and replaced by a member starting above it
                        self.ida_model.accept_deleted_strucmember(
                            memory_exporter, struc_id, struc_name, offset, struc_type, strucmember_type)
                    elif new_member_id != member_id:
                        # the member has been deleted and later recreated
                        name = idaapi.get_member_name(new_member_id)
                        self.ida_model.accept_struc_member(
                            memory_exporter, 0, ida_struc, struc_id, is_union, offset, struc_name, name, struc_type,
                            strucmember_type, stackframe_func_addr=stackframe_func_addr)
                    else:
                        # the member has just been modified
                        name = idaapi.get_member_name(new_member_id)
                        logger.debug("exporting member %s (%s) at offset 0x%02X (mid=0x%016X)" %
                                     (strucmember_type, name, offset, member_id))
                        self.ida_model.accept_struc_member(
                            memory_exporter, 0, ida_struc, struc_id, is_union, offset, struc_name, name, struc_type,
                            strucmember_type, stackframe_func_addr=stackframe_func_addr)
Example #21
0
def dispatch(args):

    ## dispatch args....
    class A():
        pass

    a = A()
    for name in args:
        setattr(a, name, args[name])
    del args

    ### dispatch idp events
    if a.action == 'rename':
        debug('[*] renaming %s to %s @ %x', a.old_name, a.new_name, a.ea)
        idc.MakeNameEx(a.ea, str(a.new_name), idaapi.SN_NOWARN)
        return

    ## dispatch idb events
    if a.action == 'cmt_changed':
        if not a.cmt: a.cmt = ''
        _pcmt = a.cmt if len(a.cmt) < 10 else a.cmt[:10] + '...'
        debug('[*] cmt changed @ %X (rep:%s) - %s', a.ea, a.rep, _pcmt)
        if a.rep: idc.MakeRptCmt(a.ea, str(a.cmt))
        else: idc.MakeComm(a.ea, str(a.cmt))

    if a.action == 'struct_created':
        debug('[*] Struct %s created with id %x', a.sname, a.struct)
        print idc.AddStrucEx(-1, str(a.sname), a.union)

    if a.action == 'struct_deleted':
        sid = idc.GetStrucId(a.struct)
        sname = idc.GetStrucName(sid)
        debug('[*] Struct(%x) %s deleted', a.struct, sname)
        idc.DelStruc(sid)

    if a.action == 'struct_renamed':
        sid = idc.GetStrucId(a.struct)
        sname = idc.GetStrucName(sid)
        debug('[*] Struct(%d - %x) renamed from %s to %s', a.struct, sid,
              sname, a.sname)
        idc.SetStrucName(sid, str(a.sname))

    if a.action == 'struct_cmt_changed':
        sid = idc.GetStrucId(a.struct)
        debug('[*] Struct(%d - %x) %s - cmt changed', a.struct, sid, a.sname)
        idc.SetStrucComment(sid, a.cmt, 0)

    if a.action == 'struct_expanded':
        pass

    if a.action == 'struct_member_created':
        pass

    if a.action == 'struct_member_deleted':
        pass
    if a.action == 'struct_member_renamed':
        pass
    if a.action == 'struct_member_changed':
        pass
    if a.action == 'struct_member_':
        pass
    if a.action == 'struct_member_created':
        pass
    if a.action == 'struct_member_created':
        pass

    # if a.action == 'struct_expanded':
    #     debug('

    return 0
Example #22
0
def name(id, name=None):
    if name is None:
        return idc.GetStrucName(id)
    return idc.SetStrucName(id, name)
Example #23
0
 def get_name(self):
     return idc.GetStrucName(self.sid) or "{no name}"
Example #24
0
    def clear_struc_fields(self,
                           struc_id,
                           struc_size,
                           xref_keys,
                           is_union=False,
                           member_type=ya.OBJECT_TYPE_STRUCT_MEMBER,
                           name_offset=0):

        idc.BeginTypeUpdating(idc.UTP_STRUCT)
        last_offset = idc.GetLastMember(struc_id)

        # get existing member offsets
        field_offsets = set()
        for (xref_offset, xref_operand) in xref_keys:
            field_offsets.add(xref_offset)

        new_offsets = set()
        struc = idaapi.get_struc(struc_id)
        # create missing members first (prevent from deleting all members)
        for offset in field_offsets:
            member = idaapi.get_member(struc, offset)
            if member is not None and member.soff < offset:
                # we have a member above this member that is too big and contain this member
                # clear it!
                if DEBUG_EXPORTER:
                    logger.debug(
                        "reduce field : set_member_type(0x%08X, 0x%08X), overlapping 0x%08X",
                        struc_id, member.soff, offset)
                idaapi.set_member_type(struc, member.soff, idc.FF_BYTE, None,
                                       1)
                member = idaapi.get_member(struc, offset)

            if member is None or idaapi.get_member_name(member.id) is None:
                new_offsets.add(offset)
                member_name = YaToolIDATools.get_default_struc_member_name(
                    member_type, offset, name_offset)
                if offset == last_offset and offset == struc_size:
                    field_size = 0
                else:
                    field_size = 1
                if DEBUG_EXPORTER:
                    logger.debug(
                        "AddStrucMember(0x%08X, '%s', 0x%08X, idc.FF_BYTE, -1, 0x%08X), name_offset=%d",
                        struc_id, member_name, offset, field_size, name_offset)
                retval = idc.AddStrucMember(struc_id, member_name, offset,
                                            idc.FF_BYTE, -1, field_size)
                if retval != 0:
                    logger.error(
                        "Error %d with idc.AddStrucMember(0x%08X, '%s', 0x%08X,"
                        "idc.FF_BYTE, -1, 0x%08X), name_offset=%d", retval,
                        struc_id, member_name, offset, field_size, name_offset)
            elif DEBUG_EXPORTER:
                logger.debug("Member exists : (0x%08X, '%s', 0x%08X, 0x%08X)",
                             struc_id, idc.GetMemberName(struc_id,
                                                         offset), offset,
                             idc.GetMemberSize(struc_id, offset))

        kept_offsets = field_offsets - new_offsets
        # clear kept members
        # split the loop since we will modify the structure while iterating
        offsets = set()
        for (offset, member_name) in YaToolIDATools.struc_member_list(
                struc_id, is_union):
            offsets.add(offset)

        for offset in offsets:
            if offset in kept_offsets:
                # This member already existed and is kept
                if offset == last_offset and offset == struc_size:
                    # this is the last field, and it is a variable sized structure
                    field_size = 0
                else:
                    field_size = 1
                if member_type == ya.OBJECT_TYPE_STRUCT_MEMBER:
                    strucmember_id = self.hash_provider.get_struc_member_id(
                        struc_id, offset)
                elif member_type == ya.OBJECT_TYPE_STACKFRAME_MEMBER:
                    strucmember_id = self.hash_provider.get_stackframe_member_object_id(
                        struc_id, offset)
                else:
                    logger.error("Bad member_type : %d" % member_type)

                if strucmember_id not in self.strucmember_ids:
                    # It is not necessary to clear the member if it is presnet in the resolved_objects
                    if DEBUG_EXPORTER:
                        logger.debug(
                            "SetStrucmember(0x%08X, None, 0x%08X, idc.FF_BYTE, -1, 0x%08X, name_offset=%s)",
                            struc_id, offset, field_size, name_offset)
                    YaToolIDATools.SetStrucmember(struc_id,
                                                  None,
                                                  offset,
                                                  idc.FF_BYTE,
                                                  -1,
                                                  field_size,
                                                  member_type=member_type,
                                                  name_offset=name_offset)

                    idc.SetMemberComment(struc_id, offset, "", 0)
                    idc.SetMemberComment(struc_id, offset, "", 1)
            elif offset not in new_offsets:
                if (member_type != ya.OBJECT_TYPE_STACKFRAME_MEMBER
                        or not idaapi.is_special_member(
                            idc.GetMemberId(struc_id, offset))):
                    if DEBUG_EXPORTER:
                        logger.debug(
                            "DelStrucMember(0x%08X, 0x%08X)  (=%s:%s)",
                            struc_id, offset, idc.GetStrucName(struc_id),
                            idc.GetMemberName(struc_id, offset))
                    idc.DelStrucMember(struc_id, offset)
            else:
                # in new_offsets : just created
                pass
        idc.EndTypeUpdating(idc.UTP_STRUCT)
Example #25
0
    def make_struc_member(self,
                          object_version,
                          address,
                          member_type=ya.OBJECT_TYPE_STRUCT_MEMBER):
        struc_object_id = object_version.get_parent_object_id()

        struc_id = 0
        try:
            struc_id = self.struc_ids[struc_object_id]
        except:
            return
        is_union = struc_id in self.union_ids

        offset = address

        if is_union:
            last_offset = idc.GetLastMember(struc_id)
            if last_offset == idc.BADADDR:
                last_offset = -1
            if last_offset < offset:
                for i in xrange(last_offset + 1, offset + 1):
                    idc.AddStrucMember(struc_id, "yaco_filler_%d" % i, 0,
                                       idc.FF_BYTE | idc.FF_DATA, -1, 1)
                    # ensure that 'offset' fields are present

        member_size = object_version.get_size()
        member_name = object_version.get_name()

        flags = object_version.get_object_flags()
        if idc.isStruct(flags):
            # if the sub field is a struct, it must have a single Xref field with the struct object id
            try:
                sub_struc_object_id = object_version.getXRefIdsAt(0, 0)[0]
                sub_struc_id = self.struc_ids[sub_struc_object_id]

                #                 logger.debug("%20s: adding sub member at offset 0x%08X,
                #                               size=0x%08X (sub=0x%.016X, size=0x%08X) with name %s" %
                #                             (
                #                                 idc.GetStrucName(struc_id), offset, member_size, sub_struc_id,
                #                                               idc.GetStrucSize(sub_struc_id), object_version.get_name()
                #                             ))

                sub_struc_size = idc.GetStrucSize(sub_struc_id)
                if sub_struc_size == 0:
                    logger.error(
                        "%20s: adding sub member at offset 0x%08X, size=0x%08X "
                        "(sub=0x%.016X, size=0x%08X) with name %s : sub struc size is ZERO"
                        % (idc.GetStrucName(struc_id), offset, member_size,
                           sub_struc_id, idc.GetStrucSize(sub_struc_id),
                           object_version.get_name()))

                else:
                    nitems = member_size / sub_struc_size

                    YaToolIDATools.SetStrucmember(struc_id, member_name,
                                                  offset, flags, sub_struc_id,
                                                  nitems)

            except KeyError:
                logger.error(
                    "Error while looking for sub struc in struc %s, offset 0x%08X (field name='%s')"
                    % (self.hash_provider.hash_to_string(struc_object_id),
                       offset, object_version.get_name()))
                traceback.print_exc()
        elif idc.isEnum0(flags):
            # an enum is applied here
            try:
                sub_enum_object_id = object_version.getXRefIdsAt(0, 0)[0]
                sub_enum_id = self.enum_ids[sub_enum_object_id]

                name_ok = idc.SetMemberName(struc_id, offset, member_name)
                if name_ok is not True:
                    logger.debug(
                        "Error while setting member name (enum) : "
                        "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X"
                        % (name_ok, idc.GetStrucName(struc_id), member_name,
                           offset, flags, member_size, sub_struc_id))
                else:
                    sub_enum_size = idc.GetEnumWidth(sub_enum_id)
                    if sub_enum_size == 0:
                        sub_enum_size = member_size

                    nitems = member_size / sub_enum_size
                    ret = idc.SetMemberType(struc_id, offset, flags,
                                            sub_enum_id, nitems)
                    if ret == 0:
                        logger.debug(
                            "Error while setting member type (enum) : "
                            "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X"
                            % (ret, idc.GetStrucName(struc_id), member_name,
                               offset, flags, member_size, sub_struc_id))

            except KeyError:
                logger.error(
                    "Error while looking for sub enum in struc %s, offset 0x%08X (field name='%s')"
                    % (struc_object_id, offset, member_name))
                traceback.print_exc()

        else:
            #             logger.debug("%20s: adding member at offset 0x%08X, size=0x%08X with name %s" %
            #                         (
            #                         idc.GetStrucName(struc_id), offset, member_size, object_version.get_name()
            #                         ))
            tid = -1
            if idc.isASCII(flags):
                logger.debug(
                    "object: %s : %s" % (self.hash_provider.hash_to_string(
                        object_version.get_id()), object_version.get_name()))
                try:
                    tid = object_version.get_string_type()
                except KeyError:
                    tid = idc.ASCSTR_C

            name_ok = idc.SetMemberName(struc_id, offset, member_name)
            if name_ok is not True:
                logger.debug(
                    "Error while setting member name :" +
                    " (struc_id=0x%08X, struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)"
                    % (struc_id, idc.GetStrucName(struc_id), member_name,
                       offset, flags, member_size))
            else:
                item_size = YaToolIDATools.get_field_size(flags, tid)
                nitems = member_size / item_size
                # IDA BUG : 4-byte chars are stored as 2 double words, thus me must
                # multiply nitem by 2!
                ret = idc.SetMemberType(struc_id, offset, flags, tid, nitems)
                if ret == 0:
                    logger.debug(
                        "Error while setting member type :" +
                        " (struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)"
                        % (idc.GetStrucName(struc_id), member_name, offset,
                           flags, member_size))

        try:
            repeatable_headercomment = self.sanitize_comment_to_ascii(
                object_version.get_header_comment(True))
            idc.SetMemberComment(struc_id, offset, repeatable_headercomment, 1)
        except KeyError:
            pass

        try:
            nonrepeatable_headercomment = self.sanitize_comment_to_ascii(
                object_version.get_header_comment(False))
            idc.SetMemberComment(struc_id, offset, nonrepeatable_headercomment,
                                 0)
        except KeyError:
            pass

        member_id = idc.GetMemberId(struc_id, offset)

        self.set_struct_member_type(object_version, member_id)
        if object_version.get_type() == ya.OBJECT_TYPE_STRUCT_MEMBER:
            self.strucmember_ids[object_version.get_id()] = member_id