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