def __init__(self, interactive=False): if interactive: csv_file = OpenFileNameField("Import csv file") get_form_input([csv_file], "Polypyus Import Options") self.verbose = True if csv_file.result == "": self.csv_file = None else: self.csv_file = csv_file.result self.output_name = None return # headless descr = "Export functions from a Polypyus csv into an existing Binary Ninja database." parser = ArgumentParser(description=descr) parser.add_argument("csv", type=FileType("w"), help="Path to Polypyus csv.") parser.add_argument("bndb", type=FileType("r"), help="Path to Binary Ninja database.") args = parser.parse_args() self.csv_file = args.csv self.input_file = args.csv self.output_name = args.bndb
def generate_all_platforms(bv): platforms = [i.name for i in list(Platform)] header_file = OpenFileNameField("Select Header File") lib_name = TextLineField("Type Library Name") file_name = TextLineField("File Name") get_form_input([header_file, lib_name, file_name], "Generate Type Library") try: for p in list(Platform): typelib = generate_typelib(p, header_file.result, lib_name.result) path = typelib_path / p.name / "{}.bntl".format(file_name.result) typelib.write_to_file(str(path.resolve())) except SyntaxError as e: show_message_box("Error", e.msg)
def easypatch(bv, addr): """ Shows a dialog containing all memory operands at current instruction and prompts for data to overwrite with. Expression is eval()ed so \n and \0 are valid inputs """ targets = get_memory_operands_at(bv, addr) targets_field = interaction.ChoiceField('Patch Target:', targets) patch_text_field = interaction.TextLineField('Patch text:') valid_input = interaction.get_form_input([targets_field, patch_text_field], 'easypatch') if valid_input: target = targets[targets_field.result].addr patch_text = eval("'%s'" % patch_text_field.result) if not bv.write(target, patch_text): if not make_valid_for_writing(bv, target, len(patch_text)): interaction.show_message_box( 'easypatch', 'Failed to make writable to %x' % target) elif not bv.write(target, patch_text): interaction.show_message_box('easypatch', 'Failed to write to %x' % target) else: function = bv.get_basic_blocks_at(addr)[0].function function.reanalyze() else: function = bv.get_basic_blocks_at(addr)[0].function function.reanalyze()
def generate_single_platform(bv): arch_choices = [i.name for i in list(Platform)] header_file = OpenFileNameField("Select Header File") arch = ChoiceField("Select Architecture", arch_choices) name = TextLineField("Type Library Name") save_file = SaveFileNameField("Save Type Library", ext="bntl") get_form_input([header_file, arch, name, save_file], "Generate Type Library") arch = arch_choices[arch.result] platform = Platform[arch] try: typelib = generate_typelib(platform, header_file.result, name.result) typelib.write_to_file(save_file.result) except SyntaxError as e: show_message_box("Error", e.msg.decode())
def abi_dialog(view, addr): func = get_function_defined_or_referred_at(view, addr) def show_error(text): bni.show_message_box("ABI Error", text, icon=bne.MessageBoxIcon.ErrorIcon) arch = view.platform.arch cconvs = view.platform.calling_conventions cconv_names = list(map(lambda x: x.name, cconvs)) cconv = func.calling_convention clobbers = set(func.clobbered_regs) cconv_clobbers = set([cconv.int_return_reg] + cconv.int_arg_regs + cconv.caller_saved_regs) add_clobbers = clobbers.difference(cconv_clobbers) remove_clobbers = cconv_clobbers.difference(clobbers) cconv_field = bni.ChoiceField("Calling convention", cconv_names) cconv_field.result = cconvs.index(cconv) cconv_current_field = "(current: {})".format(cconv) add_clobber_field = bni.TextLineField("Additional clobbers") add_clobber_field.result = " ".join(list(map(str, add_clobbers))) add_clobber_current_field = "(current: {})".format( add_clobber_field.result) remove_clobber_field = bni.TextLineField("Excluded clobbers") remove_clobber_field.result = " ".join(list(map(str, remove_clobbers))) remove_clobber_current_field = "(current: {})".format( remove_clobber_field.result) fields = [ "Note: it's not currently possible to pre-fill the fields,", "so please manually set the ones you don't want to change to current values", cconv_field, cconv_current_field, add_clobber_field, add_clobber_current_field, remove_clobber_field, remove_clobber_current_field ] if bni.get_form_input(fields, "Function ABI"): cconv = cconvs[cconv_field.result] add_clobbers = set(add_clobber_field.result.split()) remove_clobbers = set(remove_clobber_field.result.split()) for reg in add_clobbers | remove_clobbers: if reg not in arch.regs: show_error("{} is not a valid {} register.".format( reg, arch.name)) return func.calling_convention = cconv clobbers = set([cconv.int_return_reg] + cconv.int_arg_regs + cconv.caller_saved_regs) clobbers.update(add_clobbers) clobbers.difference_update(remove_clobbers) func.clobbered_regs = list(clobbers)
def save_svg(bv, function): sym = bv.get_symbol_at(function.start) if sym: offset = sym.name else: offset = "%x" % function.start path = Path(os.path.dirname(bv.file.filename)) origname = os.path.basename(bv.file.filename) filename = path / f'binaryninja-{origname}-{offset}.html' functionChoice = TextLineField("Blank to accept default") # TODO: implement linear disassembly settings and output modeChoices = ["Graph"] modeChoiceField = ChoiceField("Mode", modeChoices) if Settings().get_bool('ui.debugMode'): formChoices = [ "Assembly", "Lifted IL", "LLIL", "LLIL SSA", "Mapped Medium", "Mapped Medium SSA", "MLIL", "MLIL SSA", "HLIL", "HLIL SSA" ] formChoiceField = ChoiceField("Form", formChoices) else: formChoices = ["Assembly", "LLIL", "MLIL", "HLIL"] formChoiceField = ChoiceField("Form", formChoices) showOpcodes = ChoiceField("Show Opcodes", ["Yes", "No"]) showAddresses = ChoiceField("Show Addresses", ["Yes", "No"]) saveFileChoices = SaveFileNameField("Output file", 'HTML files (*.html)', str(filename)) if not get_form_input([ f'Current Function: {offset}', functionChoice, formChoiceField, modeChoiceField, showOpcodes, showAddresses, saveFileChoices ], "SVG Export") or saveFileChoices.result is None: return if saveFileChoices.result == '': outputfile = filename else: outputfile = saveFileChoices.result content = render_svg(function, offset, modeChoices[modeChoiceField.result], formChoices[formChoiceField.result], showOpcodes.result == 0, showAddresses.result == 0, origname) output = open(outputfile, 'w') output.write(content) output.close() result = show_message_box("Open SVG", "Would you like to view the exported SVG?", buttons=MessageBoxButtonSet.YesNoButtonSet, icon=MessageBoxIcon.QuestionIcon) if result == MessageBoxButtonResult.YesButton: # might need more testing, latest py3 on windows seems.... broken with these APIs relative to other platforms if sys.platform == 'win32': webbrowser.open(outputfile) else: webbrowser.open('file://' + str(outputfile))
def ief_find_library(binview): """ run `ief <path> -l <partial library name>` """ name = TextLineField("Library name (can be partial)") directory = DirectoryNameField( "Directory to search", dirname(binview.file.filename)) get_form_input([name, None, directory], "Find binaries that import library") if not directory.result: directory.result = dirname(binview.file.filename) if name.result is None: return # Assumes `~/.cargo/bin` already exists in PATH result = run(["ief", directory.result, "-l", name.result], capture_output=True) directory = directory.result markdown = f"# Results - binaries in '[{directory}]({directory})'" \ f"with imported library name containing '_{name.result}_'\n\n" for line in result.stdout.split(b"\n")[1:-1]: npath = normpath(line.decode('utf-8')) markdown += f"* [{npath}]({npath})\n" show_markdown_report(f"IEF - {name.result}", markdown, result.stdout.decode('utf-8'))
def run_plugin(bv): patch_text_field = interaction.MultilineTextField( "Instruction(s) to convert to nop's (e.g. int3)") res = interaction.get_form_input([patch_text_field], 'Find And Nop') if res == False: return lines = patch_text_field.result.split("\n") special_characters = ",[]-+*:" pattern = [] for line in lines: temp = line for char in special_characters: temp = temp.replace(char, " " + char + " ") # remove double spaces temp = ' '.join(temp.split()) temp = temp.split() pattern.append(temp) pattern_len = len(pattern) for func in bv.functions: func_instr_list = list(func.instructions) for idx, inst in enumerate(func_instr_list): if (idx + pattern_len) > len(func_instr_list): # pattern too long for this function set, check next function break if check_pattern(pattern, func_instr_list[idx:idx + pattern_len], bv): for i in range(pattern_len): # original code as comment comment(func, inst[1], "FaN: " + str(pattern)) bv.convert_to_nop(func_instr_list[idx + i][1]) interaction.show_message_box( "Possible Reload Required", "Maybe you have to save and reload the binary because the functions aren't updated. E.g. if you have replaced int3 instructions the code flow will change." )
def show_delphi_modal(bv: BinaryView): global _version_mapping global _arch_mapping arch_mapping = copy.copy(_arch_mapping) if bv.arch is not None and bv.arch.address_size == 8: arch_mapping.reverse() version_field = interaction.ChoiceField('Delphi version', [x for x, _ in _version_mapping]) arch_field = interaction.ChoiceField('Architecture (ptr size)', [x for x, _ in arch_mapping]) normalize_section_name = lambda x: f'{x.name} {{0x{x.start:x}-0x{x.end:x}}}' normalize_section_tuple = lambda x: (normalize_section_name(x), (x.start, x.end)) sections = sorted(bv.sections.values(), key=lambda x: x.start) range_mapping = [('Whole binary', (bv.start, bv.end)) ] + [normalize_section_tuple(x) for x in sections] range_field = interaction.ChoiceField('Search area', [x for x, _ in range_mapping]) result = interaction.get_form_input( [version_field, arch_field, range_field], "Search options") if not result: return None return { 'delphi_version': _version_mapping[version_field.result][1], 'offset_ptr_size': arch_mapping[arch_field.result][1], 'start': range_mapping[range_field.result][1][0], 'end': range_mapping[range_field.result][1][1], }
def __init__(self, interactive=False): if interactive: import_strings_choice = ChoiceField("Import Strings", ["Yes", "No"]) import_string_name_choice = ChoiceField("Import String Names", ["Yes", "No"]) import_function_choice = ChoiceField("Import Functions", ["Yes", "No"]) import_comment_choice = ChoiceField("Import Comments", ["Yes", "No"]) json_file = OpenFileNameField("Import json file") get_form_input([json_file, import_strings_choice, import_string_name_choice, import_function_choice, import_comment_choice], "IDA Import Options") self.import_strings = import_strings_choice.result == 0 self.import_strings_names = import_string_name_choice.result == 0 self.import_functions = import_function_choice.result == 0 self.import_comments = import_comment_choice.result == 0 self.verbose = True if json_file.result == '': self.json_file = None else: self.json_file = json_file.result self.output_name = None else: usage = "usage: %prog [options] <ida_export.json> <file|bndb>" parser = OptionParser(usage=usage) parser.add_option("-q", "--quiet", dest="verbose", action="store_false", default=True, help="Don't display automatic actions") parser.add_option("-s", "--no-strings", dest="import_strings", action="store_false", default=True, help="Don't import string data") parser.add_option("-n", "--no-string-names", dest="import_strings_names", action="store_false", default=True, help="Don't import string names") parser.add_option("-o", "--output-name", dest="output_name", action="store", default=None, help="Specify output name of bndb. Defaults to <file_name>.bndb") parser.add_option("-f", "--no-functions", dest="import_functions", action="store_false", default=True, help="Don't import function starts") parser.add_option("-c", "--no-comments", dest="import_comments", action="store_false", default=True, help="Don't import comments") (options, args) = parser.parse_args() self.import_strings = options.import_strings self.import_strings_names = options.import_strings_names self.import_functions = options.import_functions self.import_comments = options.import_comments self.verbose = options.verbose self.json_file = args[0] self.input_file = args[0] self.output_name = options.output_name if self.output_name is None: self.output_name = self.input_file + ".bndb" self.usage = parser.get_usage()
config = {"host": host, "port": port, "nick": nick, "password": password} with open(os.path.join(path, "config.json"), "w") as f: config = f.write(json.dumps(config)) try: import binaryninja import binaryninja.interaction as bi try: import config except ImportError: host_f = bi.TextLineField("host") port_f = bi.IntegerField("port") nick_f = bi.TextLineField("nick") password_f = bi.TextLineField("password") success = bi.get_form_input([None, host_f, port_f, nick_f, password_f], "Configure Revsync") if not success: binaryninja.interaction.show_message_box( title="Revsync error", text="Failed to configure revsync") raise write_config(host_f.result, port_f.result, nick_f.result, password_f.result) import config import binja_frontend #import binja_coverage good = True except ImportError: pass try:
def _display_menu(self, items, title): form_menu = get_form_input(items, title) return form_menu