from PyQt5 import QtGui, QtCore, QtWidgets import idaapi import idautils import idc import DIE.Lib.DIEDb import DIE.UI.FunctionViewEx class ValueView(idaapi.PluginForm): """ DIE Value View """ def __init__(self): super(ValueView, self).__init__() self.die_db = None self.function_view = None self.highligthed_items = [] def Show(self): return idaapi.PluginForm.Show(self, "Value View", options=idaapi.PluginForm.FORM_PERSIST) def OnCreate(self, form): """ Called when the view is created """ self.die_db = DIE.Lib.DIEDb.get_db() self.function_view = DIE.UI.FunctionViewEx.get_view() # Get parent widget self.parent = self.FormToPyQtWidget(form) self.valueModel = QtGui.QStandardItemModel() self.valueTreeView = QtWidgets.QTreeView() self.valueTreeView.setExpandsOnDoubleClick(False) self.valueTreeView.doubleClicked.connect(self.itemDoubleClickSlot) self._model_builder(self.valueModel) self.valueTreeView.setModel(self.valueModel) # Toolbar self.value_toolbar = QtWidgets.QToolBar() # Value type combobox type_list = [] if self.die_db: type_list = self.die_db.get_all_value_types() type_list.insert(0, "All Values") self.value_type_combo = QtWidgets.QComboBox() self.value_type_combo.addItems(type_list) self.value_type_combo.activated[str].connect(self.on_value_type_combobox_change) self.value_type_label = QtWidgets.QLabel("Value Type: ") self.value_toolbar.addWidget(self.value_type_label) self.value_toolbar.addWidget(self.value_type_combo) # Layout layout = QtWidgets.QGridLayout() layout.addWidget(self.value_toolbar) layout.addWidget(self.valueTreeView) self.parent.setLayout(layout) def isVisible(self): """ Is valueview visible @return: True if visible, otherwise False """ try: return self.valueTreeView.isVisible() except: return False def _model_builder(self, model): """ Build the function model. @param model: QStandardItemModel object """ model.clear() # Clear the model root_node = model.invisibleRootItem() model.setHorizontalHeaderLabels(("Type", "Score", "Value", "Description", "Raw Value")) if self.die_db is None: return value_list = self.die_db.get_all_values() for value in value_list: value_data_item_list = self._make_value_item(value) root_node.appendRow(value_data_item_list) def _make_value_type_item(self, type): """ Make a value item type @param type: item type """ item_value_type = QtGui.QStandardItem(type) item_value_type.setEditable(False) return [item_value_type] def _make_value_item(self, value): """ Make a value model item @param value: dbParsed_Value object @return: a list of items for this row. """ null_item = QtGui.QStandardItem() null_item.setEditable(False) null_item.setData(value.type, role=DIE.UI.ValueType_Role) null_item.setData(value.__hash__(), role=DIE.UI.Value_Role) item_value_score = QtGui.QStandardItem(str(value.score)) item_value_score.setEditable(False) item_value_data = QtGui.QStandardItem(value.data) ea_list = self.die_db.get_parsed_value_contexts(value) item_value_data.setData(ea_list, role=DIE.UI.ContextList_Role) item_value_data.setEditable(False) item_value_desc = QtGui.QStandardItem(value.description) item_value_desc.setEditable(False) item_value_raw = QtGui.QStandardItem(value.raw) item_value_raw.setEditable(False) return [null_item, item_value_score, item_value_data, item_value_desc, item_value_raw] ############################################################################################### # Highlight Items # ############################################################################################### def highlight_item(self, item): """ Highlight a single item @param item: module item """ try: item.setBackground(QtCore.Qt.yellow) cur_font = item.font() cur_font.setBold(True) item.setFont(cur_font) except Exception as ex: idaapi.msg("Error while highlighting item: %s\n" % ex) def highlight_item_row(self, item): """ highlight the entire row containing a table item @param item: table item """ try: if not item.index().isValid(): return parent = item.parent() if parent is None: parent = item if not parent.hasChildren(): self.highlight_item(parent) return row = item.row() column_num = parent.columnCount() for column in xrange(0, column_num): if self.valueModel.hasIndex(row, column, parent.index()): cur_index = self.valueModel.index(row, column, parent.index()) self.highlight_item(self.valueModel.itemFromIndex(cur_index)) persistent_index = QtCore.QPersistentModelIndex(cur_index) self.highligthed_items.append(persistent_index) except Exception as ex: idaapi.msg("Error while highlighting item row: %s\n" % ex) def clear_highlights(self): """ Clear all highlighted items @return: """ try: self.valueTreeView.collapseAll() for persistent_index in self.highligthed_items: if persistent_index.isValid(): item = self.valueModel.itemFromIndex(persistent_index) item.setBackground(QtCore.Qt.white) cur_font = item.font() cur_font.setBold(False) item.setFont(cur_font) self.highligthed_items = [] except Exception as ex: idaapi.msg("Error while clearing highlights: %s\n" % ex) ############################################################################################### # Find Items # ############################################################################################### def find_value(self, value): """ Find and highlight a function in current module @param value object (of type dbParsed_Value) """ try: root_index = self.valueModel.index(0, 0) if not root_index.isValid(): return matched_items = self.valueModel.match(root_index, DIE.UI.Value_Role, value.__hash__(), -1, QtCore.Qt.MatchRecursive | QtCore.Qt.MatchExactly) for index in matched_items: if not index.isValid(): continue item = self.valueModel.itemFromIndex(index) self.valueTreeView.expand(index) self.valueTreeView.scrollTo(index, QtWidgets.QAbstractItemView.ScrollHint.PositionAtTop) self.highlight_item_row(item) except Exception as ex: idaapi.msg("Error while finding value: %s\n" % ex) ############################################################################################### # Slots # ############################################################################################### #@QtCore.Slot(QtCore.QModelIndex) @QtCore.pyqtSlot(QtCore.QModelIndex) def itemDoubleClickSlot(self, index): """ TreeView DoubleClicked Slot. @param index: QModelIndex object of the clicked tree index item. @return: """ func_context_list = index.data(role=DIE.UI.ContextList_Role) try: if self.function_view is None: self.function_view = DIE.UI.FunctionViewEx.get_view() if func_context_list is not None and len(func_context_list) > 0: if not self.function_view.isVisible(): self.function_view.Show() self.function_view.find_context_list(func_context_list) except Exception as ex: idaapi.msg("Error while loading function view: %s\n" % ex) def on_value_type_combobox_change(self, value_type): """ Value type Combobox item changed slot. """ if value_type == "All Values": if not self.valueTreeView.model() is self.valueModel: self.valueTreeView.setModel(self.valueModel) return valuetypeProxyModel = QtCore.QSortFilterProxyModel() valuetypeProxyModel.setFilterRole(DIE.UI.ValueType_Role) valuetypeProxyModel.setFilterRegExp(value_type) valuetypeProxyModel.setSourceModel(self.valueModel) self.valueTreeView.setModel(valuetypeProxyModel) # Singelton _value_view = None def initialize(): global _value_view _value_view = ValueView() def get_view(): return _value_view