def repositionCaret(self): self.updateCache() found = False for i in range(0, len(self.lines)): if (((self.cursorAddr >= self.lines[i].address) and (self.cursorAddr < (self.lines[i].address + self.lines[i].length))) or (((i + 1) == len(self.lines)) and (self.cursorAddr == (self.lines[i].address + self.lines[i].length)))): if i < self.topLine: self.topLine = i elif i > (self.topLine + self.visibleRows - 1): self.topLine = i - (self.visibleRows - 1) self.updatingScrollBar = True addr = self.lines[self.topLine].address self.verticalScrollBar().setValue( self.getContiguousOffsetForAddress(addr) // self.scrollBarMultiplier) self.updatingScrollBar = False self.updateCache() self.viewport().update() found = True break if not found: self.setTopToAddress(self.cursorAddr) self.refreshLines() self.showContextAroundTop() # Force caret to be visible and repaint self.caretBlink = True self.cursorTimer.stop() self.cursorTimer.start() self.updateCaret() UIContext.updateStatus()
def executeSnippet(code, description): #Get UI context, try currently selected otherwise default to the first one if the snippet widget is selected. ctx = UIContext.activeContext() dummycontext = { 'binaryView': None, 'address': None, 'function': None, 'token': None, 'lowLevelILFunction': None, 'mediumLevelILFunction': None } if not ctx: ctx = UIContext.allContexts()[0] if not ctx: #There is no tab open at all but we still want other snippest to run that don't rely on context. context = namedtuple("context", dummycontext.keys())(*dummycontext.values()) else: handler = ctx.contentActionHandler() if handler: context = handler.actionContext() else: context = namedtuple("context", dummycontext.keys())(*dummycontext.values()) snippetGlobals = setupGlobals(context) SnippetTask(code, snippetGlobals, context, snippetName=description).start()
def __init__(self): UIContextNotification.__init__(self) UIContext.registerNotification(self) self.request_handler = RequestHandler(self) self.client_listener = None self.client = None self.next_tab_lock = threading.Event() self.pgm_mgr = ProgramManager() # binary ninja objects self.widget = None self.view_frame = None self.view = None self.binary_view = None self.frame = None # context self.current_tab = None self.current_pgm = None self.target_tab = None self.base = None self.base_remote = None self.sync_enabled = False self.sync_mode_auto = True self.cb_trace_enabled = False
def __init__(self, widget): UIContextNotification.__init__(self) self.widget = widget # __del__ will not be called because the widget owns a reference to this object. Use # QWidget.destroyed event to know when to stop listening for notifications. self.widget.destroyed.connect(self.destroyed) UIContext.registerNotification(self)
def display_block(bv, addr): view = bv.view # Navigate to location in view result = bv.file.navigate(view, addr) if result is False: view = "Linear:" + view.split(":")[1] result = bv.file.navigate(view, addr) # Switch displayed view UIContext.activeContext().navigateForBinaryView(bv, addr)
def selectNone(self): for i in self.lines: if (self.cursorAddr >= i.address) and (self.cursorAddr < (i.address + i.length)) and i.separator: self.cursorAddr = i.address + i.length break self.selectionStartAddr = self.cursorAddr if self.selectionVisible: self.viewport().update() self.repositionCaret() UIContext.updateStatus()
def view_memory(self): memory_view = self.parent().view.session_data['emulator.memory.view'] ctx = UIContext.activeContext() linear_view = LinearView(memory_view, None) memory_view.register_notification(linear_view) ctx.createTabForWidget('Emulator Memory', linear_view)
def current_function(self, message_box=False) -> Optional[Function]: all_contexts = UIContext.allContexts() if not all_contexts: if message_box: show_message_box( "UI contexts not found", "No UI context is available. Please open a binary first.", MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.ErrorIcon, ) return ctx = all_contexts[0] handler = ctx.contentActionHandler() if handler is None: if message_box: show_message_box( "Action handler not found", "No action handler is available. Please open a binary first.", MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.ErrorIcon, ) return actionContext = handler.actionContext() func = actionContext.function if func is None: if message_box: show_message_box( "No function is in selection", "Please navigate to a function in the disassembly view.", MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.ErrorIcon, ) return None return func
def init(self): self.raw = self.data self.binary = self.raw.read(0, len(self.raw)) macho_list = self.get_macho_names(self.data, len(self.raw)) print(f"Found {len(macho_list)} apps") [print(f" - {macho}") for macho in macho_list] offset = self.get_header_offset() sep_fw_header = self.get_fw_header(offset) offset += 0xC8 choice = interaction.get_choice_input("sep-firmware modules", "choices", macho_list) if choice is not None: print(f"extracting {macho_list[choice]}") if choice == 0: app = self.extract_sepos_kernel(sep_fw_header) elif choice == 1: app = self.extract_sepos_root(sep_fw_header) else: name = macho_list[choice] app = self.process_apps(sep_fw_header, offset, name, choice) mainthread.execute_on_main_thread_and_wait( lambda: UIContext.allContexts()[0].openFilename(app)) else: return False return True
def __init__(self, parent, view, data): super(ExportsWidget, self).__init__(parent) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.imports = ExportsTreeView(self, view, data) self.filter = FilteredView(self, self.imports, self.imports) layout.addWidget(self.filter, 1) self.setLayout(layout) self.setMinimumSize(UIContext.getScaledWindowSize(100, 196))
def refreshLines(self): addr = self.topAddr self.lines = [] self.topLine = 0 self.bottomAddr = self.topAddr self.updateRanges() if self.allocatedLength > 0x7fffffff: self.scrollBarMultiplier = (self.allocatedLength // 0x7fffffff) + 1 else: self.scrollBarMultiplier = 1 self.updatingScrollBar = True self.verticalScrollBar().setRange(0, (self.allocatedLength - 1) // self.scrollBarMultiplier) self.verticalScrollBar().setValue( self.getContiguousOffsetForAddress(addr) // self.scrollBarMultiplier) self.updatingScrollBar = False self.updateCache() self.viewport().update() UIContext.updateStatus()
def __init__(self, parent, data): super(SegmentsWidget, self).__init__(parent) layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setVerticalSpacing(1) layout.setHorizontalSpacing( UIContext.getScaledWindowSize(16, 16).width()) self.segments = [] for segment in data.segments: if segment.readable or segment.writable or segment.executable: self.segments.append(segment) self.segments.sort(key=lambda segment: segment.start) row = 0 for segment in self.segments: begin = "0x%x" % segment.start end = "0x%x" % segment.end permissions = "" if segment.readable: permissions += "r" else: permissions += "-" if segment.writable: permissions += "w" else: permissions += "-" if segment.executable: permissions += "x" else: permissions += "-" rangeLayout = QHBoxLayout() rangeLayout.setContentsMargins(0, 0, 0, 0) beginLabel = headers.ClickableAddressLabel(begin) dashLabel = QLabel("-") dashLabel.setFont(binaryninjaui.getMonospaceFont(self)) endLabel = headers.ClickableAddressLabel(end) rangeLayout.addWidget(beginLabel) rangeLayout.addWidget(dashLabel) rangeLayout.addWidget(endLabel) layout.addLayout(rangeLayout, row, 0) permissionsLabel = QLabel(permissions) permissionsLabel.setFont(binaryninjaui.getMonospaceFont(self)) layout.addWidget(permissionsLabel, row, 1) row += 1 layout.setColumnStretch(2, 1) self.setLayout(layout)
def add_function_hook(emulator, function): ctx = UIContext.activeContext() handler = ctx.globalActions() hook_options = [ a for a in handler.getAllValidActions() if "Snippets\\" in a and "emulator" in a.lower() ] snippets = ChoiceField("Snippets:", hook_options) get_form_input([snippets], "Add Function Hook") choice = hook_options[snippets.result]
def execute(self, il: LowLevelILInstruction): function = self.hooks.get(il.function, {}) hook = function.get(il.instr_index) if hook is None: super().execute(il) else: ctx = UIContext.contextForWidget( self.view.session_data['emulator.memory.widget']) handler = ctx.contentActionHandler() handler.executeAction(hook) if self.current_instr_index == il.instr_index: self.set_next_instr_index(il.function, il.instr_index + 1)
def remove_hook(self): emulator = self.parent().view.session_data['emulator'] ctx = UIContext.activeContext() content = ctx.contentActionHandler() action_context = content.actionContext() llil = action_context.lowLevelILFunction instr_index = action_context.instrIndex if None in (llil, instr_index) or instr_index == 0xffffffffffffffff: log.log_alert('LLIL Function/Instruction not selected!') return remove_hook(emulator, llil[instr_index])
def updateState(self): # Get the currently active view frame for this group of panes. There can be # multiple view frames in a single window, or the pane could be popped out # into its own window. UIContext.currentViewFrameForWidget will determine # the best view frame to use for context. frame = UIContext.currentViewFrameForWidget(self) # 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 __init__(self, parent, header): super(HeaderWidget, self).__init__(parent) layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setVerticalSpacing(1) row = 0 col = 0 for field in header.fields: name = field[0] value = field[1] fieldType = "" if len(field) > 2: fieldType = field[2] layout.addWidget(QLabel(name + ": "), row, col * 3) if isinstance(value, list): for i in range(0, len(value)): if fieldType == "ptr": label = ClickableAddressLabel(value[i]) elif fieldType == "code": label = ClickableCodeLabel(value[i]) else: label = QLabel(value[i]) label.setFont(binaryninjaui.getMonospaceFont(self)) layout.addWidget(label, row, col * 3 + 1) row += 1 else: if fieldType == "ptr": label = ClickableAddressLabel(value) elif fieldType == "code": label = ClickableCodeLabel(value) else: label = QLabel(value) label.setFont(binaryninjaui.getMonospaceFont(self)) layout.addWidget(label, row, col * 3 + 1) row += 1 if (header.columns > 1) and (row >= header.rows_per_column) and ( (col + 1) < header.columns): row = 0 col += 1 for col in range(1, header.columns): layout.setColumnMinimumWidth( col * 3 - 1, UIContext.getScaledWindowSize(20, 20).width()) layout.setColumnStretch(header.columns * 3 - 1, 1) self.setLayout(layout)
def add_hook(emulator, instruction): ctx = UIContext.activeContext() handler = ctx.globalActions() hook_options = [ a for a in handler.getAllValidActions() if "Snippets\\" in a and "emulator" in a.lower() ] snippets = ChoiceField("Snippets:", hook_options) get_form_input([snippets], "Add Hook") choice = hook_options[snippets.result] emulator.add_hook(instruction, choice) instruction.function.source_function.set_auto_instr_highlight( instruction.address, HighlightStandardColor.BlackHighlightColor )
def active_context(self): all_contexts = UIContext.allContexts() if not all_contexts: return None ctx = all_contexts[0] handler = ctx.contentActionHandler() if handler is None: return None actionContext = handler.actionContext() func = actionContext.function if func is None: return None return binsync.data.Function(func.start, 0, header=FunctionHeader( func.name, func.start))
def __init__(self, parent, view, data): super(EntropyWidget, self).__init__(parent) self.view = view self.data = data self.raw_data = data.file.raw self.block_size = (len(self.raw_data) / 4096) + 1 if self.block_size < 1024: self.block_size = 1024 self.width = int(len(self.raw_data) / self.block_size) self.image = QImage(self.width, 1, QImage.Format_ARGB32) self.image.fill(QColor(0, 0, 0, 0)) self.thread = EntropyThread(self.raw_data, self.image, self.block_size) self.started = False self.timer = QTimer() self.timer.timeout.connect(self.timerEvent) self.timer.setInterval(100) self.timer.setSingleShot(False) self.timer.start() self.setMinimumHeight(UIContext.getScaledWindowSize(32, 32).height())
def setCurrentOffset(self, offset): #log.log_debug('setCurrentOffset(0x%X)' % offset) self.rootSelectionStart = offset UIContext.updateStatus(True)
def destroyed(self): UIContext.unregisterNotification(self)
def __init__(self, parent, data): super(SectionsWidget, self).__init__(parent) layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setVerticalSpacing(1) layout.setHorizontalSpacing( UIContext.getScaledWindowSize(16, 16).width()) maxNameLen = 0 for section in data.sections.values(): if len(section.name) > maxNameLen: maxNameLen = len(section.name) if maxNameLen > 32: maxNameLen = 32 self.sections = [] for section in data.sections.values(): if section.semantics != SectionSemantics.ExternalSectionSemantics: self.sections.append(section) self.sections.sort(key=lambda section: section.start) row = 0 for section in self.sections: name = section.name if len(name) > maxNameLen: name = name[:maxNameLen - 1] + "…" begin = "0x%x" % section.start end = "0x%x" % section.end typeName = section.type permissions = "" if data.is_offset_readable(section.start): permissions += "r" else: permissions += "-" if data.is_offset_writable(section.start): permissions += "w" else: permissions += "-" if data.is_offset_executable(section.start): permissions += "x" else: permissions += "-" semantics = "" if section.semantics == SectionSemantics.ReadOnlyCodeSectionSemantics: semantics = "Code" elif section.semantics == SectionSemantics.ReadOnlyDataSectionSemantics: semantics = "Ready-only Data" elif section.semantics == SectionSemantics.ReadWriteDataSectionSemantics: semantics = "Writable Data" nameLabel = QLabel(name) nameLabel.setFont(binaryninjaui.getMonospaceFont(self)) layout.addWidget(nameLabel, row, 0) rangeLayout = QHBoxLayout() rangeLayout.setContentsMargins(0, 0, 0, 0) beginLabel = headers.ClickableAddressLabel(begin) dashLabel = QLabel("-") dashLabel.setFont(binaryninjaui.getMonospaceFont(self)) endLabel = headers.ClickableAddressLabel(end) rangeLayout.addWidget(beginLabel) rangeLayout.addWidget(dashLabel) rangeLayout.addWidget(endLabel) layout.addLayout(rangeLayout, row, 1) permissionsLabel = QLabel(permissions) permissionsLabel.setFont(binaryninjaui.getMonospaceFont(self)) layout.addWidget(permissionsLabel, row, 2) typeLabel = QLabel(typeName) typeLabel.setFont(binaryninjaui.getMonospaceFont(self)) layout.addWidget(typeLabel, row, 3) semanticsLabel = QLabel(semantics) semanticsLabel.setFont(binaryninjaui.getMonospaceFont(self)) layout.addWidget(semanticsLabel, row, 4) row += 1 layout.setColumnStretch(5, 1) self.setLayout(layout)
def __init__(self, parent, data): assert type(data) == BinaryView self.bv = data QDialog.__init__(self, parent) debug_state = binjaplug.get_state(self.bv) self.setWindowTitle("Debug Adapter Settings") self.setMinimumSize(UIContext.getScaledWindowSize(400, 130)) self.setAttribute(Qt.WA_DeleteOnClose) layout = QVBoxLayout() layout.setSpacing(0) titleLabel = QLabel("Adapter Settings") titleLayout = QHBoxLayout() titleLayout.setContentsMargins(0, 0, 0, 0) titleLayout.addWidget(titleLabel) self.adapterEntry = QPushButton(self) self.adapterMenu = QMenu(self) for adapter in DebugAdapter.ADAPTER_TYPE: if not DebugAdapter.ADAPTER_TYPE.can_use(adapter): continue def select_adapter(adapter): return lambda: self.selectAdapter(adapter) self.adapterMenu.addAction(adapter.name, select_adapter(adapter)) if adapter == debug_state.adapter_type: self.adapterEntry.setText(adapter.name) self.adapterEntry.setMenu(self.adapterMenu) self.argumentsEntry = QLineEdit(self) self.addressEntry = QLineEdit(self) self.portEntry = QLineEdit(self) self.requestTerminalEmulator = QCheckBox(self) self.formLayout = QFormLayout() self.formLayout.addRow("Adapter Type", self.adapterEntry) self.formLayout.addRow("Command Line Arguments", self.argumentsEntry) self.formLayout.addRow("Address", self.addressEntry) self.formLayout.addRow("Port", self.portEntry) self.formLayout.addRow("Request Terminal Emulator", self.requestTerminalEmulator) buttonLayout = QHBoxLayout() buttonLayout.setContentsMargins(0, 0, 0, 0) self.cancelButton = QPushButton("Cancel") self.cancelButton.clicked.connect(lambda: self.reject()) self.acceptButton = QPushButton("Accept") self.acceptButton.clicked.connect(lambda: self.accept()) self.acceptButton.setDefault(True) buttonLayout.addStretch(1) buttonLayout.addWidget(self.cancelButton) buttonLayout.addWidget(self.acceptButton) layout.addLayout(titleLayout) layout.addSpacing(10) layout.addLayout(self.formLayout) layout.addStretch(1) layout.addSpacing(10) layout.addLayout(buttonLayout) self.setLayout(layout) self.addressEntry.setText(debug_state.remote_host) self.portEntry.setText(str(debug_state.remote_port)) self.addressEntry.textEdited.connect(lambda: self.apply()) self.portEntry.textEdited.connect(lambda: self.apply()) self.argumentsEntry.setText(' '.join( shlex.quote(arg) for arg in debug_state.command_line_args)) self.argumentsEntry.textEdited.connect(lambda: self.updateArguments()) self.requestTerminalEmulator.setChecked( debug_state.request_terminal_emulator) self.requestTerminalEmulator.stateChanged.connect(lambda: self.apply()) self.accepted.connect(lambda: self.apply())
"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...")
def setCurrentOffset(self, offset): self.currentOffset = offset UIContext.updateStatus(True)
def __init__(self, parent, data): assert type(data) == binaryninja.binaryview.BinaryView self.bv = data QDialog.__init__(self, parent) self.setWindowTitle("Debug Adapter Settings") self.setMinimumSize(UIContext.getScaledWindowSize(400, 130)) self.setAttribute(Qt.WA_DeleteOnClose) layout = QVBoxLayout() layout.setSpacing(0) titleLabel = QLabel("Adapter Settings") titleLayout = QHBoxLayout() titleLayout.setContentsMargins(0, 0, 0, 0) titleLayout.addWidget(titleLabel) self.argumentsEntry = QLineEdit(self) # self.addressEntry = QLineEdit(self) # self.portEntry = QLineEdit(self) formLayout = QFormLayout() formLayout.addRow("Command Line Arguments", self.argumentsEntry) # formLayout.addRow("Address", self.addressEntry) # formLayout.addRow("Port", self.portEntry) buttonLayout = QHBoxLayout() buttonLayout.setContentsMargins(0, 0, 0, 0) self.cancelButton = QPushButton("Cancel") self.cancelButton.clicked.connect(lambda: self.reject()) self.acceptButton = QPushButton("Accept") self.acceptButton.clicked.connect(lambda: self.accept()) self.acceptButton.setDefault(True) buttonLayout.addStretch(1) buttonLayout.addWidget(self.cancelButton) buttonLayout.addWidget(self.acceptButton) layout.addLayout(titleLayout) layout.addSpacing(10) layout.addLayout(formLayout) layout.addStretch(1) layout.addSpacing(10) layout.addLayout(buttonLayout) self.setLayout(layout) debug_state = binjaplug.get_state(self.bv) # settings = Settings() # address = settings.get_string_with_scope("debugger.adapter.address", data, SettingsScope.SettingsContextScope) # port = settings.get_integer_with_scope("debugger.adapter.port", data, SettingsScope.SettingsContextScope) # self.addressEntry.setText(address[0]) # self.portEntry.setText(str(port[0])) # self.addressEntry.textEdited.connect(lambda: self.updateSettings()) # self.portEntry.textEdited.connect(lambda: self.updateSettings()) self.argumentsEntry.setText(' ' .join(shlex.quote(arg) for arg in debug_state.command_line_args)) self.argumentsEntry.textEdited.connect(lambda: self.updateArguments()) self.accepted.connect(lambda: self.apply())
def selectAll(self): self.selectionStartAddr = self.getStart() self.cursorAddr = self.getEnd() self.viewport().update() UIContext.updateStatus()
def open_file_tab(filename: str): # TODO: Save libc analysis? (Renaming symbols might cause some issues...) execute_on_main_thread_and_wait( lambda: UIContext.allContexts()[0].openFilename(filename) )