Skip to content

Instantly share code, notes, and snippets.

@SciresM

SciresM/nso.py Secret

Last active June 27, 2020 02:34
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SciresM/62715cfb5d06648ee46bc4622d2725e5 to your computer and use it in GitHub Desktop.
Save SciresM/62715cfb5d06648ee46bc4622d2725e5 to your computer and use it in GitHub Desktop.
import struct
import lz4.block
import sys
import hashlib
import binascii
def main(argc, argv):
if (argc != 3):
print 'Usage: %s in.nso out.bin'
sys.exit(1)
try:
nso = file(argv[1], 'rb').read()
except:
print 'Error: failed to read %s!' % argv[1]
sys.exit(1)
try:
out = open(argv[2], 'wb')
except:
print 'Error: failed to open %s for writing!' % argv[2]
if nso[:4] != 'NSO0':
print 'Error: file provided is not an NSO!'
sys.exit(1)
decmp = lz4.block.decompress
toff, tloc, tsize = struct.unpack('<III', nso[0x10:0x1C])
roff, rloc, rsize = struct.unpack('<III', nso[0x20:0x2C])
doff, dloc, dsize = struct.unpack('<III', nso[0x30:0x3C])
thash, rhash, dhash = nso[0xA0:0xC0], nso[0xC0:0xE0], nso[0xE0:0x100]
print '.text: %08X-%08X' % (tloc, tloc+tsize)
print '.rodata: %08X-%08X' % (rloc, rloc+rsize)
print '.data: %08X-%08X' % (dloc, dloc+dsize)
text = decmp(nso[toff:roff], uncompressed_size=tsize)
ro = decmp(nso[roff:doff], uncompressed_size=rsize)
data = decmp(nso[doff:], uncompressed_size=dsize)
cthash = hashlib.sha256(text).digest()
crhash = hashlib.sha256(ro).digest()
cdhash = hashlib.sha256(data).digest()
if cthash != thash:
print 'Warning: .text SHA256 hash does not match! (%s != %s)' % (binascii.hexlify(cthash), binascii.hexlify(thash))
if crhash != rhash:
print 'Warning: .rodata SHA256 hash does not match! (%s != %s)' % (binascii.hexlify(crhash), binascii.hexlify(rhash))
if cdhash != dhash:
print 'Warning: .data SHA256 hash does not match! (%s != %s)' % (binascii.hexlify(cdhash), binascii.hexlify(dhash))
out.write(text)
out.seek(rloc)
out.write(ro)
out.seek(dloc)
out.write(data)
out.close()
if __name__=='__main__':
main(len(sys.argv), sys.argv)
@SocraticBliss
Copy link

In the rare case someone tries to use this for another file type, it currently creates a 0 byte file, may want to move the NSO check above the second try/catch block...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment