From b3e607f82b97bf8fe5718e7634c0a037a8f103ac Mon Sep 17 00:00:00 2001 From: Jordan Date: Tue, 23 Aug 2016 15:55:41 -0400 Subject: no longer use the beta channel name --- python/examples/version-switcher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/examples') diff --git a/python/examples/version-switcher.py b/python/examples/version-switcher.py index a1936a52..087bf7f9 100644 --- a/python/examples/version-switcher.py +++ b/python/examples/version-switcher.py @@ -3,7 +3,7 @@ import sys import binaryninja import datetime -chandefault="private-beta" +chandefault="release" channel=0 versions=0 -- cgit v1.3.1 From 3c19753e3ec474d4c84110b9e6ab8ef1f1971fe2 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Wed, 24 Aug 2016 16:43:33 -0400 Subject: fix export to work on windows --- python/examples/export-svg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python/examples') diff --git a/python/examples/export-svg.py b/python/examples/export-svg.py index 3800edf7..02a6d57e 100755 --- a/python/examples/export-svg.py +++ b/python/examples/export-svg.py @@ -14,7 +14,7 @@ def escape(string): return ''.join(escape_table.get(i,i) for i in string) #still escape the basics def save_svg(bv,function): - filename = bv.file.filename.split(os.sep)[-1] + 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) -- cgit v1.3.1 From 89eb0f36c13428cba18a5e40600aa2e1975e90d5 Mon Sep 17 00:00:00 2001 From: Bambu Date: Thu, 25 Aug 2016 22:54:38 -0400 Subject: Updated arm-syscall plugin to work with current api --- python/examples/README.md | 2 +- python/examples/arm-syscall.py | 18 -------------- python/examples/print_syscalls.py | 50 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 19 deletions(-) delete mode 100644 python/examples/arm-syscall.py create mode 100644 python/examples/print_syscalls.py (limited to 'python/examples') diff --git a/python/examples/README.md b/python/examples/README.md index 7fd3ab6b..5f89496f 100644 --- a/python/examples/README.md +++ b/python/examples/README.md @@ -5,7 +5,7 @@ The following examples demonstrate some of the Binary Ninja API. They include bo ## Stand-alone * bin-info.py - general binary information -* arm-syscall.py - extract syscall numbers from IL for arm Mach-O files +* print_syscalls.py - extract syscall numbers from IL on specified file. Can be run both headless and in Binary Ninja * version-switcher.py - uses the update API to see raw version notes and manually downgrade or upgrade To use the stand-alone Python examples, make sure your `PYTHON_PATH` includes the API, like: diff --git a/python/examples/arm-syscall.py b/python/examples/arm-syscall.py deleted file mode 100644 index f94b8531..00000000 --- a/python/examples/arm-syscall.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -""" - Thanks to @theqlabs from arm.ninja for the nice writeup and idea for this plugin: - http://arm.ninja/2016/03/08/intro-to-binary-ninja-api/ -""" -import sys, binaryninja, time -if len(sys.argv) > 1: - target = sys.argv[1] -else: - raise ValueError("Missing argument to binary.") - -bv = binaryninja.BinaryViewType["Mach-O"].open(target) -bv.update_analysis_and_wait() - -for func in bv.functions: - for il in func.low_level_il: - if il.operation == core.LLIL_SYSCALL: - print "System call address: %x - %d" % (il.address, func.get_reg_value_at_low_level_il_instruction(il.address, bv.platform.system_call_convention.int_arg_regs[0]).value) diff --git a/python/examples/print_syscalls.py b/python/examples/print_syscalls.py new file mode 100644 index 00000000..7e93356c --- /dev/null +++ b/python/examples/print_syscalls.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +""" + Thanks to @theqlabs from arm.ninja for the nice writeup and idea for this plugin: + http://arm.ninja/2016/03/08/intro-to-binary-ninja-api/ +""" +import sys +from itertools import chain + +from binaryninja import BinaryView, core + + +def print_syscalls(bv): + """ Print Syscall numbers for a provided binaryview """ + + calling_convention = bv.platform.system_call_convention + if not calling_convention: + print('Error: No syscall convention available for {:s}'.format(bv.platform)) + return + + register = calling_convention.int_arg_regs[0] + + for func in bv.functions: + syscalls = (il for il in chain.from_iterable(func.low_level_il) + if il.operation == core.LLIL_SYSCALL) + for il in syscalls: + value = func.get_reg_value_at(bv.arch, il.address, register).value + print("System call address: {:#x} - {:d}".format(il.address, value)) + + +def main(): + if len(sys.argv) != 2: + print('Usage: {} '.format(sys.argv[0])) + return -1 + + target = sys.argv[1] + + bv = BinaryView.open(target) + view_type = next(bvt for bvt in bv.available_view_types if bvt.name != 'Raw') + if not view_type: + print('Error: Unable to get any other view type besides Raw') + return -1 + + bv = bv.file.get_view_of_type(view_type.name) + bv.update_analysis_and_wait() + + print_syscalls(bv) + + +if __name__ == "__main__": + sys.exit(main()) -- cgit v1.3.1 From b398b6a0a8683ae844e6b61389d02317f53a252e Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 13 Sep 2016 18:22:57 -0400 Subject: better defaults for version switcher --- python/examples/version-switcher.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'python/examples') diff --git a/python/examples/version-switcher.py b/python/examples/version-switcher.py index 087bf7f9..6199c578 100644 --- a/python/examples/version-switcher.py +++ b/python/examples/version-switcher.py @@ -3,14 +3,14 @@ import sys import binaryninja import datetime -chandefault="release" -channel=0 -versions=0 +chandefault = binaryninja.UpdateChannel.list[0].name +channel = None +versions = [] def load_channel(newchannel): global channel global versions - if (channel != 0 and newchannel == channel.name): + if (channel != None and newchannel == channel.name): print "Same channel, not updating." else: try: -- cgit v1.3.1 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/bin-info.py | 34 ------- python/examples/bin_info.py | 34 +++++++ python/examples/export-svg.py | 166 -------------------------------- python/examples/export_svg.py | 166 ++++++++++++++++++++++++++++++++ python/examples/instruction-iterator.py | 49 ---------- python/examples/instruction_iterator.py | 49 ++++++++++ python/examples/jump-table.py | 63 ------------ python/examples/jump_table.py | 63 ++++++++++++ python/examples/version-switcher.py | 119 ----------------------- python/examples/version_switcher.py | 119 +++++++++++++++++++++++ 10 files changed, 431 insertions(+), 431 deletions(-) delete mode 100644 python/examples/bin-info.py create mode 100644 python/examples/bin_info.py delete mode 100755 python/examples/export-svg.py create mode 100755 python/examples/export_svg.py delete mode 100644 python/examples/instruction-iterator.py create mode 100644 python/examples/instruction_iterator.py delete mode 100644 python/examples/jump-table.py create mode 100644 python/examples/jump_table.py delete mode 100644 python/examples/version-switcher.py create mode 100644 python/examples/version_switcher.py (limited to 'python/examples') diff --git a/python/examples/bin-info.py b/python/examples/bin-info.py deleted file mode 100644 index 48073894..00000000 --- a/python/examples/bin-info.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python -import sys, binaryninja, time -if sys.platform.lower().startswith("linux"): - bintype="ELF" -elif sys.platform.lower() == "darwin": - bintype="Mach-O" -else: - raise Exception, "%s is not supported on this plugin" % sys.platform - -if len(sys.argv) > 1: - target = sys.argv[1] -else: - target = "/bin/ls" - -bv = binaryninja.BinaryViewType[bintype].open(target) -bv.update_analysis_and_wait() - -print "-------- %s --------" % target -print "START: 0x%x" % bv.start -print "ENTRY: 0x%x" % bv.entry_point -print "ARCH: %s" % bv.arch.name -print "\n-------- Function List --------" - -for func in bv.functions: - print func.symbol.name - - -print "\n-------- First 10 strings --------" - -for i in xrange(10): - start = bv.strings[i].start - length = bv.strings[i].length - string = bv.read(start,length) - print "0x%x (%d):\t%s" % (start, length, string) diff --git a/python/examples/bin_info.py b/python/examples/bin_info.py new file mode 100644 index 00000000..48073894 --- /dev/null +++ b/python/examples/bin_info.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +import sys, binaryninja, time +if sys.platform.lower().startswith("linux"): + bintype="ELF" +elif sys.platform.lower() == "darwin": + bintype="Mach-O" +else: + raise Exception, "%s is not supported on this plugin" % sys.platform + +if len(sys.argv) > 1: + target = sys.argv[1] +else: + target = "/bin/ls" + +bv = binaryninja.BinaryViewType[bintype].open(target) +bv.update_analysis_and_wait() + +print "-------- %s --------" % target +print "START: 0x%x" % bv.start +print "ENTRY: 0x%x" % bv.entry_point +print "ARCH: %s" % bv.arch.name +print "\n-------- Function List --------" + +for func in bv.functions: + print func.symbol.name + + +print "\n-------- First 10 strings --------" + +for i in xrange(10): + start = bv.strings[i].start + length = bv.strings[i].length + string = bv.read(start,length) + print "0x%x (%d):\t%s" % (start, length, string) diff --git a/python/examples/export-svg.py b/python/examples/export-svg.py deleted file mode 100755 index 02a6d57e..00000000 --- a/python/examples/export-svg.py +++ /dev/null @@ -1,166 +0,0 @@ -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) 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) diff --git a/python/examples/instruction-iterator.py b/python/examples/instruction-iterator.py deleted file mode 100644 index 43bc000e..00000000 --- a/python/examples/instruction-iterator.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python - -import sys -try: - import binaryninja -except ImportError: - sys.path.append("/Applications/Binary Ninja.app/Contents/Resources/python/") - import binaryninja -import time - -if sys.platform.lower().startswith("linux"): - bintype="ELF" -elif sys.platform.lower() == "darwin": - bintype="Mach-O" -else: - raise Exception, "%s is not supported on this plugin" % sys.platform - -if len(sys.argv) > 1: - target = sys.argv[1] -else: - target = "/bin/ls" - -bv = binaryninja.BinaryViewType[bintype].open(target) -bv.update_analysis_and_wait() - -print "-------- %s --------" % target -print "START: 0x%x" % bv.start -print "ENTRY: 0x%x" % bv.entry_point -print "ARCH: %s" % bv.arch.name -print "\n-------- Function List --------" - -""" print all the functions, their basic blocks, and their il instructions """ -for func in bv.functions: - print repr(func) - for block in func.low_level_il: - print "\t{0}".format(block) - - for insn in block: - print "\t\t{0}".format(insn) - - -""" print all the functions, their basic blocks, and their mc instructions """ -for func in bv.functions: - print repr(func) - for block in func: - print "\t{0}".format(block) - - for insn in block: - print "\t\t{0}".format(insn) diff --git a/python/examples/instruction_iterator.py b/python/examples/instruction_iterator.py new file mode 100644 index 00000000..43bc000e --- /dev/null +++ b/python/examples/instruction_iterator.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +import sys +try: + import binaryninja +except ImportError: + sys.path.append("/Applications/Binary Ninja.app/Contents/Resources/python/") + import binaryninja +import time + +if sys.platform.lower().startswith("linux"): + bintype="ELF" +elif sys.platform.lower() == "darwin": + bintype="Mach-O" +else: + raise Exception, "%s is not supported on this plugin" % sys.platform + +if len(sys.argv) > 1: + target = sys.argv[1] +else: + target = "/bin/ls" + +bv = binaryninja.BinaryViewType[bintype].open(target) +bv.update_analysis_and_wait() + +print "-------- %s --------" % target +print "START: 0x%x" % bv.start +print "ENTRY: 0x%x" % bv.entry_point +print "ARCH: %s" % bv.arch.name +print "\n-------- Function List --------" + +""" print all the functions, their basic blocks, and their il instructions """ +for func in bv.functions: + print repr(func) + for block in func.low_level_il: + print "\t{0}".format(block) + + for insn in block: + print "\t\t{0}".format(insn) + + +""" print all the functions, their basic blocks, and their mc instructions """ +for func in bv.functions: + print repr(func) + for block in func: + print "\t{0}".format(block) + + for insn in block: + print "\t\t{0}".format(insn) diff --git a/python/examples/jump-table.py b/python/examples/jump-table.py deleted file mode 100644 index 39fed1a5..00000000 --- a/python/examples/jump-table.py +++ /dev/null @@ -1,63 +0,0 @@ -# This plugin will attempt to resolve simple jump tables (an array of code pointers) and add the destinations -# as indirect branch targets so that the flow graph reflects the jump table's control flow. -from binaryninja import * -import struct - -def find_jump_table(bv, addr): - for block in bv.get_basic_blocks_at(addr): - func = block.function - arch = func.arch - addrsize = arch.address_size - - # Grab the instruction tokens so that we can look for the table's starting address - tokens, length = arch.get_instruction_text(bv.read(addr, 16), addr) - - # Look for the next jump instruction, which may be the current instruction. Some jump tables will - # compute the address first then jump to the computed address as a separate instruction. - jump_addr = addr - while jump_addr < block.end: - info = arch.get_instruction_info(bv.read(jump_addr, 16), jump_addr) - if len(info.branches) != 0: - break - jump_addr += info.length - if jump_addr >= block.end: - print "Unable to find jump after instruction 0x%x" % addr - continue - print "Jump at 0x%x" % jump_addr - - # Collect the branch targets for any tables referenced by the clicked instruction - branches = [] - for token in tokens: - if token.type == "PossibleAddressToken": # Table addresses will be a "possible address" token - tbl = token.value - print "Found possible table at 0x%x" % tbl - i = 0 - while True: - # Read the next pointer from the table - data = bv.read(tbl + (i * addrsize), addrsize) - if len(data) == addrsize: - if addrsize == 4: - ptr = struct.unpack("= bv.start) and (ptr < bv.end): - print "Found destination 0x%x" % ptr - branches.append((arch, ptr)) - else: - # Once a value that is not a pointer is encountered, the jump table is ended - break - else: - # Reading invalid memory - break - - i += 1 - - # Set the indirect branch targets on the jump instruction to be the list of targets discovered - func.set_user_indirect_branches(arch, jump_addr, branches) - -# Create a plugin command so that the user can right click on an instruction referencing a jump table and -# invoke the command -PluginCommand.register_for_address("Process jump table", "Look for jump table destinations", find_jump_table) diff --git a/python/examples/jump_table.py b/python/examples/jump_table.py new file mode 100644 index 00000000..39fed1a5 --- /dev/null +++ b/python/examples/jump_table.py @@ -0,0 +1,63 @@ +# This plugin will attempt to resolve simple jump tables (an array of code pointers) and add the destinations +# as indirect branch targets so that the flow graph reflects the jump table's control flow. +from binaryninja import * +import struct + +def find_jump_table(bv, addr): + for block in bv.get_basic_blocks_at(addr): + func = block.function + arch = func.arch + addrsize = arch.address_size + + # Grab the instruction tokens so that we can look for the table's starting address + tokens, length = arch.get_instruction_text(bv.read(addr, 16), addr) + + # Look for the next jump instruction, which may be the current instruction. Some jump tables will + # compute the address first then jump to the computed address as a separate instruction. + jump_addr = addr + while jump_addr < block.end: + info = arch.get_instruction_info(bv.read(jump_addr, 16), jump_addr) + if len(info.branches) != 0: + break + jump_addr += info.length + if jump_addr >= block.end: + print "Unable to find jump after instruction 0x%x" % addr + continue + print "Jump at 0x%x" % jump_addr + + # Collect the branch targets for any tables referenced by the clicked instruction + branches = [] + for token in tokens: + if token.type == "PossibleAddressToken": # Table addresses will be a "possible address" token + tbl = token.value + print "Found possible table at 0x%x" % tbl + i = 0 + while True: + # Read the next pointer from the table + data = bv.read(tbl + (i * addrsize), addrsize) + if len(data) == addrsize: + if addrsize == 4: + ptr = struct.unpack("= bv.start) and (ptr < bv.end): + print "Found destination 0x%x" % ptr + branches.append((arch, ptr)) + else: + # Once a value that is not a pointer is encountered, the jump table is ended + break + else: + # Reading invalid memory + break + + i += 1 + + # Set the indirect branch targets on the jump instruction to be the list of targets discovered + func.set_user_indirect_branches(arch, jump_addr, branches) + +# Create a plugin command so that the user can right click on an instruction referencing a jump table and +# invoke the command +PluginCommand.register_for_address("Process jump table", "Look for jump table destinations", find_jump_table) diff --git a/python/examples/version-switcher.py b/python/examples/version-switcher.py deleted file mode 100644 index 6199c578..00000000 --- a/python/examples/version-switcher.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -import sys -import binaryninja -import datetime - -chandefault = binaryninja.UpdateChannel.list[0].name -channel = None -versions = [] - -def load_channel(newchannel): - global channel - global versions - if (channel != None and newchannel == channel.name): - print "Same channel, not updating." - else: - try: - print "Loading channel %s" % newchannel - channel = binaryninja.UpdateChannel[newchannel] - print "Loading versions..." - versions = channel.versions - except Exception: - print "%s is not a valid channel name. Defaulting to " % chandefault - channel = binaryninja.UpdateChannel[chandefault] - -def select(version): - done = False - date = datetime.datetime.fromtimestamp(version.time).strftime('%c') - while not done: - print "Version:\t%s" % version.version - print "Updated:\t%s" % date - print "Notes:\n\n-----\n%s" % version.notes - print "-----" - print "\t1)\tSwitch to version" - print "\t2)\tMain Menu" - selection = raw_input('Choice: ') - if selection.isdigit(): - selection = int(selection) - else: - selection = 0 - if (selection == 2): - done = True - elif (selection == 1): - if (version.version == channel.latest_version.version): - print "Requesting update to latest version." - else: - print "Requesting update to prior version." - if binaryninja.are_auto_updates_enabled(): - print "Disabling automatic updates." - binaryninja.set_auto_updates_enabled(False) - if (version.version == binaryninja.core_version): - print "Already running %s" % version.version - else: - print "version.version %s" % version.version - print "binaryninja.core_version %s" % binaryninja.core_version - print "Updating..." - print version.update() - #forward updating won't work without reloading - sys.exit() - else: - print "Invalid selection" - -def list_channels(): - done = False - print "\tSelect channel:\n" - while not done: - channel_list = binaryninja.UpdateChannel.list - for index, item in enumerate(channel_list): - print "\t%d)\t%s" % (index+1, item.name) - print "\t%d)\t%s" % (len(channel_list)+1, "Main Menu") - selection = raw_input('Choice: ') - if selection.isdigit(): - selection = int(selection) - else: - selection = 0 - if (selection <= 0 or selection > len(channel_list)+1): - print "%s is an invalid choice." % selection - else: - done = True - if (selection != len(channel_list) + 1): - load_channel(channel_list[selection - 1].name) - -def toggle_updates(): - binaryninja.set_auto_updates_enabled(not binaryninja.are_auto_updates_enabled()) - -def main(): - global channel - done = False - load_channel(chandefault) - while not done: - print "\n\tBinary Ninja Version Switcher" - print "\t\tCurrent Channel:\t%s" % channel.name - print "\t\tCurrent Version:\t%s" % binaryninja.core_version - print "\t\tAuto-Updates On:\t%s\n" % binaryninja.are_auto_updates_enabled() - for index, version in enumerate(versions): - date = datetime.datetime.fromtimestamp(version.time).strftime('%c') - print "\t%d)\t%s (%s)" % (index + 1, version.version, date) - print "\t%d)\t%s" % (len(versions) + 1, "Switch Channel") - print "\t%d)\t%s" % (len(versions) + 2, "Toggle Auto Updates") - print "\t%d)\t%s" % (len(versions) + 3, "Exit") - selection = raw_input('Choice: ') - if selection.isdigit(): - selection = int(selection) - else: - selection = 0 - if (selection <= 0 or selection > len(versions) + 3): - print "%d is an invalid choice.\n\n" % selection - else: - if (selection == len(versions) + 3): - done = True - elif (selection == len(versions) + 2): - toggle_updates() - elif (selection == len(versions) + 1): - list_channels() - else: - select(versions[selection - 1]) - - -if __name__ == "__main__": - main() diff --git a/python/examples/version_switcher.py b/python/examples/version_switcher.py new file mode 100644 index 00000000..6199c578 --- /dev/null +++ b/python/examples/version_switcher.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +import sys +import binaryninja +import datetime + +chandefault = binaryninja.UpdateChannel.list[0].name +channel = None +versions = [] + +def load_channel(newchannel): + global channel + global versions + if (channel != None and newchannel == channel.name): + print "Same channel, not updating." + else: + try: + print "Loading channel %s" % newchannel + channel = binaryninja.UpdateChannel[newchannel] + print "Loading versions..." + versions = channel.versions + except Exception: + print "%s is not a valid channel name. Defaulting to " % chandefault + channel = binaryninja.UpdateChannel[chandefault] + +def select(version): + done = False + date = datetime.datetime.fromtimestamp(version.time).strftime('%c') + while not done: + print "Version:\t%s" % version.version + print "Updated:\t%s" % date + print "Notes:\n\n-----\n%s" % version.notes + print "-----" + print "\t1)\tSwitch to version" + print "\t2)\tMain Menu" + selection = raw_input('Choice: ') + if selection.isdigit(): + selection = int(selection) + else: + selection = 0 + if (selection == 2): + done = True + elif (selection == 1): + if (version.version == channel.latest_version.version): + print "Requesting update to latest version." + else: + print "Requesting update to prior version." + if binaryninja.are_auto_updates_enabled(): + print "Disabling automatic updates." + binaryninja.set_auto_updates_enabled(False) + if (version.version == binaryninja.core_version): + print "Already running %s" % version.version + else: + print "version.version %s" % version.version + print "binaryninja.core_version %s" % binaryninja.core_version + print "Updating..." + print version.update() + #forward updating won't work without reloading + sys.exit() + else: + print "Invalid selection" + +def list_channels(): + done = False + print "\tSelect channel:\n" + while not done: + channel_list = binaryninja.UpdateChannel.list + for index, item in enumerate(channel_list): + print "\t%d)\t%s" % (index+1, item.name) + print "\t%d)\t%s" % (len(channel_list)+1, "Main Menu") + selection = raw_input('Choice: ') + if selection.isdigit(): + selection = int(selection) + else: + selection = 0 + if (selection <= 0 or selection > len(channel_list)+1): + print "%s is an invalid choice." % selection + else: + done = True + if (selection != len(channel_list) + 1): + load_channel(channel_list[selection - 1].name) + +def toggle_updates(): + binaryninja.set_auto_updates_enabled(not binaryninja.are_auto_updates_enabled()) + +def main(): + global channel + done = False + load_channel(chandefault) + while not done: + print "\n\tBinary Ninja Version Switcher" + print "\t\tCurrent Channel:\t%s" % channel.name + print "\t\tCurrent Version:\t%s" % binaryninja.core_version + print "\t\tAuto-Updates On:\t%s\n" % binaryninja.are_auto_updates_enabled() + for index, version in enumerate(versions): + date = datetime.datetime.fromtimestamp(version.time).strftime('%c') + print "\t%d)\t%s (%s)" % (index + 1, version.version, date) + print "\t%d)\t%s" % (len(versions) + 1, "Switch Channel") + print "\t%d)\t%s" % (len(versions) + 2, "Toggle Auto Updates") + print "\t%d)\t%s" % (len(versions) + 3, "Exit") + selection = raw_input('Choice: ') + if selection.isdigit(): + selection = int(selection) + else: + selection = 0 + if (selection <= 0 or selection > len(versions) + 3): + print "%d is an invalid choice.\n\n" % selection + else: + if (selection == len(versions) + 3): + done = True + elif (selection == len(versions) + 2): + toggle_updates() + elif (selection == len(versions) + 1): + list_channels() + else: + select(versions[selection - 1]) + + +if __name__ == "__main__": + main() -- 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') 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 9ab0ead47220d704a3c80cae25ddd05afac55271 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 19 Sep 2016 23:57:57 -0400 Subject: Add example plugin to solve with angr --- python/examples/angr_plugin.py | 120 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 python/examples/angr_plugin.py (limited to 'python/examples') diff --git a/python/examples/angr_plugin.py b/python/examples/angr_plugin.py new file mode 100644 index 00000000..5d567511 --- /dev/null +++ b/python/examples/angr_plugin.py @@ -0,0 +1,120 @@ +# This plugin assumes angr is already installed and available on the system. See the angr documentation +# for information about installing angr. It should be installed using the virtualenv method. +# +# This plugin is currently only known to work on Linux using virtualenv. Switch to the virtual environment +# (using a command such as "workon angr"), then run the Binary Ninja UI from the command line. +# +# This method is known to fail on Mac OS X as the virtualenv used by angr does not appear to provide a +# way to automatically link to the correct version of Python, even when running the UI from within the +# virtual environment. A later update may allow for a manual override to link to the required version +# of Python. + +__name__ = "__console__" # angr looks for this, it won't load from within a UI without it +import angr +from binaryninja import * +import tempfile +import threading +import logging +import os + +# Disable warning logs as they show up as errors in the UI +logging.disable(logging.WARNING) + +# Create sets in the BinaryView's data field to store the desired path for each view +BinaryView.set_default_data("angr_find", set()) +BinaryView.set_default_data("angr_avoid", set()) + +def escaped_output(str): + return '\n'.join([s.encode("string_escape") for s in str.split('\n')]) + +# Define a background thread object for solving in the background +class Solver(BackgroundTaskThread): + def __init__(self, find, avoid, view): + BackgroundTaskThread.__init__(self, "Solving with angr...", True) + self.find = tuple(find) + self.avoid = tuple(avoid) + self.view = view + + # Write the binary to disk so that the angr API can read it + self.binary = tempfile.NamedTemporaryFile() + self.binary.write(view.file.raw.read(0, len(view.file.raw))) + self.binary.flush() + + def run(self): + # Create an angr project and an explorer with the user's settings + p = angr.Project(self.binary.name) + e = p.surveyors.Explorer(find = self.find, avoid = self.avoid) + + # Solve loop + while not e.done: + if self.cancelled: + # Solve cancelled, show results if there were any + if len(e.found) > 0: + break + return + + # Perform the next step in the solve + e.step() + + # Update status + active_count = len(e.active) + found_count = len(e.found) + + progress = "Solving with angr (%d active path%s" % (active_count, "s" if active_count != 1 else "") + if found_count > 0: + progress += ", %d path%s found" % (found_count, "s" if found_count != 1 else "") + self.progress = progress + ")..." + + # Solve complete, show report + text_report = "Found %d path%s.\n\n" % (len(e.found), "s" if len(e.found) != 1 else "") + i = 1 + for f in e.found: + text_report += "Path %d\n" % i + "=" * 10 + "\n" + text_report += "stdin:\n" + escaped_output(f.state.posix.dumps(0)) + "\n\n" + text_report += "stdout:\n" + escaped_output(f.state.posix.dumps(1)) + "\n\n" + text_report += "stderr:\n" + escaped_output(f.state.posix.dumps(2)) + "\n\n" + i += 1 + + name = self.view.file.filename + if len(name) > 0: + show_plain_text_report("Results from angr - " + os.path.basename(self.view.file.filename), text_report) + else: + show_plain_text_report("Results from angr", text_report) + +def find_instr(bv, addr): + # Highlight the instruction in green + blocks = bv.get_basic_blocks_at(addr) + for block in blocks: + block.set_auto_highlight(HighlightColor(GreenHighlightColor, alpha = 128)) + block.function.set_auto_instr_highlight(block.arch, addr, GreenHighlightColor) + + # Add the instruction to the list associated with the current view + bv.data.angr_find.add(addr) + +def avoid_instr(bv, addr): + # Highlight the instruction in red + blocks = bv.get_basic_blocks_at(addr) + for block in blocks: + block.set_auto_highlight(HighlightColor(RedHighlightColor, alpha = 128)) + block.function.set_auto_instr_highlight(block.arch, addr, RedHighlightColor) + + # Add the instruction to the list associated with the current view + bv.data.angr_avoid.add(addr) + +def solve(bv): + if len(bv.data.angr_find) == 0: + show_message_box("Angr Solve", "You have not specified a goal instruction.\n\n" + + "Please right click on the goal instruction and select \"Find Path to This Instruction\" to " + + "continue.", OKButtonSet, ErrorIcon) + return + + # Start a solver thread for the path associated with the view + s = Solver(bv.data.angr_find, bv.data.angr_avoid, bv) + s.start() + +# Register commands for the user to interact with the plugin +PluginCommand.register_for_address("Find Path to This Instruction", + "When solving, find a path that gets to this instruction", find_instr) +PluginCommand.register_for_address("Avoid This Instruction", + "When solving, avoid paths that reach this instruction", avoid_instr) +PluginCommand.register("Solve With Angr", "Attempt to solve for a path that satisfies the constraints given", solve) -- 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') 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') 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 From 0ee439859c9f09ed0d725bef385bcc9ac6d635a1 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Wed, 21 Sep 2016 11:16:35 -0400 Subject: update for new plugins and mention difference between personal and commercial --- python/examples/README.md | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'python/examples') diff --git a/python/examples/README.md b/python/examples/README.md index 5f89496f..43af34be 100644 --- a/python/examples/README.md +++ b/python/examples/README.md @@ -4,11 +4,14 @@ The following examples demonstrate some of the Binary Ninja API. They include bo ## Stand-alone -* bin-info.py - general binary information +These plugins only operate when run directly outside of the UI + +* bin_info.py - general binary information * print_syscalls.py - extract syscall numbers from IL on specified file. Can be run both headless and in Binary Ninja -* version-switcher.py - uses the update API to see raw version notes and manually downgrade or upgrade +* version_switcher.py - uses the update API to see raw version notes and manually downgrade or upgrade +* instruction_iterator.py - very simple plugin that iterates through functions, blocks, and instructions -To use the stand-alone Python examples, make sure your `PYTHON_PATH` includes the API, like: +To use the stand-alone Python examples, make sure your `PYTHON_PATH` includes the API, as shown below. Please note, this is a feature that requires the "GUI-less processing" capability not available in the personal edition. In the personal edition, all scripts must by run from the integrated python console (follow the directions below under "Loading Plugins" section) ``` PYTHONPATH=$PYTHONPATH:/Applications/Binary\ Ninja.app/Contents/Resources/python @@ -16,9 +19,21 @@ PYTHONPATH=$PYTHONPATH:/Applications/Binary\ Ninja.app/Contents/Resources/python ## GUI Plugins -* nes.py - 6502 CPU architecture including LLIL lifting and `.NES` file format parser +These plugins require the UI to be running + * breakpoint.py - small example showing how to modify a file and register a GUI menu item -* jump-table.py - stop-gap jump table plugin triggered via right-click menu at an indirect jump +* jump_table.py - heuristic based jump table detection for when the data-flow based computation fails, triggered by right-clicking on the location where the jump value is computed +* angr_plugin.py - a plugin to demonstrate both background threads, the simplified plugin UI elements, and highlighting +* export_svg.py - exports the graph view of a function to an SVG file for including in reports + +## Both + +These plugins are able to operate in either the GUI or as stand-alone plugins + +* nes.py - 6502 CPU architecture including LLIL lifting and `.NES` file format parser + + +## Loading Plugins Plugins are meant to be loaded into a running Binary Ninja GUI and should either be copied or symlinked into the appropriate plugin folder. You'll need to then re-start Binary Ninja. -- cgit v1.3.1 From 78a13604bfeba1798379d15d6e26f4b6c128bda1 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 26 Sep 2016 17:23:05 -0400 Subject: Fix NES plugin after API changes --- python/__init__.py | 4 +++- python/examples/nes.py | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) (limited to 'python/examples') diff --git a/python/__init__.py b/python/__init__.py index 80302c0c..26c8fb5d 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1022,7 +1022,7 @@ class BinaryView(object): self.file = file_metadata self.handle = core.BNCreateCustomBinaryView(self.__class__.name, file_metadata.handle, self._cb) self.notifications = {} - self.next_address = self.entry_point + self.next_address = None # Do NOT try to access view before init() is called, use placeholder @classmethod def register(cls): @@ -1579,6 +1579,8 @@ class BinaryView(object): """ if arch is None: arch = self.arch + if self.next_address is None: + self.next_address = self.entry_point txt, size = arch.get_instruction_text(self.read(self.next_address, self.arch.max_instr_length), self.next_address) self.next_address += size if txt is None: diff --git a/python/examples/nes.py b/python/examples/nes.py index 5cb6bc0d..00f9d8eb 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -521,9 +521,9 @@ class NESView(BinaryView): def __init__(self, data): BinaryView.__init__(self, data.file) - self.data = data + self.raw = data self.notification = NESViewUpdateNotification(self) - self.data.register_notification(self.notification) + self.raw.register_notification(self.notification) @classmethod def is_valid_for_data(self, data): @@ -539,7 +539,7 @@ class NESView(BinaryView): def init(self): try: - hdr = self.data.read(0, 16) + hdr = self.raw.read(0, 16) self.rom_banks = struct.unpack("B", hdr[4])[0] self.vrom_banks = struct.unpack("B", hdr[5])[0] self.rom_flags = struct.unpack("B", hdr[6])[0] @@ -592,9 +592,9 @@ class NESView(BinaryView): self.define_auto_symbol(Symbol(DataSymbol, 0x4016, "JOY1")) self.define_auto_symbol(Symbol(DataSymbol, 0x4017, "JOY2")) - sym_files = [self.data.file.filename + ".%x.nl" % self.__class__.bank, - self.data.file.filename + ".ram.nl", - self.data.file.filename + ".%x.nl" % (self.rom_banks - 1)] + sym_files = [self.raw.file.filename + ".%x.nl" % self.__class__.bank, + self.raw.file.filename + ".ram.nl", + self.raw.file.filename + ".%x.nl" % (self.rom_banks - 1)] for f in sym_files: if os.path.exists(f): sym_contents = open(f, "r").read() @@ -634,9 +634,9 @@ class NESView(BinaryView): else: to_read = length if addr < 0xc000: - data = self.data.read(self.rom_offset + bank_ofs + (self.__class__.bank * 0x4000), to_read) + data = self.raw.read(self.rom_offset + bank_ofs + (self.__class__.bank * 0x4000), to_read) else: - data = self.data.read(self.rom_offset + bank_ofs + self.rom_length - 0x4000, to_read) + data = self.raw.read(self.rom_offset + bank_ofs + self.rom_length - 0x4000, to_read) result += data if len(data) < to_read: break @@ -663,9 +663,9 @@ class NESView(BinaryView): else: to_write = length if addr < 0xc000: - written = self.data.write(self.rom_offset + bank_ofs + (self.__class__.bank * 0x4000), value[offset : offset + to_write]) + written = self.raw.write(self.rom_offset + bank_ofs + (self.__class__.bank * 0x4000), value[offset : offset + to_write]) else: - written = self.data.write(self.rom_offset + bank_ofs + self.rom_length - 0x4000, value[offset : offset + to_write]) + written = self.raw.write(self.rom_offset + bank_ofs + self.rom_length - 0x4000, value[offset : offset + to_write]) if written < to_write: break length -= to_write -- cgit v1.3.1