Skip to content

PS5 PackagePS5 parser misinterprets FIH layout and does not resolve CNT ENTRY_NAMES #5

Description

@ChayahLabs

Hi,

while independently validating PS5 PKG parsing, I found a reproducible issue in packages/package_ps5.py.

I tested the current PkgToolBox main parser against two independently produced physical PS5 debug PKG samples:

  1. A package generated with prospero-pub-cmd
  2. The public HomebrewTest package from SvenGDK/LibProsperoPKG

PkgToolBox main commit tested/current at report time:
e0b74a70da5414dc2ac4c6dda486adcb50e92325

Both physical samples independently confirm the same outer structure:

  • FIH magic: 0x7F464948
  • FIH size: 0x10000
  • PFS starts at 0x10000
  • embedded SC/CNT magic: 0x7F434E54
  • CNT entries: 13
  • SC entries: 6
  • ENTRY_NAMES: ID 0x0200
  • icon0.png: ID 0x1200
  • param.json: ID 0x2000
  • PlayGo metadata entries are present

The two builders use different NameTableOffset values/order, but both resolve the same filenames correctly when the CNT name table is used. This is useful confirmation that entry names are not positional.

Current PkgToolBox behaviour

PackagePS5 correctly recognizes the initial FIH signature, but the subsequent header interpretation does not match either validated physical sample.

Across both samples the current reader produced results such as:

  • content_id = 256
  • pkg_file_count = 256
  • FIH/PFS/SC/SI layout values reported as zero
  • package/PFS digests reported as zero
  • CNT not detected
  • ENTRY_NAMES not detected
  • param.json not detected
  • icon entries not detected
  • PlayGo metadata not detected

The reader exits normally, so this appears to be a parsing/layout issue rather than a crash.

Entry-name resolution

There also appears to be a second structural issue in __load_ps5_files().

The current implementation reads a possible filename from the entry's own data offset:

fp.seek(file["offset"])
fn = fp.read(256).split(b'\x00')[0]

On both independently built samples, entry names are instead stored in the CNT ENTRY_NAMES table and are resolved using the entry's NameTableOffset:

ENTRY_NAMES.DataOffset + Entry.NameTableOffset

Reading from Entry.DataOffset accesses entry payload data rather than the corresponding filename.

Expected behaviour

For a finalized PS5 FIH image, the parser should first interpret the FIH layout, locate the embedded SC/CNT region, parse the CNT entry table, locate entry 0x0200 (ENTRY_NAMES), and resolve each name through its NameTableOffset.

The two independently produced samples agree on these structural properties. Their payload sizes, data offsets, hashes, SI ZIP sizes, and name-table ordering vary, which appears to be valid builder/payload variation rather than a format mismatch.

Public reproducible reference sample:
SvenGDK/LibProsperoPKG -> src/HomebrewTest/UP9000-PPSA99099_00-PROSPERO00000000-A0100-V0100.pkg

I can provide the detailed field-by-field comparison results if useful.

Thanks for maintaining PkgToolBox.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions