From 11d6f78e43e0f305be43aeb8fc75d9d6733e508a Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 13 Sep 2016 18:24:02 -0400 Subject: rename files to allow them to be imported --- python/examples/export_svg.py | 166 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100755 python/examples/export_svg.py (limited to 'python/examples/export_svg.py') diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py new file mode 100755 index 00000000..02a6d57e --- /dev/null +++ b/python/examples/export_svg.py @@ -0,0 +1,166 @@ +from binaryninja import * +import os,sys + +escape_table = { + "'": "'", + ">": ">", + "<": "<", + '"': """, + ' ': " " +} + +def escape(string): + string=string.decode('utf-8').encode('ascii','xmlcharrefreplace') #handle extended unicode + return ''.join(escape_table.get(i,i) for i in string) #still escape the basics + +def save_svg(bv,function): + filename = os.path.basename(bv.file.filename) + address = hex(function.start).replace('L','') + outputfile = os.path.join(os.path.expanduser('~'), 'binaryninja-{filename}-{function}.html'.format(filename=filename,function=address)) + content = render_svg(function) + output = open(outputfile,'w') + output.write(content) + output.close() + #os.system('open %s' % outputfile) + +def instruction_data_flow(function,address): + ''' TODO: Extract data flow information ''' + length = function.view.get_instruction_length(function.arch,address) + bytes = function.view.read(address, length) + hex = bytes.encode('hex') + padded = ' '.join([hex[i:i+2] for i in range(0, len(hex), 2)]) + return 'Opcode: {bytes}'.format(bytes=padded) + +def render_svg(function): + graph = function.create_graph() + graph.layout_and_wait() + heightconst = 15 + ratio = 0.48 + widthconst = heightconst*ratio + + output = ''' + + + + +''' + output += ''' + + + + + + + + + + + + + + + '''.format(width=graph.width*widthconst, height=graph.height*heightconst) + output += ''' + Function Graph 0 + ''' + edges = '' + for i,block in enumerate(graph.blocks): + + #Calculate basic block location and coordinates + x = ((block.x) * widthconst) + y = ((block.y) * heightconst) + width = ((block.width) * widthconst) + height = ((block.height) * heightconst) + + #Render block + output += ' \n'.format(i=i) + output += ' Basic Block {i}\n'.format(i=i) + output += ' \n'.format(x=x,y=y,width=width,height=height) + + #Render instructions, unfortunately tspans don't allow copying/pasting more + #than one line at a time, need SVG 1.2 textarea tags for that it looks like + + output += ' \n'.format(x=x,y=y + (i + 1) * heightconst) + for i,line in enumerate(block.lines): + output += ' '.format(x=x,y=y + (i + 0.7) * heightconst,address=hex(line.address)[:-1]) + hover = instruction_data_flow(function, line.address) + output += '{hover}'.format(hover=hover) + for token in line.tokens: + # TODO: add hover for hex, function, and reg tokens + output+='{text}'.format(text=escape(token.text),tokentype=token.type) + output += '\n' + output += ' \n' + output += ' \n' + + #Edges are rendered in a seperate chunk so they have priority over the + #basic blocks or else they'd render below them + + for edge in block.outgoing_edges: + points = "" + for x,y in edge.points: + points += str(x*widthconst)+","+str(y*heightconst) + " " + edges += ' \n'.format(type=edge.type,points=points) + output += ' ' + edges + '\n' + output += ' \n' + output += '' + return output + +PluginCommand.register_for_function("Export to SVG", "Exports an SVG of the current function to your home folder.", save_svg) -- cgit v1.3.1 From 9c94170020ec15eb2e6ac621915257ef2e270c7a Mon Sep 17 00:00:00 2001 From: rootbsd Date: Fri, 16 Sep 2016 10:19:42 +0200 Subject: Add the color support to export_svg.py --- python/examples/export_svg.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'python/examples/export_svg.py') diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py index 02a6d57e..ebf3e2d1 100755 --- a/python/examples/export_svg.py +++ b/python/examples/export_svg.py @@ -1,6 +1,8 @@ from binaryninja import * import os,sys +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]} + escape_table = { "'": "'", ">": ">", @@ -21,7 +23,7 @@ def save_svg(bv,function): output = open(outputfile,'w') output.write(content) output.close() - #os.system('open %s' % outputfile) + os.system('%s' % outputfile) def instruction_data_flow(function,address): ''' TODO: Extract data flow information ''' @@ -46,7 +48,6 @@ def render_svg(function): background-color: rgb(42, 42, 42); } .basicblock { - fill: rgb(74, 74, 74); stroke: rgb(224, 224, 224); } .edge { @@ -133,7 +134,16 @@ def render_svg(function): #Render block output += ' \n'.format(i=i) output += ' Basic Block {i}\n'.format(i=i) - output += ' \n'.format(x=x,y=y,width=width,height=height) + rgb=colors['none'] + try: + bb = block.basic_block + color_code = bb.highlight._get_core_struct().color + color_str = bb.highlight._standard_color_to_str(color_code) + if color_str in colors: + rgb=colors[color_str] + except: + pass + output += ' \n'.format(x=x,y=y,width=width,height=height,r=rgb[0],g=rgb[1],b=rgb[2]) #Render instructions, unfortunately tspans don't allow copying/pasting more #than one line at a time, need SVG 1.2 textarea tags for that it looks like @@ -164,3 +174,4 @@ def render_svg(function): return output PluginCommand.register_for_function("Export to SVG", "Exports an SVG of the current function to your home folder.", save_svg) + -- cgit v1.3.1 From 9f1620b744c7b71fc898a46b668624d25fbff60f Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 20 Sep 2016 00:30:37 -0400 Subject: add file save dialog and fix spacing --- python/examples/export_svg.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'python/examples/export_svg.py') diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py index ebf3e2d1..35f35f00 100755 --- a/python/examples/export_svg.py +++ b/python/examples/export_svg.py @@ -1,7 +1,7 @@ from binaryninja import * import os,sys -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]} +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]} escape_table = { "'": "'", @@ -16,9 +16,11 @@ def escape(string): return ''.join(escape_table.get(i,i) for i in string) #still escape the basics def save_svg(bv,function): - filename = os.path.basename(bv.file.filename) address = hex(function.start).replace('L','') - outputfile = os.path.join(os.path.expanduser('~'), 'binaryninja-{filename}-{function}.html'.format(filename=filename,function=address)) + filename = 'binaryninja-{filename}-{function}.html'.format(filename=os.path.basename(bv.file.filename),function=address) + outputfile = get_save_filename_input('File name for svg-export', 'HTML files (*.html)', filename) + if outputfile is None: + return content = render_svg(function) output = open(outputfile,'w') output.write(content) @@ -136,13 +138,13 @@ def render_svg(function): output += ' Basic Block {i}\n'.format(i=i) rgb=colors['none'] try: - bb = block.basic_block - color_code = bb.highlight._get_core_struct().color - color_str = bb.highlight._standard_color_to_str(color_code) - if color_str in colors: - rgb=colors[color_str] + bb = block.basic_block + color_code = bb.highlight.color + color_str = bb.highlight._standard_color_to_str(color_code) + if color_str in colors: + rgb=colors[color_str] except: - pass + pass output += ' \n'.format(x=x,y=y,width=width,height=height,r=rgb[0],g=rgb[1],b=rgb[2]) #Render instructions, unfortunately tspans don't allow copying/pasting more @@ -174,4 +176,3 @@ def render_svg(function): return output PluginCommand.register_for_function("Export to SVG", "Exports an SVG of the current function to your home folder.", save_svg) - -- cgit v1.3.1 From e7bb1c066ba1067e6ba93c9bffcf5beb4162f11f Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 20 Sep 2016 01:02:21 -0400 Subject: update svg exporter to use new dialogs --- python/examples/export_svg.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'python/examples/export_svg.py') diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py index 35f35f00..a54dc879 100755 --- a/python/examples/export_svg.py +++ b/python/examples/export_svg.py @@ -1,5 +1,11 @@ from binaryninja import * -import os,sys +import os +import webbrowser +try: + from urllib import pathname2url # Python 2.x +except: + from urllib.request import pathname2url # Python 3.x + 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]} @@ -17,15 +23,19 @@ def escape(string): def save_svg(bv,function): address = hex(function.start).replace('L','') - filename = 'binaryninja-{filename}-{function}.html'.format(filename=os.path.basename(bv.file.filename),function=address) - outputfile = get_save_filename_input('File name for svg-export', 'HTML files (*.html)', filename) + 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 outputfile is None: return content = render_svg(function) output = open(outputfile,'w') output.write(content) output.close() - os.system('%s' % outputfile) + if show_message_box("Open SVG", "Would you like to view the exported SVG?", buttons = core.YesNoButtonSet, icon = core.QuestionIcon) == core.YesButton: + url = 'file:{}'.format(pathname2url(outputfile)) + webbrowser.open(url) def instruction_data_flow(function,address): ''' TODO: Extract data flow information ''' @@ -175,4 +185,4 @@ def render_svg(function): output += '' return output -PluginCommand.register_for_function("Export to SVG", "Exports an SVG of the current function to your home folder.", save_svg) +PluginCommand.register_for_function("Export to SVG", "Exports an SVG of the current function", save_svg) -- cgit v1.3.1