def _init_ui(self): # config dialog configure_binsync_id = "BinSync: Configure" UIAction.registerAction(configure_binsync_id) UIActionHandler.globalActions().bindAction( configure_binsync_id, UIAction(self._launch_config)) Menu.mainMenu("Tools").addAction(configure_binsync_id, "BinSync") # control panel (per BV) dock_handler = DockHandler.getActiveDockHandler() dock_handler.addDockWidget( "BinSync: Control Panel", lambda n, p, d: create_widget( ControlPanelDockWidget, n, p, d, self.controllers), Qt.RightDockWidgetArea, Qt.Vertical, True)
def registerAllSnippets(): for action in list( filter(lambda x: x.startswith("Snippets\\"), UIAction.getAllRegisteredActions())): if action == "Snippets\\Snippet Editor...": continue UIActionHandler.globalActions().unbindAction(action) Menu.mainMenu("Tools").removeAction(action) UIAction.unregisterAction(action) for snippet in includeWalk(snippetPath, ".py"): snippetKeys = None (snippetDescription, snippetKeys, snippetCode) = loadSnippetFromFile(snippet) if not snippetDescription: actionText = "Snippets\\" + os.path.basename(snippet).rstrip( ".py") else: actionText = "Snippets\\" + snippetDescription if snippetCode: if snippetKeys == None: UIAction.registerAction(actionText) else: UIAction.registerAction(actionText, snippetKeys) UIActionHandler.globalActions().bindAction( actionText, UIAction(makeSnippetFunction(snippetCode))) Menu.mainMenu("Tools").addAction(actionText, actionText)
def bindActions(self): self.actionHandler.bindAction("IR graph", UIAction(self.on_ir_graph)) self.actionHandler.bindAction("IR graph (SSA)", UIAction(self.on_ssa_simp)) self.actionHandler.bindAction("IR graph (SSA + unSSA)", UIAction(self.on_unssa_simp)) self.actionHandler.bindAction("Simplify code", UIAction(self.on_simp)) self.actionHandler.bindAction("Subcalls don't change stack", UIAction(self.on_dontmodstack)) self.actionHandler.bindAction("Load static memory", UIAction(self.on_loadmem))
def registerAllSnippets(self): for action in list(filter(lambda x: x.startswith("Snippet\\"), UIAction.getAllRegisteredActions())): UIActionHandler.globalActions().unbindAction(action) UIAction.unregisterAction(action) for snippet in includeWalk(snippetPath, ".py"): (snippetDescription, snippetKey, snippetCode) = loadSnippetFromFile(snippet) if not snippetDescription: actionText = "Snippet\\" + snippet else: actionText = "Snippet\\" + snippetDescription UIAction.registerAction(actionText, snippetKey) UIActionHandler.globalActions().bindAction(actionText, UIAction(makeSnippetFunction(snippetCode)))
def __init__(self, context): super(TriageFilePicker, self).__init__() self.context = context self.actionHandler = UIActionHandler() self.actionHandler.setupActionHandler(self) self.contextMenu = Menu() self.contextMenuManager = ContextMenuManager(self) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.model = QFileSystemModel() self.model.setRootPath("") self.model.setFilter(QDir.AllEntries | QDir.Hidden | QDir.System) self.tree = QTreeView(self) self.tree.setModel(self.model) self.tree.setSelectionMode(QAbstractItemView.ExtendedSelection) self.tree.setColumnWidth(0, 500) layout.addWidget(self.tree, 1) self.setLayout(layout) self.tree.doubleClicked.connect(self.onDoubleClick) recentFile = QSettings().value("triage/recentFile", os.path.expanduser("~")) while len(recentFile) > 0: f = self.model.index(recentFile) if f.isValid(): self.tree.scrollTo(f) self.tree.setExpanded(f, True) break parentDir = os.path.dirname(recentFile) if parentDir == recentFile: break recentFile = parentDir self.actionHandler.bindAction( "Open Selected Files", UIAction(lambda context: self.openSelectedFiles(), lambda context: self.areFilesSelected())) self.contextMenu.addAction("Open Selected Files", "Open")
def _registerUIActions(): UIAction.registerAction("SENinja\\Setup argv...") UIActionHandler.globalActions().bindAction("SENinja\\Setup argv...", UIAction(_launchArgvDialog)) Menu.mainMenu("Tools").addAction("SENinja\\Setup argv...", "Setup argv...")
def add_commands(plugin): DbgAction = namedtuple('DbgAction', 'name, key_seq, handler') plugin_actions = (DbgAction("SyncEnable", QKeySequence(Qt.ALT + Qt.Key_S), UIAction(plugin.cmd_sync)), DbgAction("SyncDisable", QKeySequence(Qt.ALT + Qt.SHIFT + Qt.Key_S), UIAction(plugin.cmd_syncoff)), DbgAction("SyncGo", QKeySequence(Qt.ALT + Qt.Key_F5), UIAction(plugin.cmd_go)), DbgAction("SyncStepOver", QKeySequence(Qt.Key_F10), UIAction(plugin.cmd_so)), DbgAction("SyncStepInto", QKeySequence(Qt.Key_F11), UIAction(plugin.cmd_si)), DbgAction("SyncTranslate", QKeySequence(Qt.ALT + Qt.Key_F2), UIAction(plugin.cmd_translate)), DbgAction("SyncBp", QKeySequence(Qt.Key_F2), UIAction(plugin.cmd_bp)), DbgAction("SyncHwBp", QKeySequence(Qt.CTRL + Qt.Key_F2), UIAction(plugin.cmd_hwbp)), DbgAction("SyncBpOneShot", QKeySequence(Qt.ALT + Qt.Key_F3), UIAction(plugin.cmd_bp1)), DbgAction("SyncHwBpOneShot", QKeySequence(Qt.CTRL + Qt.Key_F3), UIAction(plugin.cmd_hwbp1))) for action in plugin_actions: UIAction.registerAction(action.name, action.key_seq) UIActionHandler.globalActions().bindAction(action.name, action.handler) rs_log('commands added')
def _install_open_coverage_overview(self): action = self.ACTION_COVERAGE_OVERVIEW UIAction.registerAction(action) UIActionHandler.globalActions().bindAction(action, UIAction(self._open_coverage_overview)) Menu.mainMenu("Tools").addAction(action, "Windows", 0) logger.info("Installed the 'Open Coverage Overview' menu entry")
def _install_load_batch(self): action = self.ACTION_LOAD_BATCH UIAction.registerAction(action) UIActionHandler.globalActions().bindAction(action, UIAction(self._interactive_load_batch)) Menu.mainMenu("Tools").addAction(action, "Loading", 1) logger.info("Installed the 'Code coverage batch' menu entry")
# Update UI according to the active frame if frame: self.datatype.setText(frame.getCurrentView()) view = frame.getCurrentViewInterface() self.data = view.getData() self.offset.setText(hex(view.getCurrentOffset())) else: self.datatype.setText("None") self.data = None def contextMenuEvent(self, event): self.m_contextMenuManager.show(self.m_menu, self.actionHandler) @staticmethod def createPane(context): if context.context and context.binaryView: widget = HelloPaneWidget(context.binaryView) pane = WidgetPane(widget, "Hello") context.context.openPane(pane) @staticmethod def canCreatePane(context): return context.context and context.binaryView UIAction.registerAction("Hello Pane") UIActionHandler.globalActions().bindAction( "Hello Pane", UIAction(HelloPaneWidget.createPane, HelloPaneWidget.canCreatePane)) Menu.mainMenu("Tools").addAction("Hello Pane", "Hello")
if len(snippetKey) != 0 and snippetKey[0] != self.keySequenceEdit.keySequence(): return True return self.edit.toPlainText() != snippetCode or \ self.snippetDescription.text() != snippetDescription def save(self): log_debug("Saving snippet %s" % self.currentFile) outputSnippet = open(self.currentFile, "w") outputSnippet.write("#" + self.snippetDescription.text() + "\n") outputSnippet.write("#" + self.keySequenceEdit.keySequence().toString() + "\n") outputSnippet.write(self.edit.toPlainText()) outputSnippet.close() self.registerAllSnippets() def clearHotkey(self): self.keySequenceEdit.clear() def launchPlugin(context): snippets = Snippets() snippets.exec_() if __name__ == '__main__': app = QApplication(sys.argv) snippets = Snippets() snippets.show() sys.exit(app.exec_()) else: UIAction.registerAction("Snippet Editor...") UIActionHandler.globalActions().bindAction("Snippet Editor...", UIAction(launchPlugin)) Menu.mainMenu("Tools").addAction("Snippet Editor...", "Snippet")
"description" : "Controls the amount of analysis performed on functions when opening for triage.", "enum" : ["controlFlow", "basic", "full"], "enumDescriptions" : [ "Only perform control flow analysis on the binary. Cross references are valid only for direct function calls.", "Perform fast initial analysis of the binary. This mode does not analyze types or data flow through stack variables.", "Perform full analysis of the binary." ] } """) Settings().register_setting("triage.linearSweep", """ { "title" : "Triage Linear Sweep Mode", "type" : "string", "default" : "partial", "description" : "Controls the level of linear sweep performed when opening for triage.", "enum" : ["none", "partial", "full"], "enumDescriptions" : [ "Do not perform linear sweep of the binary.", "Perform linear sweep on the binary, but skip the control flow graph analysis phase.", "Perform full linear sweep on the binary." ] } """) UIAction.registerAction("Open for Triage...", QKeySequence("Ctrl+Alt+O")) UIAction.registerAction("Open Selected Files") UIActionHandler.globalActions().bindAction("Open for Triage...", UIAction(openForTriage)) Menu.mainMenu("File").addAction("Open for Triage...", "Open") UIContext.registerFileOpenMode("Triage...", "Open file(s) for quick analysis in the Triage Summary view.", "Open for Triage...")
if size > 0 and size < 400 and i + size < len(data): byte_key = data[i:i+4] decrypted = bytearray() valid = True for j in range(size): char = data[i+8+j] ^ byte_key[j % 4] if char not in printables: valid = False break decrypted.append(char) if valid: sym_addr = data_section.start + i s = bytes(decrypted).decode() sym_name = s[:20].strip() for c in " \t\r\n": sym_name = sym_name.replace(c, "_") sym_name = "str_" + sym_name symbol = Symbol(SymbolType.DataSymbol, sym_addr, sym_name) bv.define_user_symbol(symbol) bv.write(sym_addr, s + "\x00") def launch_plugin(context): bv = context.binaryView decrypt_strings(bv) find_dynamic_apis(bv) UIAction.registerAction("Emotet Deobufscator") UIActionHandler.globalActions().bindAction("Emotet Deobufscator", UIAction(launch_plugin)) Menu.mainMenu("Tools").addAction("Emotet Deobufscator", "Emotet Deobufscator")
try: from binaryninjaui import (UIAction, UIActionHandler, Menu) from . import keypatch UIAction.registerAction("KEYPATCH") UIActionHandler.globalActions().bindAction( "KEYPATCH", UIAction(keypatch.launch_keypatch)) Menu.mainMenu("Tools").addAction("KEYPATCH", "KEYPATCH") except ModuleNotFoundError: # probably being loaded by headless BinaryNinja pass
"default" : "partial", "description" : "Controls the level of linear sweep performed when opening for triage.", "enum" : ["none", "partial", "full"], "enumDescriptions" : [ "Do not perform linear sweep of the binary.", "Perform linear sweep on the binary, but skip the control flow graph analysis phase.", "Perform full linear sweep on the binary." ] } """) Settings().register_setting( "triage.hiddenFiles", """ { "title" : "Triage Shows Hidden Files", "type" : "boolean", "default" : false, "description" : "Whether the Triage file picker shows hidden files." } """) UIAction.registerAction("Open for Triage...", QKeySequence("Ctrl+Alt+O")) UIAction.registerAction("Open Selected Files") UIActionHandler.globalActions().bindAction("Open for Triage...", UIAction(openForTriage)) Menu.mainMenu("File").addAction("Open for Triage...", "Open") UIContext.registerFileOpenMode( "Triage...", "Open file(s) for quick analysis in the Triage Summary view.", "Open for Triage...")
def __init__(self, parent, data): if not type(data) == binaryninja.binaryview.BinaryView: raise Exception('expected widget data to be a BinaryView') self.bv = data self.debug_state = binjaplug.get_state(data) memory_view = self.debug_state.memory_view self.debug_state.ui.debug_view = self QWidget.__init__(self, parent) View.__init__(self) self.setupView(self) self.current_offset = 0 self.splitter = QSplitter(Qt.Orientation.Horizontal, self) frame = ViewFrame.viewFrameForWidget(self) self.memory_editor = LinearView(memory_view, frame) self.binary_editor = DisassemblyContainer(frame, data, frame) self.binary_text = TokenizedTextView(self, memory_view) self.is_raw_disassembly = False # TODO: Handle these and change views accordingly # Currently they are just disabled as the DisassemblyContainer gets confused # about where to go and just shows a bad view self.binary_editor.getDisassembly().actionHandler().bindAction( "View in Hex Editor", UIAction()) self.binary_editor.getDisassembly().actionHandler().bindAction( "View in Linear Disassembly", UIAction()) self.binary_editor.getDisassembly().actionHandler().bindAction( "View in Types View", UIAction()) self.memory_editor.actionHandler().bindAction("View in Hex Editor", UIAction()) self.memory_editor.actionHandler().bindAction( "View in Disassembly Graph", UIAction()) self.memory_editor.actionHandler().bindAction("View in Types View", UIAction()) small_font = QApplication.font() small_font.setPointSize(11) bv_layout = QVBoxLayout() bv_layout.setSpacing(0) bv_layout.setContentsMargins(0, 0, 0, 0) bv_label = QLabel("Loaded File") bv_label.setFont(small_font) bv_layout.addWidget(bv_label) bv_layout.addWidget(self.binary_editor) self.bv_widget = QWidget() self.bv_widget.setLayout(bv_layout) disasm_layout = QVBoxLayout() disasm_layout.setSpacing(0) disasm_layout.setContentsMargins(0, 0, 0, 0) disasm_label = QLabel("Raw Disassembly at PC") disasm_label.setFont(small_font) disasm_layout.addWidget(disasm_label) disasm_layout.addWidget(self.binary_text) self.disasm_widget = QWidget() self.disasm_widget.setLayout(disasm_layout) memory_layout = QVBoxLayout() memory_layout.setSpacing(0) memory_layout.setContentsMargins(0, 0, 0, 0) memory_label = QLabel("Debugged Process") memory_label.setFont(small_font) memory_layout.addWidget(memory_label) memory_layout.addWidget(self.memory_editor) self.memory_widget = QWidget() self.memory_widget.setLayout(memory_layout) self.splitter.addWidget(self.bv_widget) self.splitter.addWidget(self.memory_widget) # Equally sized self.splitter.setSizes([0x7fffffff, 0x7fffffff]) self.controls = ControlsWidget.DebugControlsWidget( self, "Controls", data, self.debug_state) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.addWidget(self.controls) layout.addWidget(self.splitter, 100) self.setLayout(layout) self.needs_update = True self.update_timer = QTimer(self) self.update_timer.setInterval(200) self.update_timer.setSingleShot(False) self.update_timer.timeout.connect(lambda: self.updateTimerEvent()) # Add debugger state to the interpreter as `dbg` main_window = parent.window() dock_handler = main_window.findChild(DockHandler, '__DockHandler') if dock_handler: console = dock_handler.getDockWidget('Python Console') if console: # Hack: Currently no way to access the scripting provider directly # So just run the commands through the ui console.widget().addInput( "import debugger\ndbg = debugger.get(bv)")
def make_code(bv: BinaryView, start: int, end: int) -> None: if bv.get_basic_blocks_at(start): return if end - start <= 1: # find the next basic block, data variable, or segment/section end data_var = bv.get_next_data_var_after(start) if data_var is not None: end = data_var.address else: end = bv.end end = min(bv.get_next_basic_block_start_after(start), end) seg = bv.get_segment_at(start) if seg is not None: end = min(seg.end, end) section_ends = [s.end for s in bv.get_sections_at(start)] end = min(*section_ends, end) bv.define_data_var(start, Type.array(Type.int(1, False), end - start), f"CODE_{start:08x}") def make_code_helper(ctx: UIActionContext): make_code(ctx.binaryView, ctx.address, ctx.address + ctx.length) CodeDataRenderer().register_type_specific() UIAction.registerAction("Make Code", QKeySequence("C")) UIActionHandler.globalActions().bindAction("Make Code", UIAction(make_code_helper))
def registerActions(self): UIAction.registerAction("IR graph") UIAction.registerAction("IR graph (SSA)") UIAction.registerAction("IR graph (SSA + unSSA)") UIAction.registerAction("Simplify code") UIAction.registerAction("Subcalls don't change stack") UIAction.registerAction("Load static memory")
def __init__(self, parent, data): QAbstractScrollArea.__init__(self, parent) View.__init__(self) View.setBinaryDataNavigable(self, True) self.setupView(self) self.data = data self.byte_mapping = [ u' ', u'☺', u'☻', u'♥', u'♦', u'♣', u'♠', u'•', u'◘', u'○', u'◙', u'♂', u'♀', u'♪', u'♫', u'☼', u'▸', u'◂', u'↕', u'‼', u'¶', u'§', u'▬', u'↨', u'↑', u'↓', u'→', u'←', u'∟', u'↔', u'▴', u'▾', u' ', u'!', u'"', u'#', u'$', u'%', u'&', u'\'', u'(', u')', u'*', u'+', u',', u'-', u'.', u'/', u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u':', u';', u'<', u'=', u'>', u'?', u'@', u'A', u'B', u'C', u'D', u'E', u'F', u'G', u'H', u'I', u'J', u'K', u'L', u'M', u'N', u'O', u'P', u'Q', u'R', u'S', u'T', u'U', u'V', u'W', u'X', u'Y', u'Z', u'[', u'\\', u']', u'^', u'_', u'`', u'a', u'b', u'c', u'd', u'e', u'f', u'g', u'h', u'i', u'j', u'k', u'l', u'm', u'n', u'o', u'p', u'q', u'r', u's', u't', u'u', u'v', u'w', u'x', u'y', u'z', u'{', u'|', u'}', u'~', u'⌂', u'Ç', u'ü', u'é', u'â', u'ä', u'à', u'å', u'ç', u'ê', u'ë', u'è', u'ï', u'î', u'ì', u'Ä', u'Å', u'É', u'æ', u'Æ', u'ô', u'ö', u'ò', u'û', u'ù', u'ÿ', u'Ö', u'Ü', u'¢', u'£', u'¥', u'₧', u'ƒ', u'á', u'í', u'ó', u'ú', u'ñ', u'Ñ', u'ª', u'º', u'¿', u'⌐', u'¬', u'½', u'¼', u'¡', u'«', u'»', u'░', u'▒', u'▓', u'│', u'┤', u'╡', u'╢', u'╖', u'╕', u'╣', u'║', u'╗', u'╝', u'╜', u'╛', u'┐', u'└', u'┴', u'┬', u'├', u'─', u'┼', u'╞', u'╟', u'╚', u'╔', u'╩', u'╦', u'╠', u'═', u'╬', u'╧', u'╨', u'╤', u'╥', u'╙', u'╘', u'╒', u'╓', u'╫', u'╪', u'┘', u'┌', u'█', u'▄', u'▌', u'▐', u'▀', u'α', u'ß', u'Γ', u'π', u'Σ', u'σ', u'µ', u'τ', u'Φ', u'Θ', u'Ω', u'δ', u'∞', u'φ', u'ε', u'∩', u'≡', u'±', u'≥', u'≤', u'⌠', u'⌡', u'÷', u'≈', u'°', u'∙', u'·', u'√', u'ⁿ', u'²', u'■', u' ' ] if sys.version_info.major == 2: mapping = {} for i in range(0, 256): mapping[chr(i)] = self.byte_mapping[i] self.byte_mapping = mapping self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.setFocusPolicy(Qt.StrongFocus) self.cursorAddr = self.data.start self.prevCursorAddr = self.cursorAddr self.selectionStartAddr = self.cursorAddr self.topAddr = self.cursorAddr self.topLine = 0 self.selectionVisible = False self.caretVisible = False self.caretBlink = True self.leftButtonDown = False self.cols = 128 self.updatesRequired = False self.visibleRows = 1 self.lines = [] self.updateRanges() areaSize = self.viewport().size() self.adjustSize(areaSize.width(), areaSize.height()) if self.allocatedLength > 0x7fffffff: self.scrollBarMultiplier = (self.allocatedLength // 0x7fffffff) + 1 else: self.scrollBarMultiplier = 1 self.wheelDelta = 0 self.updatingScrollBar = False self.verticalScrollBar().setRange(0, (self.allocatedLength - 1) // self.scrollBarMultiplier) self.verticalScrollBar().sliderMoved.connect(self.scrollBarMoved) self.verticalScrollBar().actionTriggered.connect(self.scrollBarAction) self.cursorTimer = QTimer(self) self.cursorTimer.setInterval(500) self.cursorTimer.setSingleShot(False) self.cursorTimer.timeout.connect(self.cursorTimerEvent) self.cursorTimer.start() self.updateTimer = QTimer(self) self.updateTimer.setInterval(200) self.updateTimer.setSingleShot(False) #self.updateTimer.timeout.connect(self.updateTimerEvent) self.actionHandler().bindAction("Move Cursor Up", UIAction(lambda ctxt: self.up(False))) self.actionHandler().bindAction( "Move Cursor Down", UIAction(lambda ctxt: self.down(False))) self.actionHandler().bindAction( "Move Cursor Left", UIAction(lambda ctxt: self.left(1, False))) self.actionHandler().bindAction( "Move Cursor Right", UIAction(lambda ctxt: self.right(1, False))) self.actionHandler().bindAction( "Move Cursor Word Left", UIAction(lambda ctxt: self.left(8, False))) self.actionHandler().bindAction( "Move Cursor Word Right", UIAction(lambda ctxt: self.right(8, False))) self.actionHandler().bindAction("Extend Selection Up", UIAction(lambda ctxt: self.up(True))) self.actionHandler().bindAction("Extend Selection Down", UIAction(lambda ctxt: self.down(True))) self.actionHandler().bindAction( "Extend Selection Left", UIAction(lambda ctxt: self.left(1, True))) self.actionHandler().bindAction( "Extend Selection Right", UIAction(lambda ctxt: self.right(1, True))) self.actionHandler().bindAction( "Extend Selection Word Left", UIAction(lambda ctxt: self.left(8, True))) self.actionHandler().bindAction( "Extend Selection Word Right", UIAction(lambda ctxt: self.right(8, True))) self.actionHandler().bindAction( "Page Up", UIAction(lambda ctxt: self.pageUp(False))) self.actionHandler().bindAction( "Page Down", UIAction(lambda ctxt: self.pageDown(False))) self.actionHandler().bindAction( "Extend Selection Page Up", UIAction(lambda ctxt: self.pageUp(True))) self.actionHandler().bindAction( "Extend Selection Page Down", UIAction(lambda ctxt: self.pageDown(True))) self.actionHandler().bindAction( "Move Cursor to Start of Line", UIAction(lambda ctxt: self.moveToStartOfLine(False))) self.actionHandler().bindAction( "Move Cursor to End of Line", UIAction(lambda ctxt: self.moveToEndOfLine(False))) self.actionHandler().bindAction( "Move Cursor to Start of View", UIAction(lambda ctxt: self.moveToStartOfView(False))) self.actionHandler().bindAction( "Move Cursor to End of View", UIAction(lambda ctxt: self.moveToEndOfView(False))) self.actionHandler().bindAction( "Extend Selection to Start of Line", UIAction(lambda ctxt: self.moveToStartOfLine(True))) self.actionHandler().bindAction( "Extend Selection to End of Line", UIAction(lambda ctxt: self.moveToEndOfLine(True))) self.actionHandler().bindAction( "Extend Selection to Start of View", UIAction(lambda ctxt: self.moveToStartOfView(True))) self.actionHandler().bindAction( "Extend Selection to End of View", UIAction(lambda ctxt: self.moveToEndOfView(True)))
def function_updated(self, view, func): self._controller.push_function(func) def start_patch_monitor(view): notification = PatchDataNotification(view, controller) view.register_notification(notification) def start_function_monitor(view): notification = EditFunctionNotification(view, controller) view.register_notification(notification) UIAction.registerAction("Configure BinSync...") UIActionHandler.globalActions().bindAction("Configure BinSync...", UIAction(launch_binsync_configure)) Menu.mainMenu("Tools").addAction("Configure BinSync...", "BinSync") open_control_panel_id = "BinSync: Open control panel" UIAction.registerAction(open_control_panel_id) UIActionHandler.globalActions().bindAction(open_control_panel_id, UIAction(open_control_panel)) Menu.mainMenu("Tools").addAction(open_control_panel_id, "BinSync") # register the control panel dock widget dock_handler = DockHandler.getActiveDockHandler() dock_handler.addDockWidget( "BinSync: Control Panel", lambda n, p, d: create_widget(ControlPanelDockWidget, n, p, d, controller),
def addToolMenuAction(self, name, function): """ Adds an item to the tool menu (at the top of the window) without registering a plugin command """ UIAction.registerAction(name) UIActionHandler.globalActions().bindAction(name, UIAction(function)) self._tool_menu.addAction(name, function)
def bindActions(self): self.actionHandler.bindAction("archive\\cpio_old_le", UIAction(self.on_cpio_old_le)) self.actionHandler.bindAction("archive\\gzip", UIAction(self.on_gzip)) self.actionHandler.bindAction("archive\\lzh", UIAction(self.on_lzh)) self.actionHandler.bindAction("archive\\rar", UIAction(self.on_rar)) self.actionHandler.bindAction("archive\\zip", UIAction(self.on_zip)) self.actionHandler.bindAction("cad\\monomakh_sapr_chg", UIAction(self.on_monomakh_sapr_chg)) self.actionHandler.bindAction("common\\bcd", UIAction(self.on_bcd)) self.actionHandler.bindAction("database\\dbf", UIAction(self.on_dbf)) self.actionHandler.bindAction("database\\gettext_mo", UIAction(self.on_gettext_mo)) self.actionHandler.bindAction("database\\sqlite3", UIAction(self.on_sqlite3)) self.actionHandler.bindAction("database\\tsm", UIAction(self.on_tsm)) self.actionHandler.bindAction("executable\\dex", UIAction(self.on_dex)) self.actionHandler.bindAction("executable\\dos_mz", UIAction(self.on_dos_mz)) self.actionHandler.bindAction("executable\\elf", UIAction(self.on_elf)) self.actionHandler.bindAction("executable\\java_class", UIAction(self.on_java_class)) self.actionHandler.bindAction("executable\\mach_o", UIAction(self.on_mach_o)) self.actionHandler.bindAction("executable\\microsoft_pe", UIAction(self.on_microsoft_pe)) self.actionHandler.bindAction("executable\\python_pyc_27", UIAction(self.on_python_pyc_27)) self.actionHandler.bindAction("executable\\swf", UIAction(self.on_swf)) self.actionHandler.bindAction("filesystem\\apm_partition_table", UIAction(self.on_apm_partition_table)) self.actionHandler.bindAction("filesystem\\apple_single_double", UIAction(self.on_apple_single_double)) self.actionHandler.bindAction("filesystem\\cramfs", UIAction(self.on_cramfs)) self.actionHandler.bindAction("filesystem\\ext2", UIAction(self.on_ext2)) self.actionHandler.bindAction("filesystem\\gpt_partition_table", UIAction(self.on_gpt_partition_table)) self.actionHandler.bindAction("filesystem\\iso9660", UIAction(self.on_iso9660)) self.actionHandler.bindAction("filesystem\\luks", UIAction(self.on_luks)) self.actionHandler.bindAction("filesystem\\lvm2", UIAction(self.on_lvm2)) self.actionHandler.bindAction("filesystem\\mbr_partition_table", UIAction(self.on_mbr_partition_table)) self.actionHandler.bindAction("filesystem\\tr_dos_image", UIAction(self.on_tr_dos_image)) self.actionHandler.bindAction("filesystem\\vdi", UIAction(self.on_vdi)) self.actionHandler.bindAction("filesystem\\vfat", UIAction(self.on_vfat)) self.actionHandler.bindAction("filesystem\\vmware_vmdk", UIAction(self.on_vmware_vmdk)) self.actionHandler.bindAction("firmware\\andes_firmware", UIAction(self.on_andes_firmware)) self.actionHandler.bindAction("firmware\\ines", UIAction(self.on_ines)) self.actionHandler.bindAction("firmware\\uimage", UIAction(self.on_uimage)) self.actionHandler.bindAction("font\\ttf", UIAction(self.on_ttf)) self.actionHandler.bindAction("game\\allegro_dat", UIAction(self.on_allegro_dat)) self.actionHandler.bindAction("game\\doom_wad", UIAction(self.on_doom_wad)) self.actionHandler.bindAction("game\\dune_2_pak", UIAction(self.on_dune_2_pak)) self.actionHandler.bindAction("game\\fallout2_dat", UIAction(self.on_fallout2_dat)) self.actionHandler.bindAction("game\\fallout_dat", UIAction(self.on_fallout_dat)) self.actionHandler.bindAction("game\\ftl_dat", UIAction(self.on_ftl_dat)) self.actionHandler.bindAction("game\\gran_turismo_vol", UIAction(self.on_gran_turismo_vol)) self.actionHandler.bindAction("game\\heaps_pak", UIAction(self.on_heaps_pak)) self.actionHandler.bindAction("game\\heroes_of_might_and_magic_agg", UIAction(self.on_heroes_of_might_and_magic_agg)) self.actionHandler.bindAction("game\\heroes_of_might_and_magic_bmp", UIAction(self.on_heroes_of_might_and_magic_bmp)) self.actionHandler.bindAction("game\\quake_mdl", UIAction(self.on_quake_mdl)) self.actionHandler.bindAction("game\\quake_pak", UIAction(self.on_quake_pak)) self.actionHandler.bindAction("game\\renderware_binary_stream", UIAction(self.on_renderware_binary_stream)) self.actionHandler.bindAction("game\\saints_row_2_vpp_pc", UIAction(self.on_saints_row_2_vpp_pc)) self.actionHandler.bindAction("game\\warcraft_2_pud", UIAction(self.on_warcraft_2_pud)) self.actionHandler.bindAction("geospatial\\shapefile_index", UIAction(self.on_shapefile_index)) self.actionHandler.bindAction("geospatial\\shapefile_main", UIAction(self.on_shapefile_main)) self.actionHandler.bindAction("hardware\\edid", UIAction(self.on_edid)) self.actionHandler.bindAction("hardware\\mifare\\mifare_classic", UIAction(self.on_mifare_classic)) self.actionHandler.bindAction("image\\bmp", UIAction(self.on_bmp)) self.actionHandler.bindAction("image\\dicom", UIAction(self.on_dicom)) self.actionHandler.bindAction("image\\exif", UIAction(self.on_exif)) self.actionHandler.bindAction("image\\exif_be", UIAction(self.on_exif_be)) self.actionHandler.bindAction("image\\exif_le", UIAction(self.on_exif_le)) self.actionHandler.bindAction("image\\gif", UIAction(self.on_gif)) self.actionHandler.bindAction("image\\icc_4", UIAction(self.on_icc_4)) self.actionHandler.bindAction("image\\ico", UIAction(self.on_ico)) self.actionHandler.bindAction("image\\jpeg", UIAction(self.on_jpeg)) self.actionHandler.bindAction("image\\pcx", UIAction(self.on_pcx)) self.actionHandler.bindAction("image\\pcx_dcx", UIAction(self.on_pcx_dcx)) self.actionHandler.bindAction("image\\png", UIAction(self.on_png)) self.actionHandler.bindAction("image\\psx_tim", UIAction(self.on_psx_tim)) self.actionHandler.bindAction("image\\tga", UIAction(self.on_tga)) self.actionHandler.bindAction("image\\wmf", UIAction(self.on_wmf)) self.actionHandler.bindAction("image\\xwd", UIAction(self.on_xwd)) self.actionHandler.bindAction("log\\aix_utmp", UIAction(self.on_aix_utmp)) self.actionHandler.bindAction("log\\glibc_utmp", UIAction(self.on_glibc_utmp)) self.actionHandler.bindAction("log\\systemd_journal", UIAction(self.on_systemd_journal)) self.actionHandler.bindAction("log\\windows_evt_log", UIAction(self.on_windows_evt_log)) self.actionHandler.bindAction("machine_code\\code_6502", UIAction(self.on_code_6502)) self.actionHandler.bindAction("media\\avi", UIAction(self.on_avi)) self.actionHandler.bindAction("media\\blender_blend", UIAction(self.on_blender_blend)) self.actionHandler.bindAction("media\\creative_voice_file", UIAction(self.on_creative_voice_file)) self.actionHandler.bindAction("media\\genmidi_op2", UIAction(self.on_genmidi_op2)) self.actionHandler.bindAction("media\\id3v1_1", UIAction(self.on_id3v1_1)) self.actionHandler.bindAction("media\\id3v2_3", UIAction(self.on_id3v2_3)) self.actionHandler.bindAction("media\\id3v2_4", UIAction(self.on_id3v2_4)) self.actionHandler.bindAction("media\\magicavoxel_vox", UIAction(self.on_magicavoxel_vox)) self.actionHandler.bindAction("media\\ogg", UIAction(self.on_ogg)) self.actionHandler.bindAction("media\\quicktime_mov", UIAction(self.on_quicktime_mov)) self.actionHandler.bindAction("media\\standard_midi_file", UIAction(self.on_standard_midi_file)) self.actionHandler.bindAction("media\\stl", UIAction(self.on_stl)) self.actionHandler.bindAction("media\\tracker_modules\\fasttracker_xm_module", UIAction(self.on_fasttracker_xm_module)) self.actionHandler.bindAction("media\\tracker_modules\\s3m", UIAction(self.on_s3m)) self.actionHandler.bindAction("media\\vp8_ivf", UIAction(self.on_vp8_ivf)) self.actionHandler.bindAction("media\\wav", UIAction(self.on_wav)) self.actionHandler.bindAction("network\\bitcoin_transaction", UIAction(self.on_bitcoin_transaction)) self.actionHandler.bindAction("network\\dns_packet", UIAction(self.on_dns_packet)) self.actionHandler.bindAction("network\\hccap", UIAction(self.on_hccap)) self.actionHandler.bindAction("network\\hccapx", UIAction(self.on_hccapx)) self.actionHandler.bindAction("network\\icmp_packet", UIAction(self.on_icmp_packet)) if sys.version_info[0] == 3: self.actionHandler.bindAction("network\\ethernet_frame", UIAction(self.on_ethernet_frame)) self.actionHandler.bindAction("network\\ipv4_packet", UIAction(self.on_ipv4_packet)) self.actionHandler.bindAction("network\\ipv6_packet", UIAction(self.on_ipv6_packet)) self.actionHandler.bindAction("network\\microsoft_network_monitor_v2", UIAction(self.on_microsoft_network_monitor_v2)) self.actionHandler.bindAction("network\\packet_ppi", UIAction(self.on_packet_ppi)) self.actionHandler.bindAction("network\\pcap", UIAction(self.on_pcap)) self.actionHandler.bindAction("network\\protocol_body", UIAction(self.on_protocol_body)) self.actionHandler.bindAction("network\\rtcp_payload", UIAction(self.on_rtcp_payload)) self.actionHandler.bindAction("network\\rtp_packet", UIAction(self.on_rtp_packet)) self.actionHandler.bindAction("network\\tcp_segment", UIAction(self.on_tcp_segment)) self.actionHandler.bindAction("network\\tls_client_hello", UIAction(self.on_tls_client_hello)) self.actionHandler.bindAction("network\\udp_datagram", UIAction(self.on_udp_datagram)) self.actionHandler.bindAction("network\\windows_systemtime", UIAction(self.on_windows_systemtime)) self.actionHandler.bindAction("scientific\\nt_mdt\\nt_mdt", UIAction(self.on_nt_mdt)) self.actionHandler.bindAction("scientific\\nt_mdt\\nt_mdt_pal", UIAction(self.on_nt_mdt_pal)) self.actionHandler.bindAction("scientific\\spectroscopy\\avantes_roh60", UIAction(self.on_avantes_roh60)) self.actionHandler.bindAction("scientific\\spectroscopy\\specpr", UIAction(self.on_specpr)) self.actionHandler.bindAction("security\\openpgp_message", UIAction(self.on_openpgp_message)) self.actionHandler.bindAction("security\\ssh_public_key", UIAction(self.on_ssh_public_key)) self.actionHandler.bindAction("serialization\\asn1\\asn1_der", UIAction(self.on_asn1_der)) self.actionHandler.bindAction("serialization\\bson", UIAction(self.on_bson)) self.actionHandler.bindAction("serialization\\google_protobuf", UIAction(self.on_google_protobuf)) self.actionHandler.bindAction("serialization\\microsoft_cfb", UIAction(self.on_microsoft_cfb)) self.actionHandler.bindAction("serialization\\msgpack", UIAction(self.on_msgpack)) self.actionHandler.bindAction("serialization\\ruby_marshal", UIAction(self.on_ruby_marshal)) self.actionHandler.bindAction("windows\\regf", UIAction(self.on_regf)) self.actionHandler.bindAction("windows\\windows_lnk_file", UIAction(self.on_windows_lnk_file)) self.actionHandler.bindAction("windows\\windows_minidump", UIAction(self.on_windows_minidump)) self.actionHandler.bindAction("windows\\windows_resource_file", UIAction(self.on_windows_resource_file)) self.actionHandler.bindAction("windows\\windows_shell_items", UIAction(self.on_windows_shell_items)) self.actionHandler.bindAction("windows\\windows_systemtime", UIAction(self.on_windows_systemtime))
def __init__(self, parent, data): if not type(data) == BinaryView: raise Exception('expected widget data to be a BinaryView') self.bv = data self.debug_state = binjaplug.get_state(data) memory_view = self.debug_state.memory_view self.debug_state.ui.debug_view = self QWidget.__init__(self, parent) self.controls = ControlsWidget.DebugControlsWidget(self, "Controls", data, self.debug_state) View.__init__(self) self.setupView(self) self.current_offset = 0 self.splitter = QSplitter(Qt.Orientation.Horizontal, self) frame = ViewFrame.viewFrameForWidget(self) self.memory_editor = LinearView(memory_view, frame) self.binary_editor = DisassemblyContainer(frame, data, frame) self.binary_text = TokenizedTextView(self, memory_view) self.is_raw_disassembly = False self.raw_address = 0 self.is_navigating_history = False self.memory_history_addr = 0 # TODO: Handle these and change views accordingly # Currently they are just disabled as the DisassemblyContainer gets confused # about where to go and just shows a bad view self.binary_editor.getDisassembly().actionHandler().bindAction("View in Hex Editor", UIAction()) self.binary_editor.getDisassembly().actionHandler().bindAction("View in Linear Disassembly", UIAction()) self.binary_editor.getDisassembly().actionHandler().bindAction("View in Types View", UIAction()) self.memory_editor.actionHandler().bindAction("View in Hex Editor", UIAction()) self.memory_editor.actionHandler().bindAction("View in Disassembly Graph", UIAction()) self.memory_editor.actionHandler().bindAction("View in Types View", UIAction()) small_font = QApplication.font() small_font.setPointSize(11) bv_layout = QVBoxLayout() bv_layout.setSpacing(0) bv_layout.setContentsMargins(0, 0, 0, 0) bv_label = QLabel("Loaded File") bv_label.setFont(small_font) bv_layout.addWidget(bv_label) bv_layout.addWidget(self.binary_editor) self.bv_widget = QWidget() self.bv_widget.setLayout(bv_layout) disasm_layout = QVBoxLayout() disasm_layout.setSpacing(0) disasm_layout.setContentsMargins(0, 0, 0, 0) disasm_label = QLabel("Raw Disassembly at PC") disasm_label.setFont(small_font) disasm_layout.addWidget(disasm_label) disasm_layout.addWidget(self.binary_text) self.disasm_widget = QWidget() self.disasm_widget.setLayout(disasm_layout) memory_layout = QVBoxLayout() memory_layout.setSpacing(0) memory_layout.setContentsMargins(0, 0, 0, 0) memory_label = QLabel("Debugged Process") memory_label.setFont(small_font) memory_layout.addWidget(memory_label) memory_layout.addWidget(self.memory_editor) self.memory_widget = QWidget() self.memory_widget.setLayout(memory_layout) self.splitter.addWidget(self.bv_widget) self.splitter.addWidget(self.memory_widget) # Equally sized self.splitter.setSizes([0x7fffffff, 0x7fffffff]) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.addWidget(self.controls) layout.addWidget(self.splitter, 100) self.setLayout(layout) self.needs_update = True self.update_timer = QTimer(self) self.update_timer.setInterval(200) self.update_timer.setSingleShot(False) self.update_timer.timeout.connect(lambda: self.updateTimerEvent()) self.add_scripting_ref()
def registerActions(self): # add all action handlers UIAction.registerAction("archive\\cpio_old_le") UIAction.registerAction("archive\\gzip") UIAction.registerAction("archive\\lzh") UIAction.registerAction("archive\\rar") UIAction.registerAction("archive\\zip") UIAction.registerAction("cad\\monomakh_sapr_chg") UIAction.registerAction("common\\bcd") UIAction.registerAction("database\\dbf") UIAction.registerAction("database\\gettext_mo") UIAction.registerAction("database\\sqlite3") UIAction.registerAction("database\\tsm") UIAction.registerAction("executable\\dex") UIAction.registerAction("executable\\dos_mz") UIAction.registerAction("executable\\elf") UIAction.registerAction("executable\\java_class") UIAction.registerAction("executable\\mach_o") UIAction.registerAction("executable\\microsoft_pe") UIAction.registerAction("executable\\python_pyc_27") UIAction.registerAction("executable\\swf") UIAction.registerAction("filesystem\\apm_partition_table") UIAction.registerAction("filesystem\\apple_single_double") UIAction.registerAction("filesystem\\cramfs") UIAction.registerAction("filesystem\\ext2") UIAction.registerAction("filesystem\\gpt_partition_table") UIAction.registerAction("filesystem\\iso9660") UIAction.registerAction("filesystem\\luks") UIAction.registerAction("filesystem\\lvm2") UIAction.registerAction("filesystem\\mbr_partition_table") UIAction.registerAction("filesystem\\tr_dos_image") UIAction.registerAction("filesystem\\vdi") UIAction.registerAction("filesystem\\vfat") UIAction.registerAction("filesystem\\vmware_vmdk") UIAction.registerAction("firmware\\andes_firmware") UIAction.registerAction("firmware\\ines") UIAction.registerAction("firmware\\uimage") UIAction.registerAction("font\\ttf") UIAction.registerAction("game\\allegro_dat") UIAction.registerAction("game\\doom_wad") UIAction.registerAction("game\\dune_2_pak") UIAction.registerAction("game\\fallout2_dat") UIAction.registerAction("game\\fallout_dat") UIAction.registerAction("game\\ftl_dat") UIAction.registerAction("game\\gran_turismo_vol") UIAction.registerAction("game\\heaps_pak") UIAction.registerAction("game\\heroes_of_might_and_magic_agg") UIAction.registerAction("game\\heroes_of_might_and_magic_bmp") UIAction.registerAction("game\\quake_mdl") UIAction.registerAction("game\\quake_pak") UIAction.registerAction("game\\renderware_binary_stream") UIAction.registerAction("game\\saints_row_2_vpp_pc") UIAction.registerAction("game\\warcraft_2_pud") UIAction.registerAction("geospatial\\shapefile_index") UIAction.registerAction("geospatial\\shapefile_main") UIAction.registerAction("hardware\\edid") UIAction.registerAction("hardware\\mifare\\mifare_classic") UIAction.registerAction("image\\bmp") UIAction.registerAction("image\\dicom") UIAction.registerAction("image\\exif") UIAction.registerAction("image\\exif_be") UIAction.registerAction("image\\exif_le") UIAction.registerAction("image\\gif") UIAction.registerAction("image\\icc_4") UIAction.registerAction("image\\ico") UIAction.registerAction("image\\jpeg") UIAction.registerAction("image\\pcx") UIAction.registerAction("image\\pcx_dcx") UIAction.registerAction("image\\png") UIAction.registerAction("image\\psx_tim") UIAction.registerAction("image\\tga") UIAction.registerAction("image\\wmf") UIAction.registerAction("image\\xwd") UIAction.registerAction("log\\aix_utmp") UIAction.registerAction("log\\glibc_utmp") UIAction.registerAction("log\\systemd_journal") UIAction.registerAction("log\\windows_evt_log") UIAction.registerAction("machine_code\\code_6502") UIAction.registerAction("media\\avi") UIAction.registerAction("media\\blender_blend") UIAction.registerAction("media\\creative_voice_file") UIAction.registerAction("media\\genmidi_op2") UIAction.registerAction("media\\id3v1_1") UIAction.registerAction("media\\id3v2_3") UIAction.registerAction("media\\id3v2_4") UIAction.registerAction("media\\magicavoxel_vox") UIAction.registerAction("media\\ogg") UIAction.registerAction("media\\quicktime_mov") UIAction.registerAction("media\\standard_midi_file") UIAction.registerAction("media\\stl") UIAction.registerAction("media\\tracker_modules\\fasttracker_xm_module") UIAction.registerAction("media\\tracker_modules\\s3m") UIAction.registerAction("media\\vp8_ivf") UIAction.registerAction("media\\wav") UIAction.registerAction("network\\bitcoin_transaction") UIAction.registerAction("network\\dns_packet") UIAction.registerAction("network\\hccap") UIAction.registerAction("network\\hccapx") UIAction.registerAction("network\\icmp_packet") # currently on py3 can handle the circular dependency hell if sys.version_info[0] == 3: UIAction.registerAction("network\\ethernet_frame") UIAction.registerAction("network\\ipv4_packet") UIAction.registerAction("network\\ipv6_packet") UIAction.registerAction("network\\microsoft_network_monitor_v2") UIAction.registerAction("network\\packet_ppi") UIAction.registerAction("network\\pcap") UIAction.registerAction("network\\protocol_body") UIAction.registerAction("network\\rtcp_payload") UIAction.registerAction("network\\rtp_packet") UIAction.registerAction("network\\tcp_segment") UIAction.registerAction("network\\tls_client_hello") UIAction.registerAction("network\\udp_datagram") UIAction.registerAction("network\\windows_systemtime") UIAction.registerAction("scientific\\nt_mdt\\nt_mdt") UIAction.registerAction("scientific\\nt_mdt\\nt_mdt_pal") UIAction.registerAction("scientific\\spectroscopy\\avantes_roh60") UIAction.registerAction("scientific\\spectroscopy\\specpr") UIAction.registerAction("security\\openpgp_message") UIAction.registerAction("security\\ssh_public_key") UIAction.registerAction("serialization\\asn1\\asn1_der") UIAction.registerAction("serialization\\bson") UIAction.registerAction("serialization\\google_protobuf") UIAction.registerAction("serialization\\microsoft_cfb") UIAction.registerAction("serialization\\msgpack") UIAction.registerAction("serialization\\ruby_marshal") UIAction.registerAction("windows\\regf") UIAction.registerAction("windows\\windows_lnk_file") UIAction.registerAction("windows\\windows_minidump") UIAction.registerAction("windows\\windows_resource_file") UIAction.registerAction("windows\\windows_shell_items") UIAction.registerAction("windows\\windows_systemtime")
"\n") outputSnippet.write(self.edit.toPlainText()) outputSnippet.close() self.registerAllSnippets() def clearHotkey(self): self.keySequenceEdit.clear() snippets = None def launchPlugin(context): global snippets if not snippets: snippets = Snippets(context, parent=context.widget) snippets.show() if __name__ == '__main__': app = QApplication(sys.argv) snippets = Snippets(None) snippets.show() sys.exit(app.exec_()) else: Snippets.registerAllSnippets() UIAction.registerAction("Snippets\\Snippet Editor...") UIActionHandler.globalActions().bindAction("Snippets\\Snippet Editor...", UIAction(launchPlugin)) Menu.mainMenu("Tools").addAction("Snippets\\Snippet Editor...", "Snippet")
from .types.libimport import browse_type_library from binaryninja import PluginCommand from binaryninjaui import UIAction, UIActionHandler, Menu, ViewType from .types.export import export_type_library from .types.make_struct import make_struct_here from .functions.callgraph import CallGraphViewType UIAction.registerAction( "Reverse Engineer's Toolkit\\Types\\Export Type Library") UIActionHandler.globalActions().bindAction( "Reverse Engineer's Toolkit\\Types\\Export Type Library", UIAction(export_type_library, lambda ctx: ctx.binaryView is not None), ) Menu.mainMenu("Tools").addAction( "Reverse Engineer's Toolkit\\Types\\Export Type Library", "Export Type Library") UIAction.registerAction( "Reverse Engineer's Toolkit\\Types\\Import Type Library") UIActionHandler.globalActions().bindAction( "Reverse Engineer's Toolkit\\Types\\Import Type Library", UIAction(browse_type_library, lambda ctx: ctx.binaryView is not None), ) Menu.mainMenu("Tools").addAction( "Reverse Engineer's Toolkit\\Types\\Import Type Library", "Import Type Library") PluginCommand.register_for_range( "Make Structure Here", "Make a structure from this range of data variables",