def register() -> None: PluginCommand.register( "Screenshot Ninja \\ Capture view image @ 1x...", "Save an image of the currently visible linear/graph view at 1x scaling", lambda bv: _ui_save_image(bv, False, 1), ) PluginCommand.register( "Screenshot Ninja \\ Capture view image @ 2x...", "Save an image of the currently visible linear/graph view at 2x scaling", lambda bv: _ui_save_image(bv, False, 2), ) PluginCommand.register( "Screenshot Ninja \\ Capture view image...", "Save an image of the currently visible linear/graph view at custom scaling", lambda bv: _ui_save_image(bv, False), ) PluginCommand.register( "Screenshot Ninja \\ Capture window image @ 1x...", "Save an image of the main window at 1x scaling", lambda bv: _ui_save_image(bv, True, 1), ) PluginCommand.register( "Screenshot Ninja \\ Capture window image @ 2x...", "Save an image of the main window at 2x scaling", lambda bv: _ui_save_image(bv, True, 2), ) PluginCommand.register( "Screenshot Ninja \\ Capture window image...", "Save an image of the main window at custom scaling", lambda bv: _ui_save_image(bv, True), )
def _install_open_coverage_overview(self): PluginCommand.register("Lighthouse - Coverage Overview", "Open the database code coverage overview", self.interactive_load_batch) logger.info("Installed the 'Coverage Overview' menu entry")
rpc.register_instance(Lobotomy(rpc, bv)) print("[*] Started lobotomy service (!)") while True: # Handle inbound requests rpc.handle_request() except Exception as e: ExceptionHandler(e) def start_thread(bv): """ Create a new thread that will run the lobotomy service """ global t global running print(bv) try: t = threading.Thread(target=start_lobotomy, args=[bv]) t.daemon = True t.start() if not running: running = True except Exception as e: ExceptionHandler(e) # Register plugin PluginCommand.register("jni", "Find all registered JNI functions", start_thread)
rules = [RULES_DIR] paths = Settings().get_string("yara.customRulesPath") for path in paths.split(";"): rules.append(path.strip()) ys = YaraScan(bv, directories=rules) ys.start() def scan_with_file(bv): filepath = get_open_filename_input("Open YARA rule", "YARA rules (*.yar *.yara)") if filepath: ys = YaraScan(bv, filepath=filepath.decode()) ys.start() def crypto_scan(bv): crypto_rules = RULES_DIR + os.sep + "crypto_signatures.yar" ys = YaraScan(bv, filepath=crypto_rules) ys.start() PluginCommand.register("YARA\\Scan", "Scan file using YARA rules", scan) PluginCommand.register("YARA\\Scan with File", "Scan file using a specific YARA rule", scan_with_file) PluginCommand.register( "YARA\\Scan for Crypto", "Scan file for known crypto constants using YARA rules", crypto_scan)
def _install_load_file(self): PluginCommand.register("Lighthouse - Load code coverage file...", "Load individual code coverage file(s)", self.interactive_load_file) logger.info("Installed the 'Code coverage file' menu entry")
from binaryninja import PluginCommand, Architecture from .coverage import function_coverage_start from .evm import EVM, EVMView from .flowgraph import render_flowgraphs def is_valid_evm(view, function=None): return view.arch == Architecture['EVM'] PluginCommand.register(r"Ethersplay\Manticore Highlight", "EVM Manticore Highlight", function_coverage_start, is_valid=is_valid_evm) PluginCommand.register( r'Ethersplay\Render Flowgraphs', 'Render flowgraphs of every function, removing stack variable annotations', render_flowgraphs, is_valid=is_valid_evm) EVM.register() EVMView.register()
if ptr_s == 4: bv.define_data_var(addr, bv.parse_type_string('uint32_t x')[0]) if not isinstance(f, Symbol): s = Symbol(SymbolType.DataSymbol, addr, "ecall_table_size") bv.define_user_symbol(s) ecalls_count = unpack('I', bv.read(addr, 4))[0] else: bv.define_data_var(addr, bv.parse_type_string('uint64_t x')[0]) if not isinstance(f, Symbol): s = Symbol(SymbolType.DataSymbol, addr, "ecall_table_size") bv.define_user_symbol(s) ecalls_count = unpack('Q', bv.read(addr, 8))[0] log_info(f"identified {ecalls_count} ecalls") table_addr = addr + ptr_s table_type, _ = bv.parse_type_string( f"struct {_SGX_ECALL_TYPE_NAME} ecall_table[{ecalls_count}]") bv.define_data_var(table_addr, table_type) s = Symbol(SymbolType.DataSymbol, table_addr, "ecall_table") bv.define_user_symbol(s) PluginCommand.register("SGX\\find ecall table", "In a SGX binary, try to identify the ecall table", find_ecall_table)
#!/usr/bin/env python # author: carstein <*****@*****.**> # Syscaller - decoreate syscall with arguments from binaryninja import PluginCommand from .modules import syscaller # register plugin PluginCommand.register_for_function( "Syscaller\Decorate syscalls in current function", "Annotate syscalls with arguments in current function", syscaller.run_plugin_current) PluginCommand.register( "Syscaller\Decorate syscalls in all functions", "Annotate syscalls with arguments in all defined functions", syscaller.run_plugin_all)
self.caller.add_user_code_ref(src, dst, from_arch=None) self.add_call_comment(src, dst) self.call_cnt += 1 log.log(1, "Devirtualized {} calls".format(self.call_cnt)) def devirtualize_calls_v01(self, call_list): for v_call in call_list: for call in v_call: to_addr = int(v_call[call]) #print(hex(int(call))) #print(hex(to_addr)) from_addr = int(call) self.caller = self.bv.get_functions_containing(from_addr)[0] self.caller.add_user_code_ref(from_addr, to_addr, from_arch=None) self.add_call_comment(from_addr, to_addr) self.call_cnt += 1 log.log(1, "Devirtualized {} calls".format(self.call_cnt)) def add_call_comment(self, from_addr, to_addr): to_func = self.bv.get_function_at(to_addr) _, name = demangle.demangle_gnu3(self.bv.arch, to_func.name) old_comment = self.caller.get_comment_at(from_addr) self.caller.set_comment_at( from_addr, demangle.get_qualified_name(name) + "\n" + old_comment) PluginCommand.register("devi", "DEvirtualize VIrtual calls", binja_devi)
from binaryninja import PluginCommand from .obfuscation_detection import detect_obfuscation from .obfuscation_detection.heuristics import * PluginCommand.register("Obfuscation Detection\\All", "Detects obfuscated code via heuristics", detect_obfuscation) PluginCommand.register("Obfuscation Detection\\Flattened Functions", "Heuristic to detect flattened functions", find_flattened_functions) PluginCommand.register("Obfuscation Detection\\Complex Functions", "Heuristic to detect complex functions", find_complex_functions) PluginCommand.register("Obfuscation Detection\\Large Basic Blocks", "Heuristic to detect functions with large basic blocks", find_large_basic_blocks) PluginCommand.register("Obfuscation Detection\\Instruction Overlapping", "Heuristic to detect instruction overlapping", find_instruction_overlapping) PluginCommand.register("Obfuscation Detection\\Uncommon Instruction Sequences", "Heuristic to detect uncommon instruction sequences", find_uncommon_instruction_sequences)
for instr in bb: if instr[0][0].text not in ("nop", "jmp") or ( instr[0][0].text == "jmp" and not bb.outgoing_edges): print(instr[0]) n.lines += [ DisassemblyTextLine(instr[0], address=current_addr) ] current_addr += instr[1] if (instr[0][0].text == "jmp" and bb.outgoing_edges and bb.outgoing_edges[0].target.start in bbs and bb.outgoing_edges[0].target in bb.dominators): n.add_outgoing_edge( BranchType.UnconditionalBranch, bbs[bb.outgoing_edges[0].target.start], ) else: # Keep using the same FlowGraphNode pass g.append(n) g.layout_and_wait() g.show(func.name) PluginCommand.register( r"Unlock\Generate Graphs", "Generate Deobfuscated Graphs", generate_graphs, lambda v: "obfuscated" in v.file.filename, )
#!/usr/bin/env python # Author: carstein <*****@*****.**> # Annotate function arguments from binaryninja import PluginCommand from modules import annotate # register plugin PluginCommand.register_for_function( "[Annotator] Annotate Functions", "Annotate standard libc functions with arguments", annotate.run_plugin) PluginCommand.register("[Annotator All] Annotate Functions", "Annotate standard libc functions with arguments", annotate.run_plugin_all)
bv = BinaryViewType["PE"].open(args.driver) if not bv: print("[-] Error loading file: {:s}".format(args.driver), file=sys.stderr) return 1 analysis = analyze.Analysis(bv) analysis.label_driver_dispatch_routines() if args.ioctls: analysis.find_ioctls() if __name__ == "__main__": cmdline_main() else: PluginCommand.register( "Label Driver Dispatch Routines", "Label driver dispatch routines for IRPs and other callbacks", action=label_driver_dispatch_routines) #PluginCommand.register( # "Label Callback Routines", "Label callback routines used in common kernel APIs", # action=label_callback_routines) PluginCommand.register( "Find IOCTLs [global]", "Find supported IOCTLs and generate CTL_CODE macros", action=find_ioctls) PluginCommand.register_for_function( "Find IOCTLs [current function]", "Find supported IOCTLs and generate CTL_CODE macros", action=find_ioctls)
dbg("Starting background service...") __service_thread = threading.Thread(target=start_service, args=(HOST, PORT, bv)) __service_thread.daemon = True __service_thread.start() register_gef_breakpoint_menu() show_message_box( "GEF", "Service successfully started, you can now have gef connect to it", MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.InformationIcon) return def gef_stop(bv): "Stopping background service... " stop_service() show_message_box("GEF", "Service successfully stopped", MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.InformationIcon) return PluginCommand.register("GEF\\Start service", "Start the service for communicating with gef", gef_start, is_valid=lambda view: not is_service_started()) PluginCommand.register("GEF\\Stop service", "Stop the service for communicating with gef", gef_stop, is_valid=lambda view: is_service_started())
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), Qt.RightDockWidgetArea, Qt.Vertical, True) PluginCommand.register_for_function("Push function upwards", "Push function upwards", controller.push_function) # TODO how can we avoid having users to click on this menu option? PluginCommand.register("Start Sharing Patches", "Start Sharing Patches", start_patch_monitor) PluginCommand.register("Start Sharing Functions", "Start Sharing Functions", start_function_monitor)
# Print warnings when our janky parser goes awry. if len(words)>0 and words[0]!="/*" and words[0]!="*/": print("#Warning in: %s\n"%words); log_error(traceback.format_exc()) def md380ldsymbols(view): """This loads an MD380Tools symbols file in GNU LD format.""" filename=get_open_filename_input("Select GNU LD symbols file from MD380Tools.") if filename: print("Opening: %s"%filename); importldsymbols(view,filename); else: print("Aborting."); PluginCommand.register("Load MD380 LD Symbols", "Load GNU LD symbols from MD380Tools", md380ldsymbols); def importr2symbols(bv,filename): """Janky shotgun parser to import Radare2 symbols file to Binary Ninja.""" f=open(filename,"r"); for l in f: words=l.strip().split(); try: if words[0][0]=="#": pass; elif words[0]=="f" and words[2]=="@": #f name @ 0xDEADBEEF name=words[1];
def get_coverage(view): tv = TraceVisualizer(view, None, live=False) if tv.workspace is None: tv.workspace = get_workspace() tv.visualize() c = CoverageHelper(view, tv) c.start() def clear_all(view): tv = TraceVisualizer(view, None) for addr in tv.highlighted: tv.highlight_block(addr, clear) tv.clear_stats() tv.workspace = None tv.live_update = False PluginCommand.register("ManticoreTrace: Highlight", "Highlight Manticore Execution Trace", viz_trace) PluginCommand.register("ManticoreTrace: BB Coverage", "Compute cumulative BB coverage for each function ", get_coverage) PluginCommand.register( "ManticoreTrace: Live Highlight", "Highlight Manticore Execution Trace at Real-Time", viz_live_trace, ) PluginCommand.register("ManticoreTrace: Clear", "Clear Manticore Trace Highlight", clear_all)
from binaryninja import plugin, PluginCommand class bnlink_task(plugin.BackgroundTaskThread): def __init__(self, bv): plugin.BackgroundTaskThread.__init__(self, "bnlink", True) self.bv = bv def run(self): from rpyc.core import SlaveService from rpyc.utils.server import ThreadedServer ThreadedServer(SlaveService, port=6666).start() def run_task(bv): bnlink_task(bv).start() PluginCommand.register("Start bnlink", "Run's rpc service on port 6666", run_task)
"""Binary Ninja plugin for applying kernel symbols from /proc/kallsyms output """ from binaryninja import BinaryView, PluginCommand from .kallsyms import * def apply_kernel_symbols(view: BinaryView): """Registered plugin handler function """ kallsyms = KAllSyms(view) kallsyms.start() PluginCommand.register("kallsyms: Apply kernel symbols", "Apply kernel symbols from /proc/kallsyms output", apply_kernel_symbols)
#from __future__ import print_function from binaryninja import PluginCommand from printSourceCode import function_source_code_start from coverage import function_coverage_start from evm import EVM, EVMView PluginCommand.register("EVM Source Code", "EVM Source Code Printer.", function_source_code_start) PluginCommand.register("EVM Manticore Highlight", "EVM Manticore Highlight", function_coverage_start) EVM.register() EVMView.register()
task.start() def command_label_tls(view): label_tls(view) def check_view_platform(view, *platforms): platform = view.platform if platform is None: return False return platform.name in platforms PluginCommand.register( 'Windows\\Scan for RTTI', 'Scans for MSVC RTTI', lambda view: command_scan_for_rtti(view), lambda view: check_view_platform(view, 'windows-x86', 'windows-x86_64')) PluginCommand.register_for_address( 'Windows\\Create vftable', 'Creates a vftable at the current address', lambda view, address: command_create_vtable(view, address), lambda view, address: check_view_platform(view, 'windows-x86', 'windows-x86_64')) PluginCommand.register( 'Windows\\Parse exception handlers', 'Create functions based on exception handlers', lambda view: command_parse_unwind_info(view), lambda view: check_view_platform(view, 'windows-x86_64')) PluginCommand.register( 'Windows\\Fix thiscall\'s',
if not __check_executor(): return executor.bncache.settings = {} PluginCommand.register_for_address( "SENinja\\0 - Start symbolic execution", "create the first state for symbolic execution at current address", _async_start_se) PluginCommand.register_for_address( "SENinja\\1 - Change current state", "change current state with the deferred one at current address (if any)", _async_change_current_state) PluginCommand.register("SENinja\\2 - Step", "execute one instruction with the current state", _async_step) PluginCommand.register( "SENinja\\3 - Continue until branch", "execute instructions in the current state until a fork occurs", _async_continue_until_branch) PluginCommand.register_for_address( "SENinja\\4 - Continue until address", "execute instructions in the current state until the currently selected address is reached", _async_continue_until_address) PluginCommand.register_for_address( "SENinja\\5 - Merge states", "merge all states at current address in one state", _async_merge_states) PluginCommand.register("SENinja\\6 - Save active state", "save active state in deferred queue", _async_save_active_state)
from .coverage import function_coverage_start from .evm import EVM, EVMView from .flowgraph import render_flowgraphs from .annotator import annotate_all from .lookup4byte import (rename_all_functions, lookup_one_inst, update_cache_bn, lookup_all_push4) from .misc import dump_codecopy_data def is_valid_evm(view, function=None): return view.arch == Architecture['EVM'] PluginCommand.register(r"Ethersplay\Manticore Highlight", "EVM Manticore Highlight", function_coverage_start, is_valid=is_valid_evm) PluginCommand.register( r'Ethersplay\Render Flowgraphs', 'Render flowgraphs of every function, removing stack variable annotations', render_flowgraphs, is_valid=is_valid_evm) # non-upstream things PluginCommand.register("Ethersplay-contrib\\Annotate Instructions", "[EVM] Annotate Instructions", annotate_all, is_valid=is_valid_evm) PluginCommand.register(
def add_image_button(filename, size, fun=None, tooltip=None): """ Adds a pushbutton with an icon to the toolbar """ button = QtWidgets.QPushButton('', toolbar) button.setIcon(QtGui.QIcon(filename)) if fun is not None: button.clicked.connect(lambda: fun(get_binary_view())) if tooltip is not None: button.setToolTip(tooltip) button.setIconSize(QtCore.QSize(size[0], size[1])) toolbar.add_widget(button) def add_picker(pickeritems, callback): """ Adds a combobox widget to the toolbar """ picker = QtWidgets.QComboBox() for item in pickeritems: picker.addItem(item) picker.currentIndexChanged.connect(callback) toolbar.add_widget(picker) def set_bv(binary_view): """ Caches the binary view so that button callbacks can have access to it """ global global_binary_view global_binary_view = binary_view if not toolbar.isVisible(): toolbar.toggle() PluginCommand.register("Initialize Toolbar for this view", "", set_bv)
def _install_load_batch(self): PluginCommand.register("Lighthouse - Load code coverage batch...", "Load and aggregate code coverage files", self.interactive_load_batch) logger.info("Installed the 'Code coverage batch' menu entry")
for specifier in specifiers[1:]: if not specifier: continue if specifier.startswith('d'): param_types.append(Type.int(4, sign=True)) elif specifier.startswith('s'): param_types.append(Type.pointer(view.arch, Type.char())) elif specifier.startswith('p'): param_types.append(Type.pointer(view.arch, Type.void())) else: log.log_warn( f'Unknown format specifier: {specifier}; skipping') param_types.append(Type.pointer(view.arch, Type.void())) param_idx = 1 params = [ FunctionParameter(Type.pointer(view.arch, Type.char()), 'fmt') ] for param in param_types: params.append(FunctionParameter(param, f'arg{param_idx}')) param_idx += 1 caller.set_call_type_adjustment(xref.address, Type.function(Type.int(4), params)) PluginCommand.register( 'Fix up printf signatures', 'Fix up printf signatures so that the variadic arguments are correctly typed', fix_printfs)
src = self.visit(expr.src) if src is not None: self.br.seek(src) return self.br.read8() def visit_LLIL_XOR(self, expr): left = self.visit(expr.left) right = self.visit(expr.right) if None not in (left, right): return left ^ right def visit_LLIL_REG(self, expr): src = expr.src return self.regs[src.name] def visit_LLIL_NORET(self, expr): log_alert("VM Halted.") def run_emulator(view): v = VMVisitor(view) for il in view.llil_instructions: v.visit(il) PluginCommand.register('Emulate VMArch', 'Emulate VMArch LLIL', run_emulator, lambda view: view.arch == Architecture['VMArch'])
from binaryninja import PluginCommand from .binja import import_data_in_background, export_data_in_background PluginCommand.register('bnida: Import analysis data', 'Import analysis data from JSON file', import_data_in_background) PluginCommand.register('bnida: Export analysis data', 'Export analysis data to a JSON file', export_data_in_background)
def symbol_added(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def symbol_updated(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def symbol_removed(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def string_found(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def string_removed(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def type_defined(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def type_undefined(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def type_ref_changed(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def type_field_ref_changed(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) PluginCommand.register("Register Notification", "", reg_notif)
""" """ from binaryninja import ( PluginCommand, ) from .server import ( rpyc_start, rpyc_stop, is_service_started, ) PluginCommand.register("RPyC\\Start service", "Start the RPyC server", rpyc_start, is_valid=lambda view: not is_service_started()) PluginCommand.register("RPyC\\Stop service", "Start the RPyC server", rpyc_stop, is_valid=lambda view: is_service_started())
"""Returns true if a function has a 'strange loop' (ignore this, inside joke)""" for bb in fn.basic_blocks: if bb in bb.dominance_frontier: return True return False tags = [ \ {'emoji': '🍃', 'name': 'Leaf Function', 'description': 'Leaf function (does not call anything else)', 'fn': isleaf}, {'emoji': '🔄', 'name': 'Loop Function', 'description': 'Function contains a loop', 'fn': hasloop}, {'emoji': '🥾', 'name': 'Stub Function', 'description': 'Function is likely a stub (only contains one basic block and one call or indirect jump)', 'fn': isstub}, {'emoji': '🐘', 'name': 'Large Function', 'description': 'Function is "large" (IE, it has more than the blocks defined above)', 'fn': islarge}, {'emoji': '🤯', 'name': 'Complex Function', 'description': 'Function is "complex" (IE, it has a cyclomatic complexity greater than a defined constant)', 'fn': iscomplex}, {'emoji': '🌴', 'name': 'Switchy Function', 'description': 'Function contains a large switch statemen', 'fn': isswitchy}, ] def start(bv): init_tags(bv) for fn in bv.functions: for tagType in tags: if tagType['fn'](fn): fn.create_user_function_tag(bv.tag_types[tagType['name']], '', unique=True) #fn.name = fn.name + tagType['emoji'] PluginCommand.register("TagTeam", "Tag Functions with Emoji for Various Properties", start)
log.log_info(inspect.stack()[0][3] + str(args)) def function_removed(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def function_updated(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def data_var_added(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def data_var_updated(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def data_var_removed(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def string_found(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def string_removed(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def type_defined(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) def type_undefined(self, *args): log.log_info(inspect.stack()[0][3] + str(args)) PluginCommand.register("Register Notification", "", reg_notif)