diff --git a/py/lib/FsTools.py b/py/lib/FsTools.py index d67ac5c..0f9f334 100644 --- a/py/lib/FsTools.py +++ b/py/lib/FsTools.py @@ -53,15 +53,6 @@ def get_data_from_cnmt(nca): length_of_emeta = cnmt.readInt32() content_type_cnmt = cnmt._path[:-22] - # if content_type_cnmt != 'AddOnContent': - # RSV = min_sversion - # RSV = sq_tools.getFWRangeRSV(int(RSV)) - # RGV = 0 - # else: - # RSV_rq_min=sq_tools.getMinRSV(keygeneration, 0) - # RSV=sq_tools.getFWRangeRSV(int(RSV_rq_min)) - # RGV = min_sversion - cnmt.rewind() cnmt.seek(0x20 + offset) @@ -70,7 +61,7 @@ def get_data_from_cnmt(nca): cryptoHex = keygeneration.to_bytes(8, 'big').hex().upper() data['rightsId'] = data['title_id'] + cryptoHex - data['hasHtmlManual'] = hasHtmlManual=False + data['hasHtmlManual'] = False data['installedSize'] = int(nca.header.size) data['deltaSize'] = 0 diff --git a/py/ns_extract_meta.py b/py/ns_extract_meta.py new file mode 100644 index 0000000..a244548 --- /dev/null +++ b/py/ns_extract_meta.py @@ -0,0 +1,74 @@ +from binascii import hexlify as hx, unhexlify as uhx + +import os +import sys + +from pathlib import Path +from Fs import Pfs0, Nca, Type, factory +from lib import FsTools + +# set app path +appPath = Path(sys.argv[0]) +while not appPath.is_dir(): + appPath = appPath.parents[0] +appPath = os.path.abspath(appPath) +print(f'[:INFO:] App Path: {appPath}') + +# set logs path +# logs_dir = os.path.abspath(os.path.join(appPath, '..', 'logs')) +# print(f'[:INFO:] Logs Path: {logs_dir}') + +import argparse +parser = argparse.ArgumentParser(formatter_class = argparse.ArgumentDefaultsHelpFormatter) +parser.add_argument('-i', '--input', help = 'input file') +args = parser.parse_args() + +INCP_PATH = args.input + +def send_hook(message_content): + try: + print(message_content) + except: + pass + +def scan_file(): + ipath = os.path.abspath(INCP_PATH) + if not os.path.isfile(ipath): + return + if not ipath.lower().endswith(('.xci', '.xcz', '.nsp', '.nsz')): + return + + container = factory(Path(ipath).resolve()) + container.open(ipath, 'rb') + if ipath.lower().endswith(('.xci', '.xcz')): + container = container.hfs0['secure'] + try: + for nspf in container: + if isinstance(nspf, Nca.Nca) and nspf.header.contentType == Type.Content.META: + for section in nspf: + if isinstance(section, Pfs0.Pfs0): + Cnmt = section.getCnmt() + + titleType = FsTools.parse_cnmt_type_n(hx(Cnmt.titleType.to_bytes(byteorder = 'big'))) + + print(f':: CNMT: {Cnmt._path}\n') + print(f'Title ID: {Cnmt.titleId.upper()}') + print(f'Version: {Cnmt.version}') + print(f'Title Type: {titleType}') + + for entry in Cnmt.contentEntries: + entryType = FsTools.get_metacontent_type(hx(entry.type.to_bytes(byteorder = 'big'))) + print(f'\n:{Cnmt.titleId} - Content.{entryType}') + print(f'> NCA ID: {entry.ncaId}') + print(f'> HASH: {entry.hash.hex()}') + + finally: + container.close() + + +if __name__ == "__main__": + if INCP_PATH: + scan_file() + else: + parser.print_help() + print()