├── binutils ├── strings.py ├── getinfo.py ├── nm.py ├── findmagic.py └── README.md ├── README.md ├── LICENSE ├── pattern ├── applypattern.py ├── makepattern.py └── README.md ├── ipcserver ├── unicornhelpers.py ├── README.md ├── demangling.py ├── ipcserver_classic.py └── itanium_demangler.py ├── swipc-gen ├── unicornhelpers.py ├── README.md ├── demangling.py ├── hashes_gen.py ├── generatehashes.py └── ipcclient.py ├── loader └── README.md └── ipcclient ├── genidaclientscript.py ├── demangling.py ├── README.md ├── ipcclient.py └── itanium_demangler.py /binutils/strings.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | from nxo64 import load_nxo 4 | 5 | SEARCH_ALL_SECTIONS = False 6 | 7 | def main(filenames): 8 | for filename in filenames: 9 | try: 10 | with open(filename, 'rb') as li: 11 | f = load_nxo(li) 12 | except Exception as e: 13 | print filename, e 14 | continue 15 | if SEARCH_ALL_SECTIONS: 16 | f.binfile.seek(0) 17 | as_string = f.binfile.read_to_end() 18 | else: 19 | f.binfile.seek(f.rodataoff) 20 | as_string = f.binfile.read(f.rodatasize) 21 | strs = re.finditer(r'[ -~]{5,}', as_string) 22 | for i in strs: 23 | start = i.start() + f.rodataoff + 0x7100000000 24 | print '%s(%X): %s' % (filename, start, i.group(0)) 25 | 26 | if __name__ == '__main__': 27 | main(sys.argv[1:]) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # switch-reversing 2 | 3 | These are my personal Switch reversing scripts. 4 | 5 | This is all a bit messy and chaotic, but I'm going to try to push my personal RE scripts and tools a bit more, since they can be pretty useful. Use at your own risk, no warranty, etc. 6 | 7 | * `swipc-gen` is code for automated extraction of IPC information used to generate these diffs: https://gist.github.com/hthh/bb896c743878a2c0c337f41febdc0426 8 | * `binutils` has simple utilities for dumping information from Switch binaries. 9 | * `pattern` is a pair of scripts for identifying and naming common library code in 64-bit binaries (where you have one file with the code with symbols, and another with the same code, but without symbols). 10 | * `ipcserver` contains scripts for automatically finding the implementations of IPC commands in sysmodule binaries. 11 | * `ipcclient` contains a script I use to generate vtable structures for IPC client code using IDA and the Hex-Rays decompiler. 12 | * `loader` contains my personal fork of the ReSwitched loader with a number of other useful features. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2019 hthh and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /pattern/applypattern.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | import nxo64 4 | 5 | def main(pattern, filename): 6 | f = nxo64.load_nxo(open(filename, 'rb')) 7 | 8 | f.binfile.seek(0) 9 | target_text = f.binfile.read(f.textsize) 10 | 11 | rows = eval('[' + open(pattern).read() + ']') 12 | with open(filename + '-sdk-syms.py', 'wb') as f: 13 | 14 | f.write('syms = [\n') 15 | for value, size, regex, name in rows: 16 | #print '(0x%X, 0x%X, %r, %r),' % (sym.value, sym.size, regex, sym.name) 17 | positions = [m.start() for m in re.finditer(regex, target_text)] 18 | if len(positions) == 1: 19 | f.write('(0x%X, %r),\n' % (0x7100000000 + positions[0], name)) 20 | f.write('''] 21 | 22 | for addr, sym in syms: 23 | oldname = Name(addr) 24 | if oldname.startswith('sub_'): 25 | MakeName(addr, sym) 26 | MakeComm(addr, 'name from regex match') 27 | elif oldname.startswith('loc_'): 28 | MakeName(addr, sym) 29 | MakeComm(addr, 'name from regex match') 30 | print '%X %s %s' % (addr, oldname, sym) 31 | elif oldname != sym: 32 | print '%X %s %s' % (addr, oldname, sym) 33 | ''') 34 | 35 | 36 | if __name__ == '__main__': 37 | if len(sys.argv) < 2: 38 | print 'usage: applypattern.py pattern.txt [nxo files...]' 39 | print 'writes output to input filename + "-sdk-syms.py"' 40 | for filename in sys.argv[2:]: 41 | main(sys.argv[1], filename) 42 | -------------------------------------------------------------------------------- /binutils/getinfo.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import struct 3 | import re 4 | from nxo64 import load_nxo 5 | 6 | def main(filenames): 7 | for filename in filenames: 8 | print 'File:', filename 9 | with open(filename, 'rb') as li: 10 | f = load_nxo(li) 11 | 12 | path = None 13 | for off, end, name, class_ in f.sections: 14 | if name == '.rodata' and end-off < 0x1000 and end-off > 8: 15 | id_ = f.binfile.read_from(end-off, off) 16 | length = struct.unpack_from('