SuperAPI AI Directory

re-console

General & other

View repository

Updated 10-15 21:34

About this skill

Modern console and retro platform reverse engineering (Switch NSO/NPDM, PS4/PS5 ORBIS, retro ROM/saves)

When to use / when not to use

  • Use: Switch program container parsing—NSO0 (code segment structure), NPDM (program metadata/permission surface), ExeFS/NCA partition boundary identification; decrypt NCA/NAX0 partitions and extract code segments when a legal keyset is available
  • Use: PS4/PS5 ORBIS main program (eboot.bin)—encryption boundary identification, ELF structure parsing of legally decrypted samples (PT_SCE_* program headers), SDK version and imported library fingerprints
  • Use: Xbox-family containers (XBE/XEX2) parsing and entry point location
  • Use: retro platform ROMs—NES (iNES/NES 2.0), GB/GBC, GBA, PSX ROM header parsing, cartridge formats, save files, cheat code analysis
  • Use: SDK library fingerprints (Switch NX SDK, ORBIS SDK, Xbox XDK, devkit toolchains) to assist with version identification and function matching
  • Don't use: PC games (Unity/Unreal, Cheat Engine memory modification) go to [[re-game]]
  • Don't use: mobile games ([[re-mobile]])
  • Don't use: general decompilation/debugging foundation after extracting code segments from containers (hand over to [[re-binary-core]], use Ghidra/IDA as usual)
  • Don't use: console modification/custom firmware flashing, console cracking, retail media decryption and content protection circumvention, acquisition and distribution of pirated/unauthorized ROMs—this skill only provides file formats and analysis methods, and samples must come from legal channels (backups of one's own devices, devkit/official SDK content, authorized materials); cartridge dumps are limited to analysis purposes for one's own cartridges, and regulations on personal backups vary by jurisdiction and must be confirmed by the user
  • Don't use: simply using ready-made save editors/cheat tools (this skill is an analysis path and does not provide ready-made tools)

Tool preparation

Verify all tools before use. Static analysis may be done without a sandbox; anything involving dynamic execution (running ROMs in an emulator, running decrypted samples) defaults to sandbox + network isolation ([[re-analyze/platform-tips]] highest principle).

Decompiler (choose either Ghidra / IDA)

  • Ghidra (free, official release package, requires JDK; some distribution repositories have apt install ghidra / pacman -S ghidra):
    • Linux: official release package; macOS: brew install --cask ghidra; Windows: official zip
    • Verify: analyzeHeadless -help(headless mode) or GUI import of the target file
    • Architecture coverage: Switch is aarch64, PS4/PS5 are x86-64, PSX is MIPS R3000 (methodology see [[re-mips]]), GBA is ARM7TDMI (Thumb handling see [[re-arm]]), NES is 6502-family; GB/GBC use Sharp SM83: encoding is close to 8080/Z80 but it is not a Z80-compatible variant (no IX/IY, no DD/FD/ED prefixes, no IN/OUT, has its own STOP/LDH and HL auto-increment/decrement); Ghidra core has no SM83, install SM83 SLEIGH + Game Boy loader such as GhidraBoy; the Z80 module may only be used for manual comparison and must not be used as the processor language for the ROM (see pitfall 6)
  • IDA: commercial version has complete architecture modules; the range of architecture support in the Freeware version is subject to the official page
  • Set the base address by platform when importing a ROM: GBA 0x08000000 (cartridge mapping area), PSX according to the EXE header 0x18 field (typically 0x80010000, RAM base address 0x80000000); NES/GB use a fixed address space + bank switching, requiring loader support for mapper/bank (see pitfall 6)

hactool — Switch container parsing (NSO0/NPDM/NCA)

  • Source and installation: GitHub SciresM/hactool releases — 1.4.0 (the final version released in 2018, supporting NSO0/NPDM parsing and decompression, with NPDM exportable as JSON) provides a Windows package (hactool-1.4.0-win.zip); Linux/macOS build from source (config.mk.template copy as config.mk then make, depends on zlib/openssl)
  • Verify: hactool --help displays the full options
  • Note: the hactoolnet repository commonly seen in old tutorials/articles (the CLI bundled with the LibHac project) is offline — verified 2026-08 GitHub 404 (Thealexbarney/LibHac no longer exists); for materials referencing hactoolnet, verify link availability first, and fill functional gaps with hactool + self-written parsing scripts (pyelftools)
  • Keys: -k keys.txt specify a keyset (each line key_name = HEX); by default reads $HOME/.switch/prod.keys(-d , reads dev.keys). Decrypting NCA/NAX0 requires the corresponding keyset; without keys, only structural-level analysis is possible

