def set_window_position(self): stack_view = idaapi.find_widget("Stack view") if stack_view: idaapi.set_dock_pos(STACK_WIDGET_TITLE, "Stack view", idaapi.DP_INSIDE) idaapi.close_widget(stack_view, 0) else: idaapi.set_dock_pos(STACK_WIDGET_TITLE, REGS_WIDGET_TITLE, idaapi.DP_BOTTOM)
def create_proj_explorer(self, project): """Creates the project explorer "sidebar" widget.""" self.project_explorer = ProjectExplorerWidget(project) self.project_explorer.Show("continuum project") self.project_explorer.refresh_project_clicked.connect(self.refresh_project) self.project_explorer.focus_instance_clicked.connect( lambda idb_path: self.core.client.send_focus_instance(idb_path) ) idaapi.set_dock_pos("continuum project", "Functions window", idaapi.DP_BOTTOM)
def OnCreate(self, form): # Get parent widget self.parent = self.FormToPyQtWidget(form) # Set location and width (TODO: hacky) idaapi.set_dock_pos(WINDOW_NAME, 'IDA View-A', idaapi.DP_RIGHT) self.parent.parent().setMaximumWidth(500) # Populate self.populate_form()
def run(self, arg): plg = Hyara() plg.Show("Hyara") widget_a = find_widget("IDA View-A") widget_Hyara = find_widget("Hyara") widget_OW = find_widget("Output window") if widget_Hyara and widget_a: set_dock_pos("Hyara", "IDA View-A", DP_RIGHT) if widget_OW: set_dock_pos("Output window", "Functions window", DP_BOTTOM)
def Show(self): widget = idaapi.get_current_widget() if idaapi.get_widget_title(widget) != self.title: if idaapi.get_widget_type(widget) != idaapi.BWN_PSEUDOCODE: pseudo_view = idaapi.open_pseudocode(self.ea, 1) pseudo_view.refresh_view(1) widget = pseudo_view.toplevel pseudo_title = idaapi.get_widget_title(widget) idaapi.display_widget(self.GetWidget(), idaapi.PluginForm.WOPN_DP_TAB | idaapi.PluginForm.WOPN_RESTORE) idaapi.set_dock_pos(self.title, pseudo_title, idaapi.DP_RIGHT)
def eventFilter(self, source, event): # # hook the destroy event of the coverage overview widget so that we can # cleanup after ourselves in the interest of stability # if int(event.type() ) == 16: # NOTE/COMPAT: QtCore.QEvent.Destroy not in IDA7? self._target.terminate() # # this is an unknown event, but it seems to fire when the widget is # being saved/restored by a QMainWidget. we use this to try and ensure # the Coverage Overview stays docked when flipping between Reversing # and Debugging states in IDA. # # See issue #16 on github for more information. # if int(event.type()) == 2002 and disassembler.NAME == "IDA": import idaapi # # if the general registers IDA View exists, we make the assumption # that the user has probably started debugging. # # NOTE / COMPAT: if disassembler.USING_IDA7API: debug_mode = bool(idaapi.find_widget("General registers")) else: debug_mode = bool(idaapi.find_tform("General registers")) # # if this is the first time the user has started debugging, dock # the coverage overview in the debug QMainWidget workspace. its # dock status / position should persist future debugger launches. # global debugger_docked if debug_mode and not debugger_docked: idaapi.set_dock_pos(self._target._title, "Structures", idaapi.DP_TAB) debugger_docked = True return False
def main(): global MAZEWALKER try: # There is an instance, reload it MAZEWALKER MAZEWALKER.OnClose(MAZEWALKER) MAZEWALKER = MazeUIPluginForm() except: # There is no instance yet MAZEWALKER = MazeUIPluginForm() MAZEWALKER.Show() idaapi.set_dock_pos(":: Maze Walker ::", "Functions window", idaapi.DP_INSIDE)
def open_control_panel(self): """ Open the control panel view and attach it to IDA View-A or Pseudocode-A. """ wrapper = ControlPanelViewWrapper(controller) if not wrapper.twidget: l.info( "BinSync is unable to find a widget to attach to. You are likely running headlessly" ) return None flags = idaapi.PluginForm.WOPN_TAB | idaapi.PluginForm.WOPN_RESTORE | idaapi.PluginForm.WOPN_PERSIST idaapi.display_widget(wrapper.twidget, flags) wrapper.widget.visible = True # casually open a pseudocode window, this prevents magic sync from spawning pseudocode windows # in weird locations upon an initial run func_addr = next(idautils.Functions()) ida_hexrays.open_pseudocode( func_addr, ida_hexrays.OPF_NO_WAIT | ida_hexrays.OPF_REUSE) # then attempt to flip back to IDA View-A twidget = idaapi.find_widget("IDA View-A") if twidget is not None: ida_kernwin.activate_widget(twidget, True) target = "Functions" fwidget = idaapi.find_widget(target) if not fwidget: # prioritize attaching the binsync panel to a decompilation window target = "Pseudocode-A" dwidget = idaapi.find_widget(target) if not dwidget: target = "IDA View-A" if target == "Functions": idaapi.set_dock_pos(ControlPanelViewWrapper.NAME, target, idaapi.DP_INSIDE) else: # attach the panel to the found target idaapi.set_dock_pos(ControlPanelViewWrapper.NAME, target, idaapi.DP_RIGHT)
def arrange_widgets(self): if self.arranging: return self.arranging = True try: wlist = [] for ch in range(ord("A"), ord("Z")): wname = "Pseudocode-" + chr(ch) if idaapi.find_widget(wname): wlist.append(wname) if len(wlist) > 0: idaapi.set_dock_pos(wlist[0], "IDA View-A", idaapi.DP_RIGHT) for i in range(1, len(wlist)): idaapi.set_dock_pos(wlist[i], wlist[i - 1], idaapi.DP_TAB) finally: self.arranging = False
def open_control_panel(self): """ Open the control panel view and attach it to IDA View-A or Pseudocode-A. """ wrapper = InfoPanelViewWrapper(controller) if not wrapper.twidget: raise RuntimeError("Unexpected: twidget does not exist.") flags = idaapi.PluginForm.WOPN_TAB | idaapi.PluginForm.WOPN_RESTORE | idaapi.PluginForm.WOPN_PERSIST idaapi.display_widget(wrapper.twidget, flags) wrapper.widget.visible = True # Dock it for target in ["IDA View-A", "Pseudocode-A"]: dwidget = idaapi.find_widget(target) if dwidget: idaapi.set_dock_pos(InfoPanelViewWrapper.NAME, target, idaapi.DP_RIGHT) break
def show_content_viewers(self): self.dav.Show() self.hv.Show() self.iv.Show() # TODO: the docking code heavily lacks documentation. seems to be bugged as well. # also, why do we have to call the code twice for a better alignment of the docked windows? # have to deal with the following layout for now :[ for i in xrange(2): idaapi.set_dock_pos(self.capGadget, self.capGadget, idaapi.DP_FLOATING, 0, 0, 1200, 500) idaapi.set_dock_pos(self.capInfo, self.capGadget, idaapi.DP_BOTTOM) idaapi.set_dock_pos(self.capHex, self.capGadget, idaapi.DP_RIGHT) idaapi.set_dock_pos(self.capDisasm, self.capHex, idaapi.DP_RIGHT)
def retrieve_function_callback(self, __, ea=None): if not self.check_before_use(): return funcset_ids = [self.funcset] if not self.cfg['usepublic'] else None func_ea = idaapi.get_screen_ea() if ea is None else ea func_name = idaapi.get_func_name(func_ea) targets = self.retrieve_function(func_ea, self.cfg['topk'], funcset_ids) succ, skip, fail = 0, 0, 0 if targets is None: print("[{}] {} failed because get function feature error".format( self.name, func_name)) fail += 1 else: if not (self.cview and self.cview.is_alive()): self.cview = SourceCodeViewer(self.name) # CDVF_STATUSBAR 0x04, keep the status bar in the custom viewer idaapi.set_code_viewer_is_source( idaapi.create_code_viewer(self.cview.GetWidget(), 0x4)) self.cview.set_user_data(func_ea, targets) widget = idaapi.get_current_widget() if idaapi.get_widget_title(widget) == self.name: skip += 1 else: if idaapi.get_widget_type(widget) != idaapi.BWN_PSEUDOCODE: pseudo_view = idaapi.open_pseudocode(func_ea, 1) pseudo_view.refresh_view(1) widget = pseudo_view.toplevel pseudo_title = idaapi.get_widget_title(widget) idaapi.display_widget( self.cview.GetWidget(), idaapi.PluginForm.WOPN_DP_TAB | idaapi.PluginForm.WOPN_RESTORE) idaapi.set_dock_pos(self.name, pseudo_title, idaapi.DP_RIGHT) succ += 1 print( "[{}] {} functions successfully retrieved, {} functions failed, {} functions skipped" .format(self.name, succ, fail, skip))
def show_content_viewers(self): self.dav.Show() self.hv.Show() self.iv.Show() # TODO: the docking code heavily lacks documentation. seems to be bugged as well. # also, why do we have to call the code twice for a better alignment of the docked windows? # have to deal with the following layout for now :[ for i in xrange(2): idaapi.set_dock_pos(self.capGadget, self.capGadget, idaapi.DP_FLOATING, 0, 0, 1200, 500) idaapi.set_dock_pos(self.capInfo, self.capGadget, idaapi.DP_BOTTOM) idaapi.set_dock_pos(self.capHex, self.capGadget, idaapi.DP_RIGHT) idaapi.set_dock_pos(self.capDisasm, self.capHex, idaapi.DP_RIGHT)
def set_window_position(self): ref_widgets = [("Modules", idaapi.DP_TOP), ("Threads", idaapi.DP_TOP), ("IDA View-EIP", idaapi.DP_RIGHT), ("Stack view", idaapi.DP_TOP)] plug_window_name = "Registers - %s" % PLUGIN_NAME regs_widget = idaapi.find_widget("General registers") if regs_widget: idaapi.set_dock_pos(REGS_WIDGET_TITLE, "General registers", idaapi.DP_INSIDE) idaapi.close_widget(regs_widget, 0) else: found = False for wname, pos in ref_widgets: if idaapi.find_widget(wname): idaapi.set_dock_pos(REGS_WIDGET_TITLE, wname, pos) found = True break if not found: idaapi.set_dock_pos(REGS_WIDGET_TITLE, None, idaapi.DP_FLOATING)
def OnCreate(self, form) -> None: """Called when the plugin form is created """ # init data structures: self.funcMapper = FunctionsMapper_t() self.criterium_id = 0 # Get parent widget self.parent = self.FormToPyQtWidget(form) # Create models self.subDataManager = DataManager() self.table_model = TableModel_t(self.funcMapper.funcList) # init self.addr_sorted_model = QtCore.QSortFilterProxyModel() self.addr_sorted_model.setDynamicSortFilter(True) self.addr_sorted_model.setSourceModel(self.table_model) self.addr_view = FunctionsView_t(g_DataManager, COLOR_HILIGHT_FUNC, self.table_model) self.addr_view.setModel(self.addr_sorted_model) self.addr_view.setSortingEnabled(True) self.addr_view.setWordWrap(False) self.addr_view.horizontalHeader().setStretchLastSection(False) self.addr_view.verticalHeader().show() self.adjustColumnsToContents() # self.refsto_model = RefsTableModel_t(self.funcMapper.funcList, True) self.refs_view = FunctionsView_t(self.subDataManager, COLOR_HILIGHT_REFTO, self.refsto_model) self._setup_sorted_model(self.refs_view, self.refsto_model) self.refs_view.setColumnHidden(RefsTableModel_t.COL_TOADDR, True) self.refs_view.setWordWrap(False) font = self.refs_view.font() font.setPointSize(8) self.refs_view.setFont(font) self.refsfrom_model = RefsTableModel_t(self.funcMapper.funcList, False) self.refsfrom_view = FunctionsView_t(self.subDataManager, COLOR_HILIGHT_REFFROM, self.refsfrom_model) self._setup_sorted_model(self.refsfrom_view, self.refsfrom_model) self.refsfrom_view.setColumnHidden(RefsTableModel_t.COL_TOADDR, True) self.refsfrom_view.setWordWrap(False) # add a box to enable/disable live filtering self.livefilter_box = QtWidgets.QCheckBox("Live filtering") self.livefilter_box.setToolTip("If live filtering is enabled, functions are searched as you type in the edit box.\nOtherwise they are searched when you press Enter.") self.livefilter_box.setChecked(self._LIVE_FILTER) self.is_livefilter = self._LIVE_FILTER # connect SIGNAL self.livefilter_box.stateChanged.connect(self.liveSearchCheckBox) # important for proper order of objects destruction: self.table_model.setParent(self.addr_sorted_model) self.addr_sorted_model.setParent(self.addr_view) # connect SIGNAL g_DataManager.updateSignal.connect(self.longoperationcomplete) # Create a Tab widget for references: self.refs_tabs = QtWidgets.QTabWidget() self.refs_tabs.insertTab(0, self.refs_view, "Is refered by") self.refs_tabs.insertTab(1, self.refsfrom_view, "Refers to") # Create filter self.filter_edit = QtWidgets.QLineEdit() self.filter_edit.setPlaceholderText("keyword") self.filter_edit.keyReleaseEvent = self.filterKeyEvent self.filter_combo = QtWidgets.QComboBox() self.filter_combo.addItems(TableModel_t.header_names) self.filter_combo.setCurrentIndex(TableModel_t.COL_NAME) # connect SIGNAL self.filter_combo.activated.connect(self.filterChanged) self.criterium_combo = QtWidgets.QComboBox() criteria = ["contains", "matches"] self.criterium_combo.addItems(criteria) self.criterium_combo.setCurrentIndex(0) # connect SIGNAL self.criterium_combo.activated.connect(self.criteriumChanged) filter_panel = QtWidgets.QFrame() filter_layout = QtWidgets.QHBoxLayout() filter_layout.addWidget(QtWidgets.QLabel("Where ")) filter_layout.addWidget(self.filter_combo) filter_layout.addWidget(self.criterium_combo) filter_layout.addWidget(self.filter_edit) filter_panel.setLayout(filter_layout) self.filter_edit.setFixedHeight(20) filter_panel.setFixedHeight(40) filter_panel.setAutoFillBackground(True) self.refs_label = QtWidgets.QLabel("Function") self.refs_label.setTextFormat(QtCore.Qt.RichText) self.refs_label.setWordWrap(True) panel1 = QtWidgets.QFrame() layout1 = QtWidgets.QVBoxLayout() panel1.setLayout(layout1) layout1.addWidget(filter_panel) layout1.addWidget(self.livefilter_box) layout1.addWidget(self.addr_view) layout1.setContentsMargins(0, 0, 0, 0) panel2 = QtWidgets.QFrame() layout2 = QtWidgets.QVBoxLayout() layout2.addWidget(self.refs_label) layout2.addWidget(self.refs_tabs) layout2.addWidget(self._makeButtonsPanel()) layout2.setContentsMargins(0, 10, 0, 0) panel2.setLayout(layout2) self.main_splitter = QtWidgets.QSplitter() self.main_splitter.setOrientation(QtCore.Qt.Vertical) self.main_splitter.addWidget(panel1) self.main_splitter.addWidget(panel2) # Populate PluginForm layout = QtWidgets.QVBoxLayout() layout.addWidget(self.main_splitter) layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) self.parent.setLayout(layout) self.alternateRowColors(IS_ALTERNATE_ROW) idaapi.set_dock_pos(PLUGIN_NAME, None, idaapi.DP_RIGHT)
def eventFilter(self, source, event): # # hook the destroy event of the coverage overview widget so that we can # cleanup after ourselves in the interest of stability # if int(event.type()) == self.EventDestroy: source.removeEventFilter(self) self._target.terminate() # # this seems to be 'roughly' the last event triggered after the widget # is done initializing in both IDA and Binja, but prior to the first # user-triggered 'show' events. # # this is mostly to account for the fact that binja 'shows' the widget # when it is initially created (outside of our control). this was # causing lighthouse to automatically cache database metadata when # every database was opened ... # elif int(event.type()) == self.EventLayoutRequest: self._target.initialized = True # # this is used to hook a little bit after the 'show' event of the # coverage overview. this is the most universal signal that the # user is *actually* trying to use lighthouse in a meaningful way... # # we will use this moment first to check if they skipped straight to # 'go' and opened the coverage overview without the metadata cache # getting built. # # this case should only happen if the user does 'Show Coverage # Overview' from the binja-controlled Window menu entry... # elif int(event.type()) == self.EventUpdateLater: if self._target.visible and self._first_hit: self._first_hit = False if disassembler.NAME == "BINJA": self._target.lctx.start() if not self._target.director.metadata.cached: self._target.director.refresh() # # this is an unknown event, but it seems to fire when the widget is # being saved/restored by a QMainWidget (in IDA). we use this to try # and ensure the Coverage Overview stays docked when flipping between # Reversing and Debugging states in IDA. # # See issue #16 on github for more information. # elif int(event.type()) == 2002 and disassembler.NAME == "IDA": import idaapi # # if the general registers IDA View exists, we make the assumption # that the user has probably started debugging. # debug_mode = bool(idaapi.find_widget("General registers")) # # if this is the first time the user has started debugging, dock # the coverage overview in the debug QMainWidget workspace. its # dock status / position should persist future debugger launches. # global debugger_docked if debug_mode and not debugger_docked: idaapi.set_dock_pos(self._target._title, "Structures", idaapi.DP_TAB) debugger_docked = True return False
def show_diff(self, filename): viewer = Viewer(filename) viewer.show_functions_match_viewer() viewer.set_basic_blocks_color(0xCCFFFF, 0xCC00CC) idaapi.set_dock_pos("Function Matches", "Functions window", idaapi.DP_TAB)
def __init__(self, filename): self.match_results = [] if os.path.isfile(filename): self.functions_matcher = functions.Matcher(filename=filename) md5 = idc.GetInputMD5().lower() if md5 == self.functions_matcher.get_md5('source'): self.self_name = 'source' self.peer_name = 'target' elif md5 == self.functions_matcher.get_md5('target'): self.self_name = 'target' self.peer_name = 'source' else: self.self_name = 'source' self.peer_name = 'target' def show_functions_match_viewer(self, form_name): form = FunctionsMatchViewer() form.Show(form_name) form.add_items(self.functions_matcher.select_by_score(), self.self_name, self.peer_name, self.functions_matcher.get_md5(self.peer_name), 0x00ff00, 0x0000ff) if __name__ == '__main__': viewer = Viewer(get_filename()) viewer.show_functions_match_viewer() viewer.set_basic_blocks_color(0xCCFFFF, 0xCC00CC) idaapi.set_dock_pos("Function Matches", "Functions window", idaapi.DP_TAB)