Exemple #1
0
    def handle_set_struct(self):
        if self.edit_class is None:
            return

        default_struct_name = idc.get_struc_name(self.edit_class.struct_id)    \
                              if self.edit_class.struct_id != idc.BADADDR else \
                              self.edit_class.name

        dlg = ChooseStructDialog(default_struct_name, has_none_btn=True)
        if dlg.exec_() != QtWidgets.QDialog.Accepted:
            return

        if dlg.struct_id == self.edit_class.struct_id:
            return

        db = database.get()
        if dlg.struct_id in db.classes_by_struct_id:
            idaapi.warning(
                'The struct "%s" is already linked to the class "%s"' %
                (idc.get_struc_name(
                    dlg.struct_id), b.classes_by_struct_id[dlg.struct_id]))
            return

        delete_orphaned = False
        if self.edit_class.struct_id != idc.BADADDR:
            delete_orphaned = util.ask_yes_no(
                'Do you want to delete the orphaned class', False)

        self.edit_class.set_struct_id(dlg.struct_id, delete_orphaned)
        self.update_fields()
    def rename(self, new_name):
        old_name = self.name

        db = database.get()
        del db.classes_by_name[old_name]
        db.classes_by_name[new_name] = self

        self.name = new_name

        # Try to rename the struct
        if self.struct_id != idc.BADADDR:
            struct_name = idc.get_struc_name(self.struct_id)
            if struct_name == Class.s_safe_name(old_name):
                idc.set_struc_name(self.struct_id, self.safe_name())

        # Rename ctors and dtors
        for vm in self.vmethods:
            if vm.name == old_name:
                vm.name = new_name
            if vm.name == '~' + old_name:
                vm.name = '~' + new_name
        for m in self.methods:
            if m.name == old_name:
                m.name = new_name
            if m.name == '~' + old_name:
                m.name = '~' + new_name

        self.refresh()
Exemple #3
0
def Structs():
    """
    Get a list of structures

    @return: List of tuples (idx, sid, name)
    """
    idx  = idc.get_first_struc_idx()
    while idx != ida_idaapi.BADADDR:
        sid = idc.get_struc_by_idx(idx)
        yield (idx, sid, idc.get_struc_name(sid))
        idx = idc.get_next_struc_idx(idx)
    def unlink_struct(self, delete_orphaned=False):
        if self.struct_id == idc.BADADDR:
            return

        del database.get().classes_by_struct_id[self.struct_id]

        if delete_orphaned:
            idc.del_struc(self.struct_id)
        else:
            struct_name = idc.get_struc_name(self.struct_id)
            idc.set_struc_cmt(self.struct_id, 'Orphaned from %s' % self.name, False)
            idc.set_struc_name(self.struct_id, '%s_orphaned' % struct_name)

        self.struct_id = idc.BADADDR
Exemple #5
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
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.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 idc.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, idc.get_struc_size(sid))
    return struct
Exemple #7
0
    def update_fields(self):
        if self.edit_class is None:
            self.setDisabled(True)
            self.name.setText('Name: -')
            self.base_class.setText('Base class: -')
            self.derived_classes.setText('Derived classes: -')
            self.struct.setText('Struct: -')
            self.vtable_range.setText('VTable: -')
            self.vtable.setRowCount(0)
            self.methods.setRowCount(0)

        else:
            self.setEnabled(True)
            self.name.setText('Name: %s' % self.edit_class.name)
            self.base_class.setText(
                'Base class: %s' %
                (self.edit_class.base.name
                 if self.edit_class.base is not None else 'None'))

            derived_classes_txts = []
            for dc in self.edit_class.derived:
                derived_classes_txts.append(dc.name)
            derived_classes_txt = ', '.join(derived_classes_txts)
            if not derived_classes_txt:
                derived_classes_txt = 'None'
            self.derived_classes.setText('Derived classes: %s' %
                                         derived_classes_txt)

            if self.edit_class.struct_id == idc.BADADDR:
                struct_txt = 'Not set'
            else:
                struct_txt = '%s (%d)' % (
                    idc.get_struc_name(self.edit_class.struct_id),
                    idc.get_struc_idx(self.edit_class.struct_id))
            self.struct.setText('Struct: %s' % struct_txt)

            if self.edit_class.vtable_start is None or self.edit_class.vtable_end is None:
                vtable_range_txt = 'Not set'
            else:
                vtable_range_txt = '0x%X - 0x%X' % (
                    self.edit_class.vtable_start, self.edit_class.vtable_end)
            self.vtable_range.setText('VTable: %s' % vtable_range_txt)

            self.vtable.setRowCount(len(self.edit_class.vmethods))
            for idx, vm in enumerate(self.edit_class.vmethods):
                self.vtable.setItem(idx, 0,
                                    QtWidgets.QTableWidgetItem(str(idx)))
                self.vtable.setItem(
                    idx, 1,
                    QtWidgets.QTableWidgetItem((
                        "0x%X" % vm.ea) if vm.ea != idc.BADADDR else '-'))
                self.vtable.setItem(
                    idx, 2, QtWidgets.QTableWidgetItem(vm.get_signature()))
                self.vtable.setItem(idx, 3,
                                    QtWidgets.QTableWidgetItem(vm.type_name()))

            # This way of doing won't work when allowing sorting
            self.methods.setRowCount(len(self.edit_class.methods))
            for idx, m in enumerate(self.edit_class.methods):
                address_item = QtWidgets.QTableWidgetItem(m.ea)
                address_item.setData(QtCore.Qt.DisplayRole, "0x%X" % m.ea)
                address_item.setData(QtCore.Qt.UserRole, m)
                self.methods.setItem(idx, 0, address_item)
                self.methods.setItem(
                    idx, 1, QtWidgets.QTableWidgetItem(m.get_signature()))