readelf / pyelftools — ORBIS and general ELF parsing

  • Linux: bundled with binutils (apt install binutils , etc.); macOS: brew install binutils or an LLVM-based readelf; Windows: within WSL
  • pyelftools: pip install pyelftools(the script iterates program headers/section table)
  • Verify: readelf --version、python3 -c "import elftools; print('ok')"
  • PS4/PS5 ORBIS ELF is a valid ELF64 with an SCE extended program header — readelf can parse it directly (-l to see PT_SCE_* segments,-S to see the section table); not bound to dedicated ORBIS viewers (scene community tools vary in maintenance; verify before use)

Emulator debuggers (dynamic analysis for retro platforms)

  • mGBA (GB/GBC/GBA, built-in debugger + GDB stub):
    • Debian/Ubuntu: apt install mgba-qt(Qt frontend, universe) or mgba-sdl; Fedora: the official repository only has the libretro core dnf install libretro-mgba(no debugger); for mGBA with a debugger use Flatpak or a third-party COPR (e.g. dnf copr enable archjun/mgba then dnf install mgba, evaluate third-party sources yourself); Arch: pacman -S mgba;macOS: brew install mgba; Windows: installer from the official site mgba.io
    • Verify: mgba --version
    • Debugging: after loading a .gba/.elf in the GUI, Tools → Start GDB Server (or command line -g/--gdb), listening on localhost:2345 by default; on the GDB side target remote localhost:2345, set breakpoints with a symbol-bearing .elf (mGBA's symbols come from the .elf, not the .gba); the command-line -d debugger is a feature of the SDL/GTK build; the Qt build uses the GDB stub
  • FCEUX (NES, built-in debugger/hex editor/RAM search):
    • Debian/Ubuntu: apt install fceux;Fedora/Arch: dnf install fceux / pacman -S fceux; Windows: official site fceux.com
    • Verify: fceux --version
  • no$psx (PSX debugger, free Windows version): download from the official page problemkaputt.de/psx.htm (no distro package, Windows only), with built-in disassembly/breakpoints/memory and VRAM viewers; no equivalent version for Linux/macOS, for PSX dynamic debugging use QEMU-based approaches (the qemu-system idea in [[re-fw-emulate]] + gdb) or purely static
  • Other platforms as needed: for SNES debuggers, Mesen (official Windows download) and the like can be used; rely on official channels

Cartridge readers (buying guide, generalized)

  • Approach: choose the corresponding interface by platform — NES 72-pin, SNES 62-pin, GB/GBC 32-pin, GBA 32-pin; supporting many platforms at once is usually a combination of a mainboard plus adapter boards
  • Purchasing points: prioritize open-source firmware (firmware is auditable and can be compiled yourself); confirm support for the target model and cartridge variants (special mappers, accelerator chips, CGB dual voltage); support double-dump verification (read the same cartridge twice and compare, cross-validate against a known hash database); power supply and level matching (GB family 3V, NES 5V, wrong insertion may damage the cartridge); read-only dumping is the analysis baseline, and write/flashing capability determines the use case according to authorization boundaries
  • Verification: cross-validate the dumped data against emulator runnability on the same platform / known hashes

binwalk — embedded file scanning

  • For installation channels and version discrimination (v3 mainline / v2 legacy), see the binwalk/unblob installation matrix in [[re-fw-extract]]; verification: binwalk --version

Procedure

Execute in order and archive the result of each step (hashes, offset tables, sha256 of parsing outputs, [[re-triage]] evidence preservation); dynamic execution defaults to sandboxing.

  1. Container identification(determine format first, then toolchain):

    file target.bin
    xxd -l 64 target.bin
    binwalk target.bin    # 内嵌/拼接文件扫描
    
    • Switch: NSO0(NSO program),META(NPDM file header),NCA3(NCA container),NAX0(SD encrypted partition),PFS0(NSP plaintext package container); in ExeFS, main(NSO) and main.npdm coexist
    • PS4/PS5: plaintext ELF begins with \x7fELF (ORBIS ELF with PT_SCE_* program headers); the eboot.bin of a retail dump is an encrypted container (no ELF magic, high entropy), and the encryption boundary is here — this skill only analyzes decrypted/unencrypted samples that have been legally obtained
    • Xbox: XBEH(original Xbox XBE),XEX2(Xbox 360, 24-byte big-endian header, 0x8 points to embedded PE data, optional header table); Xbox One/Series are Microsoft-family variant containers (XVD/ERA system), so probe by actual sample before parsing
    • Retro: NES 4E 45 53 1A("NES\x1A"); GBA has no magic number (0x0 is an ARM branch instruction, and from 0x4 there is a 156-byte Nintendo logo); GB has no magic number (from 0x104 a 48-byte logo is the criterion plus 0x147 cartridge type); PSX discs are ISO9660 (CD001 volume descriptor), and the EXE pointed to by the main program SYSTEM.CNF begins with PS-X EXE ; raw .bin images have 2352-byte sectors (not 2048), so convert sector offsets by 2352 when locating the volume descriptor
    • Save data: GBA .sav has no unified magic number (identify by capacity/content structure); PSX memory card dumps have the MC signature at 0x0 and 0x1F80
    • When the determination is unclear, first go through the routine initial survey in [[re-triage]]
  2. Container parsing(partition/encryption boundary discrimination):

    • Switch NSO (hactool automatically identifies NSO0):
      hactool -i main.nso                          # 段信息/压缩标志/ModuleId
      hactool --uncompressed=main_u.nso main.nso   # 压缩段解压(flags 压缩位置位时)
      
      Key points of the NSO0 header: 0x0 magic NSO0; 0x10/0x20/0x30 three segment headers (each 0xC bytes: FileOffset/MemoryOffset/Size, corresponding in order to .text/.rodata/.data); 0x3C BSS size; from 0x40, a 0x20-byte ModuleId (= the ELF build-id digest); 0x60/0x64/0x68 the compressed sizes of the three segments; from 0x100 onward is segment data (compressed segments use LZ4; when flags bit7 is set in firmware 22.0.0+, it is the ZBIC/zstd variant, nxdumptool NsoFlags_UseZbicCompression=BIT(7))
    • Switch NPDM:
      hactool -t npdm --json=main.json main.npdm   # 导出权限 JSON
      
      NPDM key points: 0x0 META Header (0x80 bytes); 0xE main thread priority, 0xF main thread core number, 0x1C main thread stack size (0x1000-aligned); 0x70/0x74 ACI0 offset/size, 0x78/0x7C ACID offset/size; at ACID area 0x200 ACID magic number (preceded by RSA-2048 signature and public key), at ACI0 area 0x0 ACI0 magic number; ACI0 contains ProgramId, filesystem/service access control, kernel capability—this is where privilege surface analysis looks
    • Switch NCA (encryption boundary): the NCA header contains a section table, and the body is encrypted per section (AES-XTS); with a valid keyset, hactool -t nca -k keys.txt --exefsdir=exefs/ --romfsdir=romfs/ file.nca extract ExeFS (containing NSO/NPDM) and RomFS; NAX0 additionally requires --sdseed and --sdpath parameters. Without a keyset, perform only structural-level parsing, with no decryption bypass
    • ORBIS ELF:readelf -l eboot look at program headers—PT_SCE_DYNLIBDATA (0x61000000), PT_SCE_PROCESS_PARAM (0x61000001), PT_SCE_MODULE_PARAM (0x61000002), PT_SCE_RELRO (0x61000010);readelf -S look at the section table (.comment/.sceNote, etc.); the export table is within PT_SCE_DYNLIBDATA
    • XEX2: iterate the optional header array (each entry is two items, type+data, and the data size is determined by the low 8 bits of type, ID&0xFF)—the execution info optional header contains the entry point, and the import library optional header contains library names and ordinals; the code section location is inferred from the PE data offset at 0x8; XEX header fields are big-endian, and the embedded PE part is parsed according to PE rules ([[re-format-pe]])
    • Archive each step's output: the parsed segment files + magic number/offset/size records
  3. Code section extraction into generic decompilation:

    • NSO: in Ghidra, create .text/.rodata/.data as memory blocks according to the segment header MemoryOffset (unify the base address first, then auto-analyze), fill the BSS zero region; select aarch64 for import
    • ORBIS: decrypt the ELF and import it directly into Ghidra (x86-64), ET_EXEC by the fixed base address in the header, ET_DYN by the loading convention; first use nm/readelf -s to find unstripped symbols; the entry point is often near the module parameter segment/entry section
    • PSX: extract the EXE's text segment (file offset starting at 0x800, length taken from the 0x1C field of the header), import at the load address from the 0x18 field of the header, MIPS R3000 little-endian (for delay slots and $gp methodology see [[re-mips]])
    • GBA: import the entire ROM at 0x08000000, ARM7TDMI mixed Thumb (see [[re-arm]]); GB/NES: when there is no decompiler-native CPU, use an approximate instruction set + manual bank expansion (see pitfall 6), or a dedicated loader plugin
    • Archive: first strings find the product code/checksum signature (at PSX slot header 0x0A BXXXX-12345 product code-like string)
  4. SDK library fingerprint(version identification → function matching acceleration):

    • Switch: comparing the ModuleId at NSO header 0x40 against switchbrew's SDK version table/community database yields the SDK version (the mapping table evolves with firmware, so verify timeliness first); within the binary, NintendoSDK the version string is subject to actual sample measurements
    • ORBIS: the PT_SCE_MODULE_PARAM segment contains an sdk_version field (uint32, e.g. 0x08030001 corresponds to the 8.03 level) and the module parameter magic number 0x3C13F4BF;.comment/.sceNote the section often contains an SDK version string—sdk_version is the compiling SDK version, not equal to the running firmware version
    • Xbox: the XEX2 import library optional header lists system DLL names and ordinals (corresponding to the XDK version range); the library version array of XBE is the same
    • Retro: Toolchain fingerprinting—GBA commercial ROMs are mostly ARM7TDMI + vendor compilers (library function forms/feature strings); homebrew commonly has devkit-family feature strings; PSX commercial discs commonly have vendor SDK library function forms; compare against known library signature tables to speed up function identification
    • Output: SDK/toolchain version + library function signature table, for step 5 and subsequent decompilation naming
  5. Patch diffing(linked with [[re-variant]]):

    • Multi-version comparison: diff the ROM or main program of the same game across different regions/updates—locate functional change points, version-gating logic (region checks, SDK version branches)
    • Method: after decompression/unpacking and alignment, diff or follow the function matching process in [[re-variant]]; when version differences are concentrated in SDK upgrade areas and newly added features, first layer by SDK fingerprint then diff layer by layer
    • Output: list of difference points + corresponding analysis of changed functions
  6. Retro: Save and Cheat code analysis(memory address + value patterns):

    • Save structure parsing:
      • PSX memory card: 128KB (0x20000) = 16 blocks × 8KB, block 0 is the header/directory block;MC signature at 0x0 and 0x1F80; each block is 64 frames × 128 bytes; slot header is 128 bytes—0x00 slot type (0xA0 empty/0x51 first block/0x52 middle/0x53 last block), 0x04 save size, 0x08 next block pointer (multi-block saves are a linked list), 0x0A product code name, 0x7F XOR checksum; icon 16×16 4bpp up to 3 frames (the 2nd byte of the data, 0x11/0x12/0x13, indicates the frame count)
      • GB/GBA:.sav size is determined by cartridge type—GB depends on the 0x149 field (0x02=8KB, 0x03=32KB common); GBA commonly SRAM 32KB, Flash 64/128KB, EEPROM 512B class; there is no universal magic number, identify by capacity + content features (checksum, ASCII text)
      • Analysis purpose: recover the save checksum algorithm, field semantics (numeric values/items/progress bitmaps)
    • Cheat code analysis (methodology, not finished tools):
      • Principle: Cheat code = encoding of 「memory address + value/write pattern」, e.g. GBA CodeBreaker type AAAAAAAA 0000(8-bit address + 4-bit value)—GB/GBC use the GameShark 8-bit format, do not conflate the names; NES-family 6-character encoding (address/value + key transformation); first decode the address and value according to the encoding rules
      • Recovery path: emulator debugger (mGBA/FCEUX) memory view/search to locate in-game values (coins, lives) → record the address (GBA: EWRAM from 0x02000000, IWRAM from 0x03000000; GB: WRAM 0xC000-0xDFFF) → debugger breakpoint to find the code that writes that address → restore that function and data flow in the decompiler → derive the semantics of 「some address stores some value」 and all reference points
      • Output: address semantics table (address → meaning/type/range), for validation, decompilation annotation, or behavior research; analysis only, no finished Cheat tools provided
    • Sandbox: dynamic verification inside an emulator defaults to sandboxed + network isolation

Cross-domain combination

  • [[re-binary-core]]: the general initial survey/decompilation/debugging foundation after code section extraction ([[re-ghidra]], [[re-ida]], [[re-gdb]] are used as usual)
  • [[re-game]]: sister skill for reverse engineering PC-side Unity/Unreal games; the 「memory address + value pattern」 game logic analysis method is interoperable
  • [[re-cracking]]: license/activation validation analysis; the compliance boundary for console scenarios is the same as this skill
  • [[re-variant]]: multi-version/multi-region ROM and main program diff
  • [[re-mips]]: PSX's MIPS R3000 instruction set and methodology (delay slots, $gp)
  • [[re-arm]]: GBA ARM7TDMI Thumb/ARM handling
  • [[re-fw-extract]] / [[re-fw-rootfs]]: Extraction of embedded files and filesystems within cartridge/disc images (binwalk prerequisite)
  • [[re-patching]]: Landing ROM/program byte-level modifications (note header checksum recalculation, see pitfall 4)
  • [[re-sandbox]]: Mandatory isolation for emulators/dynamic execution ([[re-analyze/platform-tips]] default sandbox principle)
  • [[re-triage]]: Pre-assessment ahead of container identification
  • [[re-format-pe]]: Partial parsing of PE embedded within XEX2

Common Pitfalls and Traps

  • Treating encrypted containers as plaintext: Symptom—Switch NCA/NAX0 or PS4/PS5 retail eboot.bin is fed directly into a decompiler, yielding all high-entropy garbage or hallucinated disassembly; Cause—the content is encrypted in the NCA body (AES-XTS) and the ORBIS container layer, and the NSO0/ELF magic number is only visible after decryption; Countermeasure—first perform encryption boundary identification (missing magic + high entropy = ciphertext), and with a legitimate keyset use container tools to decrypt and extract (hactool to decrypt NCA/NAX0); without keys, only do structure-level work; this skill's scope covers legitimately obtained samples and does not perform decryption bypass
  • SDK fingerprint misidentification: Symptom—treating the compilation SDK version as the runtime firmware version, or mismatching a ModuleId to another SDK based on an old mapping table, causing the library function table to not match; Cause—the ModuleId↔SDK mapping table drifts as firmware evolves, and ORBIS's sdk_version field is the compile-time version; Countermeasure—annotate fingerprint conclusions as "compilation SDK version", first verify the timeliness of the mapping table (use the currently maintained page as authoritative), and cross-validate with the actual version string inside the binary before drawing conclusions
  • Separation of metadata header and body: Symptom—only NSO is parsed or only NPDM is looked at, so the permission surface/entry information/code are not correlated, leaving gaps in the analysis; Cause—NPDM (permission/entry metadata) is an independent file coexisting with NSO, the NCA partition table is in the header while partition data is scattered by offset, and XEX2's header fields are stored separately from the PE data; Countermeasure—archive the container artifacts from the same batch (NPDM+NSO, NCA partitions, XEX header+PE segments) as a whole, first listing the inventory and then parsing each one
  • ROM header checksum and patch invalidation: Symptom—after modifying a ROM (patch/translation/modification), the emulator or real hardware refuses to boot; Cause—the GBA header 0xBD is a complement check of the byte-by-byte sum of 0xA0-0xBC (then subtract 0x19 and take 8 bits), so changing the title/game code requires recalculation; the GB header 0x14D checksum covers 0x134-0x14C; changing NES mapper bits does not affect booting but affects mapping correctness; Countermeasure—recalculate the checksum according to the algorithm after changing the header, and write checksum recalculation into the patch scheme steps
  • Behavioral differences between emulators and real hardware: Symptom—modifications that run on mGBA crash on real hardware, and FCEUX and Mesen behave differently for the same ROM's mapper; Cause—timing-sensitive code (GBA audio/interrupt timing), mapper implementation differences, emulator accuracy differences; Countermeasure—annotate conclusions as "verified in emulator environment", and when real-hardware-level conclusions are needed, use multiple emulators for cross-validation plus real hardware (card reader/flashcart) review; save write-back and power-off timing are especially unreliable on emulators
  • Misaligned disassembly when the decompiler lacks native CPU supportPhenomenon—the SM83 of the GB has no native module, and using Z80 to approximately disassemble produces nonexistent instructions (the same encoding diverges in meaning between SM83/Z80, such as 0x22/0xE8/0x10); details of the NES 6502 variant are treated as ordinary instructions; cause—SM83 and 8080/Z80 have similar encodings but SM83 is not a Z80-compatible variant, and an approximate instruction set is not equal to the target CPU; countermeasure—first identify the CPU (for GB look at the 0x104 logo/0x147 cartridge type, for NES look at the mapper in the flags), for GB use SM83 SLEIGH such as GhidraBoy plus a Game Boy loader, and when there is no native support manually annotate the limitations; approximate disassembly results must be corrected by actual testing in an emulator
  • Authorization boundaries: Modding/homebrew firmware, decryption of retail media, and unauthorized ROM acquisition and distribution are outside the scope of this skill; analysis samples must come from legitimate channels; cartridge dumps are limited to analysis use of one's own cartridges, and you must confirm the applicable rules in your jurisdiction yourself; the skill body only provides format parsing and analysis methods