PKG files
See also Discussion page
Firmware Packages
File Header
All values are in big endian format.
typedef struct { u32 0x00, 0x53434500// magic u32 0x04, 2 // version u16 0x08, 0 // sdk type? u16 0x0a, 3 // SCE header type; pkg u32 0x0c, 0 // meta offset u64 0x10, // size of sce_hdr + sizeof meta_hdr u64 0x18, 0x80 // + content_size_real }
Game Packages
All game packages are signed with the ECDSA signature. The public key for it can be found in download_plugin.prx or in nas_plugin.prx (this also applies to NPDRM SELFs). Usually game packages are signed with two signatures - one for the header and the other for the entry table.
Security
The security of .pkg consists in some hashes and signatures.
PS3: file SHA-1 + QA digest + ECDSA signature
PSP: PS3 securities + .ext header (3 PKG HMAC hashes of the headers)
PSVita: PSP securities + more Metadata (0xD-0x12) that embed some hashes of some files embedded into the .pkg
0x40 digest
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
cmac_hash | 0x0 | 0x10 | 48 0D 86 60 9F 26 8E 7F 4F B4 DA A4 33 1E 9A A1 | CMAC OMAC hash. PS3 gpkg_key used as key. |
npdrm_signature | 0x10 | 0x28 | PKG header NPDRM ECDSA (R_sig, S_sig) | |
sha1_hash | 0x38 | 0x8 | EC 61 40 39 A6 5B DC BD | last 8 bytes of sha1 hash |
typedef struct { // size is 0x40 u8 cmac_hash[0x10]; u8 npdrm_signature[0x28]; u8 sha1_hash[0x8]; } digest;
PKG HMAC algorithm
16 bytes hash using SHA-1 algorithm. Used in .ext header hashes.
static void pkg_hmac(const uint8_t *data, unsigned int len, uint8_t hmac[16]) {
SHA1_CTX ctx;
uint8_t sha1[20];
uint8_t buf[64];
// Do SHA-1 of the actual data
sha1_init(&ctx);
sha1_update(&ctx, data, len);
sha1_final(&ctx, sha1);
// Setup the intermediate buffer
memset(buf, 0, 64);
memcpy(&buf[0], &sha1[4], 8);
memcpy(&buf[8], &buf[0], 8);
memcpy(&buf[16], &sha1[12], 4);
buf[20] = sha1[16];
buf[21] = sha1[1];
buf[22] = sha1[2];
buf[23] = sha1[3];
memcpy(&buf[24], &buf[16], 8);
// Do SHA-1 of the intermediate buffer
sha1_init(&ctx);
sha1_update(&ctx, buf, 64);
sha1_final(&ctx, sha1);
// Returns 16 first bytes from the 20 bytes SHA-1
memcpy(hmac, sha1, 16);
}
File Header
Header consists of main header that points to metadata header. PSP and PSVita .pkg also have .ext header right after main header.
Example from a retail PS3 .pkg
- Example: Scott Pilgrim VS. The World Unlock .pkg file:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 7F 50 4B 47 80 00 00 01 00 00 00 C0 00 00 00 08 .PKGЂ......А.... 00000010 00 00 00 C0 00 00 00 02 00 00 00 00 00 00 17 C0 ...А...........А 00000020 00 00 00 00 00 00 01 80 00 00 00 00 00 00 15 E0 .......Ђ.......а 00000030 55 50 30 30 30 31 2D 4E 50 55 42 33 30 31 36 32 UP0001-NPUB30162 00000040 5F 30 30 2D 53 43 4F 54 54 50 49 4C 47 52 49 4D _00-SCOTTPILGRIM 00000050 30 30 30 32 00 00 00 00 00 00 00 00 00 00 00 00 0002............ 00000060 09 8B A2 CA 2D 30 30 1F 8B 5B 82 79 C6 70 35 F3 .‹ўК-00.‹[‚yЖp5у 00000070 D5 FA 15 9E 7F AC 82 70 BB 3E 0C EB 97 3D 30 11 Хъ.ћ.¬‚p»>.л—=0. 00000080 48 0D 86 60 9F 26 8E 7F 4F B4 DA A4 33 1E 9A A1 H.†`џ&Ћ.OґЪ¤3.љЎ 00000090 0C 85 45 95 A8 D4 A3 9B 62 44 68 C1 38 CE D7 63 .…E•ЁФЈ›bDhБ8ОЧc 000000A0 0D FF 0C C5 3A 77 C6 E6 E4 62 AD 05 F3 93 D0 7A .я.Е:wЖждb..у“Рz 000000B0 CC 02 B4 35 2B 70 47 D6 EC 61 40 39 A6 5B DC BD М.ґ5+pGЦмa@9¦[ЬЅ
PKG Main Header
Name | Offset | Size | Example | Remark |
---|---|---|---|---|
magic | 0x00 | 0x04 | 7F 50 4B 47 | '.PKG' |
pkg_revision | 0x04 | 0x02 | 80 00 | 80 00 for retail (finalized), 00 00 for debug (non finalized) |
pkg_type | 0x06 | 0x02 | 00 01 | 00 01 for PS3, 00 02 for PSP and PSVita |
pkg_metadata_offset | 0x08 | 0x04 | 00 00 00 C0 | usually 0xC0 for PS3, usually 0x280 for PSP and PSVita |
pkg_metadata_count | 0x0C | 0x04 | 00 00 00 08 | item count |
pkg_metadata_size | 0x10 | 0x04 | 00 00 00 C0 | usually 0xC0 for PSP and PS3, usually 0x160 for PSVita |
item_count | 0x14 | 0x04 | 00 00 00 02 | files and folders into the encrypted data |
total_size | 0x18 | 0x08 | 00 00 00 00 00 00 17 C0 | 0x17C0 - total pkg file size |
data_offset | 0x20 | 0x08 | 00 00 00 00 00 00 01 80 | 0x0180 - encrypted data offset |
data_size | 0x28 | 0x08 | 00 00 00 00 00 00 15 E0 | 0x15E0 - encrypted data size |
contentid | 0x30 | 0x24 | "UP0001-NPUB30162_00-SCOTTPILGRIM0002" | PKG Content ID |
padding | 0x54 | 0x0C | 00 00 00 00 00 00 00 00 00 00 00 00 | 0x0C bytes padding |
digest | 0x60 | 0x10 | 09 8B A2 CA 2D 30 30 1F 8B 5B 82 79 C6 70 35 F3 | sha1 from debug files and attributes together merged in one block |
pkg_data_riv | 0x70 | 0x10 | D5 FA 15 9E 7F AC 82 70 BB 3E 0C EB 97 3D 30 11 | aes-128-ctr iv. Used with gpkg_key to decrypt data. |
header_cmac_hash | 0x80 | 0x10 | 48 0D 86 60 9F 26 8E 7F 4F B4 DA A4 33 1E 9A A1 | CMAC OMAC hash from 0x00-0x7F. PS3 gpkg_key used as key. |
header_npdrm_signature | 0x90 | 0x28 | PKG header NPDRM ECDSA (R_sig, S_sig) | |
header_sha1_hash | 0xB8 | 0x08 | EC 61 40 39 A6 5B DC BD | last 8 bytes of sha1 hash of 0x00-0x7F |
All values are in big endian format.
typedef struct { u32 magic; u16 pkg_revision; u16 pkg_type; u32 pkg_metadata_offset; u32 pkg_metadata_count; u32 pkg_metadata_size; u32 item_count; u64 total_size; u64 data_offset; u64 data_size; u8 contentid[0x30]; u8 digest[0x10]; u8 pkg_data_riv[0x10]; u8 header_cmac_hash[0x10]; u8 header_npdrm_signature[0x28]; u8 header_sha1_hash[0x8]; } PKG_MAIN_HEADER;
PKG .ext Header
Not present on PS3 .pkg. Only present on PSP and PSVita .pkg. It was certainly a security improvement implemented in PSVita Pkg Installer.
HMAC pointed by this header are generated using PKG HMAC algorithm.
typedef struct{ u32 magic; // 0x7F657874 (".ext") u32 unknown_1; // always 1 u32 ext_header_size; // 0x40 u32 ext_data_size; // 0x180 u32 main_and_ext_headers_hmac_offset; // 0x100 u32 metadata_header_hmac_offset; // ex: 0x360, 0x390, 0x490 u64 tail_offset; // tail size seams to be always 0x1A0 u32 padding1; u32 pkg_key_id; // PSP = 0x1, PSVita = 0xC0000002, PSM = 0xC0000004 u32 full_header_hmac_offset; // ex: none (old pkg): 0, 0x930 u8 padding2[0x14]; } PKG_EXT_HEADER;
PKG Metadata
typedef struct { union{ u32 packet_identifier; // 0-0x12 u32 data_size; { data } } ... // u8 padding[variable]; u8 digest[0x40]; // PKG_files#0x40_digest } PKG_METADATA;
Identifier | PKG type | Category name | Possible size | Possible values |
---|---|---|---|---|
0x1 | All | DRM Type | 4 | 0/5/6/7/8/9/0xA/0xB/0xC (unknown), 0x1 (network), 0x2 (local), 0x3 (DRMfree no license), 0x4 (PSP), 0xD (DRMfree with license), 0xE (PSM) |
0x2 | All | ContentType | 4 | 00 00 00 07 |
0x3 | All | PackageType / PackageFlag / StorageType (PSVita) | 4 | |
0x4 | All | Package Size | 8 | 00 00 00 00 0E 77 40 00 |
0x5 | All | make_package_npdrm Revision (2 bytes) + Package Version (2 bytes) | 4 | 00 00 00 00 (0, 0.00), 09 56 00 00 (956, 0.00), 09 60 00 00 (960, 0.00), 10 09 00 00 (1009, 0.00), 10 12 00 00 (1012, 0.00), 12 03 00 00 (1203, 0.00), 12 12 00 00 (1212, 0.00), 12 73 01 01 (1273, 1.01), 15 00 01 00 (1500, 1.00), 16 81 01 00 (1681, 1.00),19 53 01 00 (1953, 1.00), 19 63 01 00 (1963, 01.00), 19 66 01 00 (1966, 01.00), 19 70 01 01 (1970, 1.01),19 72 01 02 (1972, 1.02), 99 00 00 00 (9900, 0.00), 99 01 00 00 (9901, 0.00) |
0x6 | PSP | Version + App Version / TitleID (on size 0xC) | 0xC | "NPEG00005\0\0\0" |
0x7 | PSP and PS3 | QA Digest (described as "This is a digest of packaged files and attributes.") | 0x18 | 00 00 00 00 00 00 00 00 B5 76 E1 D9 00 EE 9B BC 8E 24 17 91 5D BC 5A CB |
0x8 | All | unk (1 byte) + PS3/PSP/PSP2 System Version (3 bytes) + Package Version (2 bytes) + App Version (2 bytes) | 8 | 00 00 00 00 00 00 00 00, 00 00 00 00 01 00 01 00, 44 01 70 00 01 01 00 00, 81 01 90 00 01 00 01 00, 81 04 75 00 01 02 01 00 (4.7500, 1.02, 1.00) --> unk: 44 maybe PSP and 02/80/81 PS3 |
0x9 | All | unk | 8 | 00 00 00 00 00 00 00 00 / 00 00 00 00 00 24 00 00 / 00 00 00 10 00 00 00 00 / 00 00 00 01 00 00 00 00 / 00 00 00 00 00 02 00 00 / 00 00 00 04 00 00 00 00 / 00 00 00 00 00 04 00 00 |
0xA | PSP and PS3 | InstallDirectory | 0x28 | 8 zeroed bytes + directory: ........UCES01264_FANTASY............... |
0xB | All | unk seen in PSP cumulative patch | 0x8 | 00 00 00 00 00 00 00 01 |
0xC | All | unk | ||
0xD | PSVita | Item Entries+Names Info | 0x28 | Offset in encrypted data (4 bytes) + Size (4 bytes) + SHA-256 of decrypted data (32 bytes) 00 00 00 00 / 00 00 05 A0 / 18 8B B1 8A E5 E8 40 FD EE 71 E2 27 60 55 E6 39 06 94 5B 65 89 04 B2 88 61 DA BB A3 B2 55 C5 C1 |
0xE | PSVita | PARAM.SFO Info | 0x38 | 00 00 0C 10 00 00 05 0C 00 00 00 14 01 67 00 00 00 00 00 00 00 00 00 00 FC 3D 1E 32 FA F7 A6 11 90 46 A6 34 BE 98 9A 78 65 A8 92 25 3C 49 D7 69 73 53 32 E7 8E 06 1E 60 |
0xF | PSVita | unknown_data_info | 0x48 | 00 00 05 60 00 00 03 20 00 00 00 00 00 00 00 00 00 00 00 00 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 0F 26 BD 5C 2F 13 95 EB 16 E6 62 07 8D 9A E3 DC 0B AC 25 11 1C 19 39 B9 40 06 4E 82 AF 1E C3
00 00 06 10 00 00 03 20 00 00 01 F4 00 00 01 F7 00 00 00 00 01 01 01 01 A5 74 D5 71 00 03 00 01 00 00 00 00 00 00 00 00 79 52 B2 3F 78 3B 9D F4 C0 BB 26 C0 EC 14 1B 37 8B 9B 69 71 1C 22 C3 49 57 97 B6 DE 78 0A D0 00 |
0x10 | PSVita | Entirety Info | 0x38 | 00 00 0A 00 00 00 00 A0 D3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 4D AD EB 44 67 51 C1 2D 69 95 46 8C 82 A9 3D 74 AD F4 62 49 90 BD EE F0 75 97 A3 B6 5B 17 48
00 00 0A B0 00 00 01 60 FF D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D2 7F 9E EF 38 F7 61 6E C1 C5 CC B1 E1 83 12 0C 6F 38 4C 8C 22 84 8B A4 3B 7B 47 57 77 C9 F9 C9 |
0x11 | PSVita | PublishingTools version (4 Bytes) + PFSBuilder version (4 Bytes) + padding (0x20 Bytes) | 0x28 | 01 60 00 00 00 06 23 47 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
02 07 00 00 00 07 60 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0x12 | PSVita | self_info | 0x38 | 00 00 11 20 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CF 74 D5 30 04 99 F0 57 E8 65 20 5C 3D 71 12 36 F1 E4 EF BC 98 EA 52 F1 F0 60 E8 7C 8A 53 B8 A4 |
ContentType
content type | type name | install path (on ps3) | notes |
---|---|---|---|
0x1 | ? | /dev_hdd0/game/ | Found in UP0700-NPUJ00213_00-0000000000000002 (so old that it doesn't embed make_package_npdrm revision) |
0x2 | |||
0x3 | |||
0x4 | GameData (also patches) | /dev_hdd0/game/ | |
0x5 | GameExec | /dev_hdd0/game/ | |
0x6 | PS1emu | /dev_hdd0/game/ | |
0x7 | PSP & PCEngine | /dev_hdd0/game/ | |
0x8 | |||
0x9 | Theme | /dev_hdd0/theme | |
0xA | Widget | /dev_hdd0/widget | |
0xB | License | /dev_hdd0/home/<current user>/exdata | |
0xC | VSHModule | /dev_hdd0/vsh/modules/ | |
0xD | PSN Avatar | /dev_hdd0/home/<current user>/psn_avatar | |
0xE | PSPgo | /dev_hdd0/game/ | Displayed as Unknown Album: Corrupted Data |
0xF | minis | /dev_hdd0/game/ | |
0x10 | NEOGEO | /dev_hdd0/game/ | |
0x11 | VMC | /dev_hdd0/tmp/vmc/ | |
0x12 | ?PS2Classic? Seen on PS2 classic | /dev_hdd0/game/ | |
0x13 | |||
0x14 | Seen on PSP remastered | /dev_hdd0/game/ | |
0x15 | PSP2GD (PSVita Game Data) | ||
0x16 | PSP2AC (PSVita Additional Content) | ||
0x17 | PSP2LA (PSVita LiveArea) | ||
0x18 | ?PSM? (PSVita PSM) | PlayStation Mobile | |
0x19 | WT (Web TV?) | /dev_hdd0/game/ | |
0x1D | ?PSM? (PSVita PSM) | ||
0x1F | PSP2Theme (PSVita Theme) |
PackageType
Identifier | type name | usage | notes |
---|---|---|---|
4th byte, bit: xxx1 xxxx, ex: 00 00 00 1E (+CumulativePatch), 00 00 20 1E (+VC-MC+CumulativePatch) | Patch | for PSP game updates, to use with CumulativePatch, IncrementalPatch, HybridPatch | |
ex: 00 00 08 5A (+RenameDirectory) | DiscGamePatch | for PS3 BD games | |
4th byte, bit: xxx1 xxxx, ex: 00 00 00 5E (+Finalized+RenameDirectory) | HDDGamePatch | for PS3 HDD games (NPDRM) | |
unk | NoEBOOTBIN | ||
4th byte, bit: xxxx 1x1x, ex: 00 00 00 4A (+RenameDirectory) | Demo | ||
4th byte, bit: xxxx 11xx, ex: 00 00 00 0C | Key | ||
ex: 00 00 30 1E (+VC-MC+CumulativePatch+Patch) | Upgradable |
To class in PackageType or PackageFlag : DiscBinded
PackageFlag
Identifier | type name | usage | notes |
---|---|---|---|
ex: 00 00 00 00 | NO FLAGS | yes it exists, it was found in IP9100-NPIA00001_00-PS2HDDSYSDAT0001 that was builded with revision 960 (very old) !!!
or even UP0700-NPUJ00213_00-0000000000000002 (so old that it doesn't embed make_package_npdrm revision) | |
4rd byte, bit: x1xx xxxx, ex: 00 00 00 4E, 00 00 00 5E | RenameDirectory | ||
when RenameDirectory flag is not set (default), ex: 00 00 00 0E | NoRenameDirectory | ||
4rd byte, bit: xxxx x11x, ex: 00 00 00 0E, 00 00 00 1E, 00 00 00 4E, 00 00 00 5E, warning: don't mistake with the finalized flag in main header | Finalized | PS1 and PSP games have not this flag: 00 00 02 0C, PS3 game that has not this flag : 00 00 00 08 | |
00 00 00 08 | NON Finalized flaged PS3 package (DLC) | ||
ex: 00 00 02 0C, 00 00 02 1C (+Patch) | NON Finalized flaged package (all PS1 and PSP packages) | ||
ex: 00 00 02 4E (+RenameDirectory) | NON Finalized flaged minis package | ||
ex: 00 00 04 8C | Theme (.p3t.edat) / License package (.edat) | -> ????noEBOOOT?????? | |
ex: 00 00 04 0C | VSH Module package | ||
ex: 00 00 20 1E, 00 00 00 1E | CumulativePatch | Embeds the previous patches | to use with Patch StorageType |
unk | IncrementalPatch | Requires the previous patches to be installed first | to use with Patch StorageType |
unk | HybridPatch | to use with Patch StorageType | |
3rd byte, bit: x1xx xxxx, ex: 00 00 40 0E | NonGame | used for most of PSVita NPDRM apps |
StorageType
Seams to be PSVita only.
Identifier | type name | usage | notes |
---|---|---|---|
3rd byte, bit:xx1x xxxx, ex: 00 00 20 0E, 00 00 20 1E | VC-MC |
[VC-MC] This application is distributed by PS Vita card(VC). This application may be distributed by network and installed onto memory card(MC). [In case of VC distribution] The VC does NOT have rewritable(R/W) area, and Patches/Additional Contents/Save Data are stored on MC. MC is REQUIRED to run this application. |
There exists 2 variants : 2GB VC and 4GB VC (it is still unknown how to recognize this difference) |
default (when VC-MC flag is not set), ex: 00 00 00 0E, 00 00 00 1E | VC-VC | [No VC/MC-MC]
This application is NOT distributed by PS Vita card(VC). This application is distributed by network and installed onto memory card(MC). |
sfo_info
typedef struct { // size is 0x38 u32 param_offset; u16 param_size; u32 unk_int; // ex: 0x2, 0x14, 0x4, 0x9 u32 PSP2_DISP_VER; // or may be PSP2_SYSTEM_VER u8 unk[0x8]; u8 param_digest[0x20]; // SHA256 of param_data. Called ParamDigest: This is sha256 digest of param.sfo. } sfo_info;
unknown_data_info
typedef struct { // size is 0x48 u32 unknown_data_offset; u16 unknown_data_size; // ex: 0x320 u8 unk[0x20]; u8 unknown_data_sha256[0x20]; } unknown_data_info;
entirety_info
typedef struct { // size is 0x38 u32 entirety_data_offset; // located just before SFO u32 entirety_data_size; // ex: 0xA0, C0, 0x100, 0x120, 0x160 u16 flags; // ex: EE 00, FE 10, FE 78, FE F8, FF 10, FF 90, FF D0, flags indicating which digests it embeds u16 unk; // always 00 00 u32 unk2_int; // ex: 1, 0 u8 unk3[0x8]; u8 entirety_digest[0x20]; // SHA256 of entirety_data. Called EntiretyDigest: This is a digest of above digests. } entirety_info;
Official Name | Official Description | Description | Flags |
---|---|---|---|
ContentDigest | This is a digest of content unique value. | May be located at offset 0x0 under encrypted form... | |
GameDigest | This is a digest of Header/Program/System/MajorParam Digests. | SHA256 of a buffer embedding Program/System/MajorParam/Header Digests in this order. | |
ProgramDigest | This is a digest of contents except sce_sys files. | ||
SystemDigest | This is a digest of sce_sys files except param.sfo. | ||
MajorParamDigest | This is a digest of param.sfo that affect behavior. | ||
ParamDigest | This is sha256 digest of param.sfo. | SHA256 of param.sfo. | |
HeaderDigest | This is a digest of package header. | ||
LiveareaDigest | This is a digest of sce_sys/livearea(&retail) files. | ||
ManualDigest | This is a digest of sce_sys/manual files. | ||
TrophyDigest | This is a digest of sce_sys/trophy files. | ||
ChangeInfoDigest | This is a digest of sce_sys/changeinfo files. | ||
OthersDigest | This is a digest of sce_sys files except above files. | ||
OriginDigest | This is the ContentDigest of base game package. | ||
unk | unk | ||
TargetDigest | unk | ||
TargetGameDigest | unk |
typedef struct { // size is 0xA0 u8 enc_content_digest[0x20]; u8 game_digest[0x20]; u8 system_digest[0x20]; u8 header_digest[0x20]; u8 livearea_digest[0x20]; // ?SHA256? of ??. Called LiveareaDigest: This is a digest of sce_sys/livearea(&retail) files. } entirety_data_A0_NOPARAM_LA_D300; // 1101 0011 0000 0000 -> 5
typedef struct { // size is 0xC0 u8 enc_content_digest[0x20]; u8 game_digest[0x20]; u8 program_digest[0x20]; u8 system_digest[0x20]; u8 major_param_digest[0x20]; u8 param_digest[0x20]; u8 header_digest[0x20]; } entirety_data_C0_EE00; // 1110 1110 0000 0000 -> 6
typedef struct { // size is 0x100 u8 enc_content_digest[0x20]; u8 game_digest[0x20]; u8 program_digest[0x20]; u8 system_digest[0x20]; u8 major_param_digest[0x20]; u8 param_digest[0x20]; u8 header_digest[0x20]; u8 others_digest[0x20]; // ?SHA256? of ??. Called OthersDigest: This is a digest of sce_sys files except above files. } entirety_data_100_OTH_FE10; // 1111 1110 0001 0000 -> 8
typedef struct { // size is 0x120 u8 enc_content_digest[0x20]; u8 game_digest[0x20]; u8 program_digest[0x20]; u8 system_digest[0x20]; u8 major_param_digest[0x20]; u8 param_digest[0x20]; u8 header_digest[0x20]; u8 livearea_digest[0x20]; // ?SHA256? of ??. Called LiveareaDigest: This is a digest of sce_sys/livearea(&retail) files. u8 others_digest[0x20]; // ?SHA256? of ??. Called OthersDigest: This is a digest of sce_sys files except above files. } entirety_data_120_LA_OTH_FF10; // 1111 1111 0001 0000 -> 9
typedef struct { // size is 0x140 u8 enc_content_digest[0x20]; u8 game_digest[0x20]; u8 program_digest[0x20]; u8 system_digest[0x20]; u8 major_param_digest[0x20]; u8 param_digest[0x20]; u8 header_digest[0x20]; u8 change_info_digest[0x20]; // ?SHA256? of ??. Called ChangeInfoDigest: This is a digest of sce_sys/changeinfo files. u8 others_digest[0x20]; // ?SHA256? of ??. Called OthersDigest: This is a digest of sce_sys files except above files. u8 enc_origin_digest[0x20]; // ?SHA256? of ??. ENCRYPTED FORM !! May be: Called OriginDigest: This is the ContentDigest of base game package. } entirety_data_140_CHG_OTH_ORI_FE38; // 1111 1110 0011 1000 -> 10
typedef struct { // size is 0x140 u8 enc_content_digest[0x20]; u8 game_digest[0x20]; u8 program_digest[0x20]; u8 system_digest[0x20]; u8 major_param_digest[0x20]; u8 param_digest[0x20]; u8 header_digest[0x20]; u8 livearea_digest[0x20]; // ?SHA256? of ??. Called LiveareaDigest: This is a digest of sce_sys/livearea(&retail) files. u8 manual_digest[0x20]; // ?SHA256? of ??. Called ManualDigest: This is a digest of sce_sys/manual files. u8 others_digest[0x20]; // ?SHA256? of ??. Called OthersDigest: This is a digest of sce_sys files except above files. } entirety_data_140_LA_MAN_OTH_FF90; // 1111 1110 1001 0000 -> 9
typedef struct { // size is 0x160 u8 enc_content_digest[0x20]; u8 game_digest[0x20]; u8 program_digest[0x20]; u8 system_digest[0x20]; u8 major_param_digest[0x20]; u8 param_digest[0x20]; u8 header_digest[0x20]; u8 livearea_digest[0x20]; // ?SHA256? of ??. Called LiveareaDigest: This is a digest of sce_sys/livearea(&retail) files. u8 manual_digest[0x20]; // ?SHA256? of ??. Called ManualDigest: This is a digest of sce_sys/manual files. u8 trophy_digest[0x20]; // ?SHA256? of ??. Called TrophyDigest: This is a digest of sce_sys/trophy files. u8 others_digest[0x20]; // ?SHA256? of ??. Called OthersDigest: This is a digest of sce_sys files except above files. } entirety_data_160_LA_MAN_TRP_OTH_FFD0; // 1111 1111 1101 0000 -> 11
typedef struct { // size is 0x160 u8 enc_content_digest[0x20]; u8 game_digest[0x20]; u8 program_digest[0x20]; u8 system_digest[0x20]; u8 major_param_digest[0x20]; u8 param_digest[0x20]; u8 header_digest[0x20]; u8 trophy_digest[0x20]; // ?SHA256? of ??. Called TrophyDigest: This is a digest of sce_sys/trophy files. u8 change_info_digest[0x20]; // ?SHA256? of ??. Called ChangeInfoDigest: This is a digest of sce_sys/changeinfo files. u8 others_digest[0x20]; // ?SHA256? of ??. Called OthersDigest: This is a digest of sce_sys files except above files. u8 enc_origin_digest[0x20]; // ?SHA256? of ??. ENCRYPTED FORM !! May be: Called OriginDigest: This is the ContentDigest of base game package. } entirety_data_160_TRP_CHG_OTH_ORI_FE78; // 1111 1110 0111 1000 -> 11
typedef struct { // size is 0x180 u8 enc_content_digest[0x20]; u8 game_digest[0x20]; u8 program_digest[0x20]; u8 system_digest[0x20]; u8 major_param_digest[0x20]; u8 param_digest[0x20]; u8 header_digest[0x20]; u8 manual_digest[0x20]; // ?SHA256? of ??. Called ManualDigest: This is a digest of sce_sys/manual files. u8 trophy_digest[0x20]; // ?SHA256? of ??. Called TrophyDigest: This is a digest of sce_sys/trophy files. u8 change_info_digest[0x20]; // ?SHA256? of ??. Called ChangeInfoDigest: This is a digest of sce_sys/changeinfo files. u8 others_digest[0x20]; // ?SHA256? of ??. Called OthersDigest: This is a digest of sce_sys files except above files. u8 enc_origin_digest[0x20]; // ?SHA256? of ??. ENCRYPTED FORM !! May be: Called OriginDigest: This is the ContentDigest of base game package. } entirety_data_180_MAN_TRP_CHG_OTH_ORI_FEF8; // 1111 1110 1111 1000 -> 12
Entirety Bitflags temporary table:
1000 0000 0000 0000 : Content
0100 0000 0000 0000 : Game
0010 0000 0000 0000 : Program
0001 0000 0000 0000 : System
0000 1000 0000 0000 : MajorParam
0000 0100 0000 0000 : Param
0000 0010 0000 0000 : Header
0000 0001 0000 0000 : LiveArea
0000 0000 1000 0000 : Manual
0000 0000 0100 0000 : Trophy
0000 0000 0010 0000 : ChangeInfo
0000 0000 0001 0000 : Others
0000 0000 0000 1000 : Origin
0000 0000 0000 0100 : unk1
0000 0000 0000 0010 : unk2
0000 0000 0000 0001 : unk3
MISSING : TargetDigest, TargetGameDigest
self_info
typedef struct { // size is 0x38 u32 self_info_offset; u32 self_info_size; // usually 0x10 or 0x20 u32 unk_int; // ex: 00 00 00 43 u8 unk[0x10]; u8 self_sha256[0x20]; } self_info;
typedef struct { // size is 0x10 u64 unk; // ex: 00 00 00 00 00 00 00 01, 80 00 00 00 00 00 00 00 u64 big_endian_authid; } self_info_data_element;
File Body
PKG Item Record
All values are in big endian format.
typedef struct { u32 filename_offset; u32 filename_size; u64 data_offset; u64 data_size; u32 flags; u32 padding; } PKG_ITEM_RECORD;
field | offset | type | notes |
---|---|---|---|
filename_offset | 0x0 | u32 | |
filename_size | 0x4 | u32 | |
data_offset | 0x8 | u64 | |
data_size | 0x10 | u64 | |
flags | 0x18 | u32 | The file type |
padding | 0x1C | u32 | zero |
PackageDigest
This is SHA1 digest of package without last 32 bytes.
The last 0x20 bytes of the package contains a hash (sha1sum) of the package (sha1 of the whole file minus the last 0x20 bytes). Or in other words... to verify the integrity of a package is needed to crop the 0x20 bytes at the end, then calculate the SHA1 of the resulting file, then compare with the SHA1 that was cropped.
It is also used as part of the package identification info inside the TITLE_ID-ver.xml files in PSN servers that lists the available game patches for each game. See: Game Updating Procedure page and the sha1sum in the .xml examples
- Notes
- This footer area is considered part of the package and is included when counting the total_size of the package (in the header at offset 0x18), and the header is hashed too by header_sha1_hash (at offset 0xB8), this is important in the sequence of actions needed when building the package and updating/adding the sha1 footer at the end
- Homebrew packages (at least some of them) doesnt includes this footer
Package Tools
PKG builder / infos / extractor
package.conf (PS3/PSVita/PSP)
Config name | usage | expected value | example |
---|---|---|---|
Content_ID | needed | XXYYYY-XXXXYYYYY_00-XXXXXXXXXXXXXXXX | EP4153-NPEZ00314_00-0000111122223333 |
K_licensee (PS3) | needed (can be set to 0x00000...) | 0x00000000000000000000000000000000 | 0x0123456789ABCDEF0123456789ABCDEF |
DRMType | needed | Network / Free / Local | Free |
ContentType | needed | See PKG_files#ContentType | minis |
PackageVersion | needed | XX.XX | 01.02 |
PackageType | See PKG_files#PackageType | DiscGamePatch | |
PackageFlag | See PKG_files#PackageFlag | RenameDirectory | |
StorageType | needed for PSVita gamedata | See PKG_files#StorageType | VC-MC |
TitleID | used only for PSP and PS1 games | XXXXYYYYY | NPEZ00314 |
LimitedTimeStart | YYYY-MM-DDThh:mmTZD | 2018-10-30T11:55T32 | |
LimitedTimeEnd | YYYY-MM-DDThh:mmTZD | 2019-10-30T11:55T32 | |
InstallDirectory | used in PSP patches ?and DLCs? | ? | UCUS98744_LBPPDLCSONYPA002 |
ForcedInstallTo | Allows installing packages to any hdd directory (and even flash memory if it's mounted RW). |
NPDRM.CONF (PSP)
Config name | usage | expected value | example |
---|---|---|---|
Content-ID | needed | XXYYYY-XXXXYYYYY_00-XXXXXXXXXXXXXXXX | EP4153-NPEZ00314_00-0000111122223333 |
K-Licensee | needed (can be set to 0x00000...) | 0x00000000000000000000000000000000 | 0x0123456789ABCDEF0123456789ABCDEF |
PackageVersion | needed | XX.XX | 01.02 |
ProtectDocument | used in PSP Downloadable Game Package (PSP .pkg)
Game Manual Protection To use NPDRM to protect the game manual, include the line "ProtectDocument = TRUE" in the configuration file. Like the downloadable game itself, once protected, the relevant game manual can only be browsed on a PSP™ that was authenticated with the user account used to purchase the downloadable game package. If "ProtectDocument = FALSE" is specified or if no specification is made, the game manual will not be protected by NPDRM. |
FALSE/TRUE | FALSE |
HealthWarning | used in PSP Downloadable Game Package (PSP .pkg)
Startup Warning You can specify that a startup warning be displayed when the game is started up. Specify "HealthWarning = " followed by the specification word shown in the following table, which indicates the region or language where the downloadable game package will be released. See Chapter 7 for the corresponding text that is displayed. If "HealthWarning = NONE" is specified or if no specification is made, no startup warning will be displayed. |
NONE/specification word | NONE |
ZIPThreshold | used in PSP Downloadable Game Package (PSP .pkg)
Compression Rate Specification During authoring of a downloadable game package, the data in the associated UMD™ image file is compressed. You can change the compression rate by specifying "ZIPThreshold=" followed by the compression rate (0 to 100). If there is no "ZIPThreshold=" specification, the compression rate will default to 80. If "ZIPThreshold=0" is specified, the data will not be compressed and there will no longer be any load for expanding the compressed data. However, the file size will increase and it will take longer for the user to download the package. Unless you specifically need to change the compression rate, do not include this specification. |
0 to 100 | 80 |
OptimizeLevel | used in PSP Downloadable Game Package (PSP .pkg)
The SCE authoring service may change the optimization level to improve processing performance when the system reads data in a downloadable game. If this change hinders the behavior of a program that is being developed, you can include the specification "OptimizeLevel=" followed by the optimization level that was used previously during authoring. If there is no impediment to program behavior, you should not enter this specification. When the authoring service changes, refer to details that are publically available in the Technical Notes. |
?0 to 100? | ?80? |
BootablePlatform | used in PSP minis Package (PSP minis .pkg)
When creating a package for minis, in addition to the necessary parameters for downloadable games, "BootablePlatform = minis" must be set in NPDRM.CONF that is a configuration file for packaging. |
minis | minis |
BootablePlatformDetails | used in PSP minis Package (PSP minis .pkg)
Game applications created via the Simple Authoring Service(SAS) having the above parameter specified can be executed on PlayStation®3. When it is required to prohibit a minis game application from running on the PlayStation®3 execution environment explicitly, set "BootablePlatformDetails=onlyPSP" to NPDRM.CONF in addition to the setting "BootablePlatform = minis". |
onlyPSP | onlyPSP |
PSP SDK official tool : make_package_npdrm (2006-2014)
- latest version: rev 1642 from 6.60 PSP SDK
PSVita SDK official tool : make_pkg (2011-2015)
- latest version: rev 1972 from 3.55 PSVita SDK
PS3 SDK official tool : make_package_npdrm (2006-2017)
- latest version: rev 1972 from 4.75 PS3 SDK
- common version: rev 1732 from 3.40 PS3 SDK (also found under patched form)
- oldest leaked version: rev 1061 from X.XX PS3 SDK
Make Package Npdrm Patcher (revision 1732) by SubZero Dezigns (2012)
A tool that patches official make_package_npdrm.exe (revision 1732) in order to remove its protections to build packages that embeds NPDRM already encrypted SELFs.
Make Edata/Package NPDRM GUI by SubZero Dezigns (2012)
A GUI program for Windows that patches on-the-fly official make_package_npdrm.exe (revision 1732) and allows to configure package.conf.
Force Package NPDRM by DEL1GHT Team (2010)
FORCE_PACKAGE_NPDRM is a modded version of SONY's "MAKE_PACKAGE_NPDRM".
It enables the repackaging of DRM'ed games into a .PKG file.
Howto :
First create the following structure :
* PARAM.SFO
* ICON0.PNG
* ...
* TROPDIR
* USRDIR
* Original EBOOT.BIN renamed to whatever you want (ie. GAME.BIN)
* YOUR EBOOT.BIN (SELF file)
* ...
Your EBOOT.BIN must launch the original EBOOT.BIN (ie. GAME.BIN)
Usage : force_package_npdrm [options] config-file target-directory
11/08/10 - V1.00 - Initial Release
- Based on SONY's "MAKE_PACKAGE_NPDRM Rev. 1203"
- "Extended" help with "--help" option
- Packaging of your SELF EBOOT.BIN
- Repackaging of SELF/SPRX/EDATA DRM'ed files
11/11/10 - V1.50 - Updates
- Based on SONY's "MAKE_PACKAGE_NPDRM Rev. 1732"
- Repackaging of SDATA DRM'ed files
- Repackaging of TROPHY directory
PSN Package NPDRM by DEL1GHT Team (2010)
PSN_PACKAGE_NPDRM is a fork of FORCE_PACKAGE_NPDRM.
It rebuilds PSN DRM'ed games into a .PKG file.
Original DRM'ed EBOOT.BIN is packaged as "raw data" ;-)
Still the problem of licence (act.dat) to run the game on another PS3.
Howto :
Download the PSN game directory from your HDD0 to your PC.
Create a "config-file" (a lot of explanations on internet).
Usage : psn_package_npdrm [options] config-file target-directory
11/11/10 - V1.00 - Initial Release
- Based (fork) on FORCE_PACKAGE_NPDRM V1.50
- Full repackaging of PSN games
PKG extractor
ungpkg by failoverflow/geohot (2010)
PS3/PSP .pkg
PkgView by Ifcaro (2012-2013)
PS3/PSP .pkg
PkgDecrypt by St4rk (2017)
PSVita .pkg
Package links
links by Hackinformer
https://hackinformer.com/PlayStationGuide/misc/zeuslinks.txt
pkgharvester
- sqlite3 db of .pkg files (pkg links, file infos, signatures, etc):
pkg_harvester_db.7z 6.7 MB (includes PS3, PSP)
uncompressed pkg_harvester.db size: 24.5 MB
several constants used in pkg_harvester.db:
enum class ProductEnvironment
{
kUnknown = 0,
kNP = 1,
kPQA = 2,
kPMGMT = 3,
kSPINT = 4,
};
enum class PackageType
{
kUnknown = 0,
kPS3 = 1,
kPSP = 2,
};
enum class FileType
{
kUnknown = 0,
kSelf = 1,
kSprx = 2,
kEdata = 3,
kSdata = 4,
};
enum class DRMLicenseType
{
kUnknown = 0,
kNetwork = 1,
kLocal = 2,
kFree = 3,
};
|