diff options
Diffstat (limited to 'python/examples')
| -rwxr-xr-x | python/examples/export_svg.py | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py index ce5122ae..7ce804ea 100755 --- a/python/examples/export_svg.py +++ b/python/examples/export_svg.py @@ -3,14 +3,14 @@ import os import webbrowser import time import sys -try: - from urllib import pathname2url # Python 2.x -except: - from urllib.request import pathname2url # Python 3.x +from pathlib import Path +from urllib.request import pathname2url -from binaryninja.interaction import get_save_filename_input, show_message_box +from binaryninja.interaction import get_save_filename_input, show_message_box, TextLineField, ChoiceField, SaveFileNameField, get_form_input +from binaryninja.settings import Settings from binaryninja.enums import MessageBoxButtonSet, MessageBoxIcon, MessageBoxButtonResult, InstructionTextTokenType, BranchType from binaryninja.plugin import PluginCommand +from binaryninja.log import log_error colors = {'green': [162, 217, 175], 'red': [222, 143, 151], 'blue': [128, 198, 233], 'cyan': [142, 230, 237], 'lightCyan': [ 176, 221, 228], 'orange': [237, 189, 129], 'yellow': [237, 223, 179], 'magenta': [218, 196, 209], 'none': [74, 74, 74]} @@ -35,30 +35,49 @@ def escape(toescape): def save_svg(bv, function): - address = hex(function.start).replace('L', '') - path = os.path.dirname(bv.file.filename) + 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 = os.path.join( - path, 'binaryninja-{filename}-{function}.html'.format(filename=origname, function=address)) - outputfile = get_save_filename_input( - 'File name for export_svg', 'HTML files (*.html)', filename) - if sys.platform == "win32": - outputfile = outputfile.replace('/', '\\') - if outputfile is None: + 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", "LLIL", "LLIL SSA", "MLIL", "MLIL SSA", "HLIL", "HLIL SSA"] + formChoiceField = ChoiceField("Form", formChoices) + else: + formChoices = ["Assembly", "LLIL", "MLIL", "HLIL"] + formChoiceField = ChoiceField("Form", formChoices) + + saveFileChoices = SaveFileNameField("Output file", 'HTML files (*.html)', str(filename)) + if not get_form_input([f'Current Function: {offset}', functionChoice, formChoiceField, modeChoiceField, saveFileChoices], "SVG Export") or saveFileChoices.result is None: return - content = render_svg(function, origname) + if saveFileChoices.result == '': + outputfile = filename + else: + outputfile = saveFileChoices.result + content = render_svg(function, offset, modeChoices[modeChoiceField.result], formChoices[formChoiceField.result], 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: - url = 'file:{}'.format(pathname2url(bytes(outputfile))) - webbrowser.open(url) + # 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 instruction_data_flow(function, address): - ''' TODO: Extract data flow information ''' + # TODO: Extract data flow information length = function.view.get_instruction_length(address) func_bytes = function.view.read(address, length) if sys.version_info[0] == 3: @@ -69,8 +88,23 @@ def instruction_data_flow(function, address): return 'Opcode: {bytes}'.format(bytes=padded) -def render_svg(function, origname): - graph = function.create_graph() +def render_svg(function, offset, mode, form, origname): + if form == "Assembly": + graph = function.create_graph() + elif form == "LLIL": + graph = function.llil.create_graph() + elif form == "LLIL SSA": + graph = function.llil.ssa_form.create_graph() + elif form == "MLIL": + graph = function.mlil.create_graph() + elif form == "MLIL SSA": + graph = function.mlil.ssa_form.create_graph() + elif form == "HLIL": + graph = function.hlil.create_graph() + elif form == "HLIL SSA": + graph = function.hlil.ssa_form.create_graph() + else: + log_error(f"Invalid form selection: {form}") graph.layout_and_wait() heightconst = 15 ratio = 0.48 @@ -242,8 +276,8 @@ def render_svg(function, origname): output += ' </g>\n' output += '</svg>' - output += '<p>This CFG generated by <a href="https://binary.ninja/">Binary Ninja</a> from {filename} on {timestring}.</p>'.format( - filename=origname, timestring=time.strftime("%c")) + output += '<p>This CFG generated by <a href="https://binary.ninja/">Binary Ninja</a> from {filename} on {timestring} showing {function} as {form}.</p>'.format( + filename=origname, timestring=time.strftime("%c"), function=offset, form=form) output += '</html>' return output |
