diff options
| author | Jordan Wiens <jordan@psifertex.com> | 2016-11-14 21:57:57 -0500 |
|---|---|---|
| committer | Jordan Wiens <jordan@psifertex.com> | 2016-11-14 21:57:57 -0500 |
| commit | de07cda2227dfa2cd560ebb1187e3aa3946a081f (patch) | |
| tree | 527cadaa052e9b27df862f78b88e8ea1ed5f7e87 /python/examples | |
| parent | bd3117ef0e09276a77ada277413743776ffc9ce1 (diff) | |
basic NSF loader
Diffstat (limited to 'python/examples')
| -rw-r--r-- | python/examples/nsf.py | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/python/examples/nsf.py b/python/examples/nsf.py new file mode 100644 index 00000000..9d4ebd5c --- /dev/null +++ b/python/examples/nsf.py @@ -0,0 +1,138 @@ +# Copyright (c) 2015-2016 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# +# Simple NSF file loader, primarily for analyzing: +# https://scarybeastsecurity.blogspot.com/2016/11/0day-exploit-compromising-linux-desktop.html +# + +from binaryninja import * +import struct +import traceback +import os + +class NSFView(BinaryView): + name = "NSF" + long_name = "Nintendo Sound Format" + + def __init__(self, data): + BinaryView.__init__(self, parent_view = data, file_metadata = data.file) + + @classmethod + def is_valid_for_data(self, data): + hdr = data.read(0, 128) + if len(hdr) < 128: + return False + if hdr[0:5] != "NESM\x1a": + return False + song_count = struct.unpack("B", hdr[6])[0] + if song_count < 1: + log_info("Appears to be an NSF, but no songs.") + return False + return True + + def init(self): + try: + hdr = self.parent_view.read(0, 128) + self.version = struct.unpack("B", hdr[5])[0] + self.song_count = struct.unpack("B", hdr[6])[0] + self.starting_song = struct.unpack("B", hdr[7])[0] + self.load_address = struct.unpack("<H", hdr[8:10])[0] + self.init_address = struct.unpack("<H", hdr[10:12])[0] + self.play_address = struct.unpack("<H", hdr[12:14])[0] + self.song_name = hdr[15].split('\0')[0] + self.artist_name = hdr[46].split('\0')[0] + self.copyright_name = hdr[78].split('\0')[0] + self.play_speed_ntsc = struct.unpack("<H", hdr[110:112])[0] + self.bank_switching = hdr[112:120] + self.play_speed_pal = struct.unpack("<H", hdr[120:122])[0] + self.pal_ntsc_bits = struct.unpack("B", hdr[122])[0] + self.pal = True if (self.pal_ntsc_bits & 1) == 1 else False + self.ntsc = not self.pal + if self.pal_ntsc_bits & 2 == 2: + self.pal = True + self.ntsc = True + self.extra_sound_bits = struct.unpack("B", hdr[123])[0] + + if self.bank_switching == "\0"*8: + #no bank switching + self.load_address & 0xFFF + self.rom_offset = 128 + + else: + #bank switching not implemented + log_info("Bank switching not implemented in this loader.") + + # Add mapping for RAM and hardware registers, not backed by file contents + self.add_auto_segment(0, 0x8000, 0, 0, SegmentReadable | SegmentWritable | SegmentExecutable) + + # Add ROM mappings + self.add_auto_segment(0x8000, 0x4000, self.rom_offset, 0x4000, + SegmentReadable | SegmentExecutable) + + self.define_auto_symbol(Symbol(FunctionSymbol, self.play_address, "_play")) + self.define_auto_symbol(Symbol(FunctionSymbol, self.init_address, "_init")) + self.add_entry_point(Architecture['6502'].standalone_platform, self.init_address) + self.add_function(Architecture['6502'].standalone_platform, self.play_address) + + # Hardware registers + self.define_auto_symbol(Symbol(DataSymbol, 0x2000, "PPUCTRL")) + self.define_auto_symbol(Symbol(DataSymbol, 0x2001, "PPUMASK")) + self.define_auto_symbol(Symbol(DataSymbol, 0x2002, "PPUSTATUS")) + self.define_auto_symbol(Symbol(DataSymbol, 0x2003, "OAMADDR")) + self.define_auto_symbol(Symbol(DataSymbol, 0x2004, "OAMDATA")) + self.define_auto_symbol(Symbol(DataSymbol, 0x2005, "PPUSCROLL")) + self.define_auto_symbol(Symbol(DataSymbol, 0x2006, "PPUADDR")) + self.define_auto_symbol(Symbol(DataSymbol, 0x2007, "PPUDATA")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4000, "SQ1_VOL")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4001, "SQ1_SWEEP")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4002, "SQ1_LO")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4003, "SQ1_HI")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4004, "SQ2_VOL")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4005, "SQ2_SWEEP")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4006, "SQ2_LO")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4007, "SQ2_HI")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4008, "TRI_LINEAR")) + self.define_auto_symbol(Symbol(DataSymbol, 0x400a, "TRI_LO")) + self.define_auto_symbol(Symbol(DataSymbol, 0x400b, "TRI_HI")) + self.define_auto_symbol(Symbol(DataSymbol, 0x400c, "NOISE_VOL")) + self.define_auto_symbol(Symbol(DataSymbol, 0x400e, "NOISE_LO")) + self.define_auto_symbol(Symbol(DataSymbol, 0x400f, "NOISE_HI")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4010, "DMC_FREQ")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4011, "DMC_RAW")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4012, "DMC_START")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4013, "DMC_LEN")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4014, "OAMDMA")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4015, "SND_CHN")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4016, "JOY1")) + self.define_auto_symbol(Symbol(DataSymbol, 0x4017, "JOY2")) + + return True + except: + log_error(traceback.format_exc()) + return False + + def perform_is_executable(self): + return True + + def perform_get_entry_point(self): + return struct.unpack("<H", str(self.perform_read(0x0a, 2)))[0] + +NSFView.register() |
