def _make_func_occur_item(self, function_context, occur_num): """ Build a tree item for function occurrence (level-2) @param function_context: a dbFunction_Context object @param occur_num: occurrence number @return: QStandradItemModel item for the function occurrence """ func_occur_txt = "Occur %s" % str(occur_num) item_func_context = QtGui.QStandardItem(func_occur_txt) item_func_context.setColumnCount(5) item_func_context.setEditable(False) item_func_context.setData(function_context, role=DIE.UI.FunctionContext_Role) item_func_context.setData( id(function_context), role=DIE.UI.ContextId_Role) # Used for module look-ups item_func_context.setData(self._make_thread_id_data( function_context.thread_id), role=DIE.UI.ThreadId_Role) item_list = [ item_func_context, QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem() ] return item_list
def __init__(self, *args, **kwargs): super(Popup, self).__init__(*args, **kwargs) pm = QtGui.QPixmap(IDABUDDY_AVATAR_PATH) transform = QtGui.QTransform() transform.scale(0.5, 0.5) self.pm = pm.transformed(transform) self.slide = Slide(self) self.image_label = QtWidgets.QLabel(self.slide) self.image_label.setPixmap(self.pm) self.image_label.setFixedSize(self.pm.size()) self.image_label.setAlignment(QtCore.Qt.AlignTop) self.slide.initialize() self.talk_bubble = TalkBubble(self) self.talk_bubble.move(TALKBUBBLE_X_MOVE, TALKBUBBLE_Y_MOVE) self.talk_bubble.hide() self.slide.move(size_to_point(self.talk_bubble.size())) self.setFixedSize(self.talk_bubble.size() + self.slide.size() + get_extra_size()) connect_method_to_signal(self.talk_bubble, 'linkActivated(QString)', self.linkActivatedHandler) self._handlers = {} self._default_handler = None
def _make_function_item(self, function): """ Build a tree item for a function name (level-0) @param function: dbFunction object @return: QStandradItemModel item for the function """ function_txt = "%s" % function.function_name item_function = QtGui.QStandardItem(self.die_icons.icon_function, function_txt) item_function.setData(function, role=DIE.UI.Function_Role) function_count = self.die_db.count_function_occurs(function) item_function_count = QtGui.QStandardItem(str(function_count)) item_function_count.setEditable(False) item_function.setEditable(False) item_list = [ item_function, item_function_count, QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem() ] return item_list
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 ]
def _make_model_headers(self, model): """ Set the model horizontal header data @param model: the QStandardItemModel which headers should be set """ ### Function Header item_header = QtGui.QStandardItem("Function") item_header.setToolTip("Function Name") model.setHorizontalHeaderItem(0, item_header) ### Call number header item_header = QtGui.QStandardItem("#") item_header.setToolTip("Number of calls preformed to this function") model.setHorizontalHeaderItem(1, item_header) ### Indirect Header item_header = QtGui.QStandardItem("I") item_header.setToolTip("Indirect Call") model.setHorizontalHeaderItem(2, item_header) ### Indirect Header item_header = QtGui.QStandardItem("N") item_header.setToolTip("New Function") model.setHorizontalHeaderItem(3, item_header) ### Indirect Header item_header = QtGui.QStandardItem("Type") item_header.setToolTip("Argument Type") model.setHorizontalHeaderItem(4, item_header) ### New Function Header item_header = QtGui.QStandardItem("Name") item_header.setToolTip("Argument Name") model.setHorizontalHeaderItem(5, item_header) ### Call Value Icon Header item_header = QtGui.QStandardItem("") model.setHorizontalHeaderItem(6, item_header) ### Call Value Header item_header = QtGui.QStandardItem("Call Value") item_header.setToolTip("Argument`s value on function call") model.setHorizontalHeaderItem(7, item_header) ### Return Value Icon Header item_header = QtGui.QStandardItem("") model.setHorizontalHeaderItem(8, item_header) ### Return Value Header item_header = QtGui.QStandardItem("Return Value") item_header.setToolTip("Argument`s value on function return") model.setHorizontalHeaderItem(9, item_header)
def _make_function_ea_item(self, function_context): """ Build a tree item for a function_ea node (level-1) @param function_context: a dbFunction_Context object @return: QStandradItemModel item for the function context """ calling_function_start = None with ignored(sark.exceptions.SarkNoFunction): calling_function_start = sark.Function( function_context.calling_ea).startEA if calling_function_start is not None: call_offset = function_context.calling_ea - calling_function_start func_ea_txt = "%s+%s" % (function_context.calling_func_name, hex(call_offset)) else: func_ea_txt = "[%s]:%s" % (function_context.calling_func_name, hex(function_context.calling_ea)) item_func_context_ea = QtGui.QStandardItem(func_ea_txt) item_func_context_ea.setEditable(False) item_func_context_ea.setData(hex(function_context.calling_ea), role=QtCore.Qt.ToolTipRole) item_func_context_ea.setData(function_context, role=DIE.UI.FunctionContext_Role) item_func_context_ea.setData( id(function_context), role=DIE.UI.ContextId_Role) # Used for module look-ups item_func_is_indirect = QtGui.QStandardItem() item_func_is_indirect.setEditable(False) if function_context.is_indirect: item_func_is_indirect.setIcon(self.die_icons.icon_v) item_func_is_new = QtGui.QStandardItem() item_func_is_new.setEditable(False) if function_context.is_new_func: item_func_is_new.setIcon(self.die_icons.icon_v) item_list = [ item_func_context_ea, QtGui.QStandardItem(), item_func_is_indirect, item_func_is_new, QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem() ] return item_list
def _make_nonexec_function_time(self, function_name): """ Build a tree item for a function name (for a non-executed function) @type: String @param function_name: Function name @return: """ item_function = QtGui.QStandardItem(self.die_icons.icon_function, function_name) item_function_count = QtGui.QStandardItem("0") item_function_count.setEditable(False) item_function.setEditable(False) item_list = [item_function, item_function_count] return 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 highlight_item(self, item): """ Highlight a single item @param item: module item """ try: item.setBackground(QtGui.QColor('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 load_icon(self, icon_path): """ Load a single icon @param icon_path: full path to the icon file @return: the loaded icon object or None """ icon_path = os.path.join(os.path.dirname(__file__), "..", "icons", icon_path) try: if os.path.exists(icon_path): return QtGui.QIcon(icon_path) else: return None except: return None
def initUI(self): config = DIE.Lib.DieConfig.get_config() self.setFixedSize(400, 330) self.setWindowTitle("About DIE") image = QtGui.QImage(os.path.join(config.icons_path, "logo.png")) pixmap = QtGui.QPixmap.fromImage(image) logo = QtWidgets.QLabel(self) logo.setFixedSize(pixmap.size()) logo.move(0.5 * (self.width() - logo.width()), 20) logo.setPixmap(pixmap) title = QtWidgets.QLabel("DIE", self) title.setAlignment(QtCore.Qt.AlignCenter) font = title.font() font.setPointSize(16) font.setBold(True) title.setFont(font) title.setFixedWidth(400) title.move(0, logo.height() + logo.y() + 20) subtitle = QtWidgets.QLabel("Dynamic IDA Enrichment framework", self) font = subtitle.font() font.setPointSize(14) subtitle.setFont(font) subtitle.setAlignment(QtCore.Qt.AlignCenter) subtitle.setFixedWidth(400) subtitle.move(0, title.height() + title.y() + 10) version = QtWidgets.QLabel("Version 0.1", self) font = subtitle.font() font.setPointSize(12) version.setFont(font) version.setAlignment(QtCore.Qt.AlignCenter) version.setFixedWidth(400) version.move(0, subtitle.height() + subtitle.y() + 30) author = QtWidgets.QLabel( "Written by Yaniv Balmas @ynvb - Check Point Software Technologies", self) font = subtitle.font() font.setPointSize(12) author.setFont(font) author.setAlignment(QtCore.Qt.AlignCenter) author.setFixedWidth(400) author.move(0, version.height() + version.y()) self.show()
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 = form_to_widget(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 clear_highlights(self): """ Clear all highlighted items @return: """ try: self.functionTreeView.collapseAll() for persistent_index in self.highligthed_items: if persistent_index.isValid(): item = self.functionModel.itemFromIndex(persistent_index) item.setBackground(QtGui.QColor('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)
def OnCreate(self, form): """ Called when the plugin form is created """ self.value_view = DIE.UI.ValueViewEx.get_view() self.bp_handler = DIE.Lib.BpHandler.get_bp_handler() self.die_icons = DIE.UI.Die_Icons.get_die_icons() self.die_db = DIE.Lib.DIEDb.get_db() # Get parent widget self.parent = form_to_widget(form) self.functionModel = QtGui.QStandardItemModel() self.functionTreeView = QtWidgets.QTreeView() self.functionTreeView.setExpandsOnDoubleClick(False) #self.functionTreeView.setSortingEnabled(True) delegate = TreeViewDelegate(self.functionTreeView) self.functionTreeView.setItemDelegate(delegate) self.functionTreeView.doubleClicked.connect(self.itemDoubleClickSlot) self._model_builder(self.functionModel) self.functionTreeView.setModel(self.functionModel) self.functionTreeView.setColumnWidth(0, 200) self.functionTreeView.setColumnWidth(1, 20) self.functionTreeView.setColumnWidth(2, 20) self.functionTreeView.setColumnWidth(3, 20) self.functionTreeView.setColumnWidth(4, 250) self.functionTreeView.setColumnWidth(5, 100) self.functionTreeView.setColumnWidth(6, 20) self.functionTreeView.setColumnWidth(7, 450) self.functionTreeView.setColumnWidth(8, 20) self.functionTreeView.setColumnWidth(9, 450) # Context menus self.functionTreeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.functionTreeView.customContextMenuRequested.connect( self.onCustomContextMenu) # Actions self.context_menu_param = None # Parameter to be passed to context menu slots action_exclude_func = QtWidgets.QAction( "Exclude Function", self.functionTreeView, triggered=lambda: self.on_exclude_func(self.context_menu_param)) action_exclude_func_adrs = QtWidgets.QAction( "Exclude All Function Calls", self.functionTreeView, triggered=lambda: self.on_exclude_func_adrs(self.context_menu_param )) action_exclude_ea = QtWidgets.QAction( "Exclude Address", self.functionTreeView, triggered=lambda: self.on_exclude_ea(self.context_menu_param)) action_exclude_library = QtWidgets.QAction( "Exclude Library", self.functionTreeView, triggered=lambda: self.on_exclude_library(self.context_menu_param)) action_value_detail = QtWidgets.QAction( "Inspect Value Details", self.functionTreeView, triggered=lambda: self.on_value_detail(self.context_menu_param)) action_show_callgraph = QtWidgets.QAction( "Show Call-Graph", self.functionTreeView, triggered=lambda: self.on_show_callgraph(self.context_menu_param)) # Function ContextMenu self.function_context_menu = QtWidgets.QMenu(self.functionTreeView) self.function_context_menu.addAction(action_exclude_func) self.function_context_menu.addAction(action_exclude_library) self.function_context_menu.addAction(action_exclude_func_adrs) # Function ea ContextMenu self.ea_context_menu = QtWidgets.QMenu(self.functionTreeView) self.ea_context_menu.addAction(action_exclude_ea) self.ea_context_menu.addAction(action_show_callgraph) # Argument value ContextMenu self.value_context_menu = QtWidgets.QMenu(self.functionTreeView) self.value_context_menu.addAction(action_value_detail) # Therad ComboBox threads = [] if self.die_db is not None: threads = self.die_db.get_thread_list() thread_id_list = [] thread_id_list.append("All Threads") for thread in threads: thread_id_list.append(str(thread.thread_num)) self.thread_id_combo = QtWidgets.QComboBox() self.thread_id_combo.addItems(thread_id_list) self.thread_id_combo.activated[str].connect( self.on_thread_combobox_change) self.thread_id_label = QtWidgets.QLabel("Thread: ") # Toolbar self.function_toolbar = QtWidgets.QToolBar() self.function_toolbar.addWidget(self.thread_id_label) self.function_toolbar.addWidget(self.thread_id_combo) # Grid layout = QtWidgets.QGridLayout() layout.addWidget(self.function_toolbar) layout.addWidget(self.functionTreeView) self.parent.setLayout(layout)
def _add_model_arg_value(self, parent, call_value, ret_value, arg_name, arg_type, nest_depth=0): """ Add a debug value @param parent: @param call_value: @param ret_value: @param arg_name: @param arg_type: @return: """ arg_count = parent.rowCount() this_row_item = QtGui.QStandardItem("") this_row_item.setData( parent.data(role=DIE.UI.ThreadId_Role), role=DIE.UI.ThreadId_Role) # Inherit thread data from parent # Set indentation for argument types (for nested values) arg_ident = " " * nest_depth arg_ident_type = arg_ident + arg_type item_parsed_val_flag_call = QtGui.QStandardItem() item_parsed_val_call = QtGui.QStandardItem() item_parsed_val_flag_ret = QtGui.QStandardItem() item_parsed_val_ret = QtGui.QStandardItem() # Get Call Value if call_value is not None: parsed_vals = self.die_db.get_parsed_values(call_value) this_row_item.setData(parsed_vals, role=DIE.UI.CallValue_Role) if parsed_vals is not None and len(parsed_vals) > 0: is_guessed, best_val = self.die_db.get_best_parsed_val( parsed_vals) item_parsed_val_call = QtGui.QStandardItem(best_val.data) if is_guessed: item_parsed_val_flag_call.setIcon( self.die_icons.icon_question) if len(parsed_vals ) > 1: # If more the 1 item, show a combo-box item_parsed_val_call.setData(parsed_vals, role=DIE.UI.ParsedValuesRole) item_parsed_val_flag_call.setIcon(self.die_icons.icon_more) else: item_parsed_val_call.setData(parsed_vals[0], role=DIE.UI.ParsedValueRole) else: parsed_val_data = "NULL" if call_value.derref_depth == 0: parsed_val_data = "!MAX_DEREF!" if call_value.raw_value is not None: parsed_val_data = hex(call_value.raw_value) if len(call_value.nested_values ) > 0 or call_value.reference_flink is not None: parsed_val_data = "" item_parsed_val_call = QtGui.QStandardItem(parsed_val_data) # Get return value if ret_value is not None: parsed_vals = self.die_db.get_parsed_values(ret_value) this_row_item.setData(parsed_vals, role=DIE.UI.RetValue_Role) # If len(parsed_vals)>1 create a combobox delegate. if parsed_vals: is_guessed, best_val = self.die_db.get_best_parsed_val( parsed_vals) item_parsed_val_ret = QtGui.QStandardItem(best_val.data) if is_guessed: item_parsed_val_flag_ret.setIcon( self.die_icons.icon_question) if len(parsed_vals ) > 1: # If more the 1 item, show a combo-box item_parsed_val_ret.setData(parsed_vals, role=DIE.UI.ParsedValuesRole) item_parsed_val_flag_ret.setIcon(self.die_icons.icon_more) else: item_parsed_val_ret.setData(parsed_vals[0], role=DIE.UI.ParsedValueRole) else: parsed_val_data = "NULL" if ret_value.derref_depth == 0: parsed_val_data = "!MAX_DEREF!" if ret_value.raw_value is not None: parsed_val_data = hex(ret_value.raw_value) if ret_value.nested_values or ret_value.reference_flink is not None: parsed_val_data = "" item_parsed_val_ret = QtGui.QStandardItem(parsed_val_data) parent.setChild(arg_count, 0, this_row_item) parent.setChild(arg_count, 1, QtGui.QStandardItem()) parent.setChild(arg_count, 2, QtGui.QStandardItem()) parent.setChild(arg_count, 3, QtGui.QStandardItem()) parent.setChild(arg_count, 4, QtGui.QStandardItem(arg_ident_type)) parent.setChild(arg_count, 5, QtGui.QStandardItem(arg_name)) parent.setChild(arg_count, 6, item_parsed_val_flag_call) parent.setChild(arg_count, 7, item_parsed_val_call) parent.setChild(arg_count, 8, item_parsed_val_flag_ret) parent.setChild(arg_count, 9, item_parsed_val_ret) # If current object contains reference values, add them to the module self._add_model_arg_ref(this_row_item, call_value, ret_value, nest_depth) # If current object is a container object, Add its members to the module self._add_model_container_members(this_row_item, call_value, ret_value, nest_depth)
def _model_builder(self, model): """ Build the function model. @param model: QStandardItemModel object """ model.clear() # Clear the model root_node = model.invisibleRootItem() self._make_model_headers(model) if self.die_db is None: return # Add db functions to the model for function in self.die_db.get_functions(): item_list_func = self._make_function_item(function) if function.is_lib_func: # Color library function for tmp_item in item_list_func: tmp_item.setBackground(QtGui.QColor(184, 223, 220)) item_function = item_list_func[0] root_node.appendRow(item_list_func) # Add function contexts ea\occurrences for the current function func_context_dict = self.die_db.get_function_context_dict(function) for function_context_ea in func_context_dict: function_context_list = func_context_dict[function_context_ea] if not len(function_context_list) > 0: continue item_func_context_list = self._make_function_ea_item( function_context_list[0]) item_func_context_ea = item_func_context_list[0] item_function.appendRow(item_func_context_list) occurrence_num = 0 for function_context in function_context_list: item_func_context_list = self._make_func_occur_item( function_context, occurrence_num) item_func_context = item_func_context_list[0] item_func_context_ea.appendRow(item_func_context_list) self._insert_thread_data(item_function, function_context.thread_id) self._insert_thread_data(item_func_context_ea, function_context.thread_id) # Add function arguments to each context current_call_values = self.die_db.get_call_values( function_context) current_ret_values = self.die_db.get_return_values( function_context) curret_ret_arg_value = self.die_db.get_return_arg_value( function_context) for arg_index in xrange(0, function.arg_num): try: current_arg = self.die_db.get_function_arg( function, arg_index) self._add_model_arg_value( item_func_context, current_call_values[arg_index], current_ret_values[arg_index], current_arg.name, current_arg.type) except IndexError: break ret_arg = self.die_db.get_function_arg(function, -1) if ret_arg is None: ret_arg_type = "VOID" else: ret_arg_type = ret_arg.type # Add return argument self._add_model_arg_value(item_func_context, None, curret_ret_arg_value, "ret_arg", ret_arg_type) # Increment occurrence counter occurrence_num += 1