#!/usr/bin/env python3 """Reconstruct kernel-only PE modules from the Zune HD NK.bin image. The main ``disassemble_zune_hd.py`` pipeline rebuilds modules from the ``EXT.bin`` ROM assets. Some high-value modules live only in the kernel image (``NK.bin``) and are not in the ROMHDR module table of ``EXT.bin``: ``zcstfs.dll`` (the ZCSTFS volume driver), ``keyvault.dll`` (the key/keypack driver), ``zcblock.dll``, ``zpartstream.dll`` and ``DwXfer.dll``. This script flattens ``NK.bin`` (B000FF), locates the named module entries in the kernel module table, reconstructs an importable ARM32 PE for each, and writes it to the external corpus ``modules/`` directory. Output stays in the git-ignored corpus; never commit it. Usage: python3 scripts/reconstruct_nk_modules.py python3 scripts/reconstruct_nk_modules.py --modules zcstfs.dll,keyvault.dll python3 scripts/reconstruct_nk_modules.py --list """ import argparse import os import struct import sys BASE_DIR = os.environ.get( "ZUNE_HD_DISASSEMBLY_DIR", os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "zune-hd-disassembly")), ) NK_PATH = os.path.join(BASE_DIR, "firmware", "NK.bin") MODULES_DIR = os.path.join(BASE_DIR, "modules") DEFAULT_MODULES = [ "zcstfs.dll", "keyvault.dll", "zcblock.dll", "zpartstream.dll", "DwXfer.dll", ] HASH = 0x7FFFFFFF def flatten_nk(path): """Return (image_start, raw) for a B000FF NK image.""" with open(path, "rb") as f: if f.read(7) != b"B000FF\n": raise ValueError("NK.bin is not a B000FF image") image_start, image_length = struct.unpack(" 1 else 0 optional_fixed = struct.pack( " 1 else 0, vbase, 0x1000, 0x200, subsysmaj, subsysmin, 0, 0, subsysmaj, subsysmin, 0, vsize, 0x400, 0, subsys, 0, stackmax, 0x1000, 0x100000, 0x1000, 0, 16, ) optional = optional_fixed + b"".join(struct.pack(" {destination}") if not args.list: print(f"[*] Reconstructed {written} kernel module(s) into the external corpus.") return 0 if __name__ == "__main__": raise SystemExit(main())