Editing PKG files
Jump to navigation
Jump to search
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
{{wikify}} | {{wikify}} | ||
For more information, see {{talk}} | |||
== Structure == | == Package Structure == | ||
=== File Header === | === File Header === | ||
While most of the PS4 is little endian, the package file header still uses big endianness as the headers are based on their PS3 predecessors. | |||
While most of the PS4 | |||
typedef struct { | typedef struct { | ||
uint32_t pkg_magic; | uint32_t pkg_magic; // 0x000 | ||
uint16_t pkg_revision; // 0x004 | |||
uint32_t | uint16_t pkg_type; // 0x006 | ||
uint32_t pkg_file_count; | uint32_t pkg_unk; // 0x008 - unknown field | ||
uint32_t pkg_entry_count; | uint32_t pkg_file_count; // 0x00C | ||
uint16_t pkg_sc_entry_count; | uint32_t pkg_entry_count; // 0x010 | ||
uint16_t pkg_entry_count_2; | uint16_t pkg_sc_entry_count; // 0x014 | ||
uint32_t pkg_table_offset; | uint16_t pkg_entry_count_2; // 0x016 - same as pkg_entry_count | ||
uint32_t | uint32_t pkg_table_offset; // 0x018 - file table offset | ||
uint64_t pkg_body_offset; | uint32_t pkg_ent_data_size; // 0x01C | ||
uint64_t pkg_body_size; | uint64_t pkg_body_offset; // 0x020 - offset of PKG entries | ||
uint64_t pkg_body_size; // 0x028 - length of all PKG entries | |||
<br> | |||
unsigned char pkg_padding[0x10]; // 0x030 - 16 bytes padding | |||
unsigned char pkg_content_id[0x24]; // 0x040 - packages' content ID as a 36-byte string | unsigned char pkg_content_id[0x24]; // 0x040 - packages' content ID as a 36-byte string | ||
unsigned char | unsigned char pad[0xC]; // 0x064 - 0x070 - padding | ||
uint32_t pkg_drm_type; // 0x070 - DRM type | uint32_t pkg_drm_type; // 0x070 - DRM type | ||
uint32_t pkg_content_type; // 0x074 - Content type | uint32_t pkg_content_type; // 0x074 - Content type | ||
// other stuff... 0x78 - 0x100 | |||
<br> | <br> | ||
/* Digest table */ | /* Digest table */ | ||
Line 43: | Line 32: | ||
unsigned char digest_table_digest[0x20]; // 0x140 - sha256 digest for digest table | unsigned char digest_table_digest[0x20]; // 0x140 - sha256 digest for digest table | ||
unsigned char digest_body_digest[0x20]; // 0x160 - sha256 digest for main table | unsigned char digest_body_digest[0x20]; // 0x160 - sha256 digest for main table | ||
// ... | // ... 0x180 - 0x400 | ||
uint32_t pfs_image_count; // 0x404 - count of PFS images | uint32_t pfs_image_count; // 0x404 - count of PFS images | ||
uint64_t | uint64_t pfs_flags; // 0x408 - PFS flags | ||
uint64_t pfs_image_offset; // 0x410 - offset to start of external PFS image | uint64_t pfs_image_offset; // 0x410 - offset to start of external PFS image | ||
uint64_t pfs_image_size; // 0x418 - size of external PFS image | uint64_t pfs_image_size; // 0x418 - size of external PFS image | ||
// ... | // ... | ||
} pkg_header; | |||
} pkg_header; | |||
=== Files === | === Files === | ||
The file table is a list of file entries: | The file table is a list of file entries: | ||
Line 89: | Line 67: | ||
There are also files without plaintext filenames. These are identified by their ID in the file entry table. | There are also files without plaintext filenames. These are identified by their ID in the file entry table. | ||
== PFS == | == PFS == | ||
Main article: [[PFS]] ''(only explains un-encrypted, un-signed PFS)'' | |||
The main portion of a PKG file is its signed and encrypted PFS image. It is encrypted with XTS-AES with a block size of 0x1000. The key is derived from the HMAC-SHA256 of the concatenation of "0x01 0x00 0x00 0x00" in and the EKPFS. The HMAC key is the "crypt seed" which is at offset 0x370 in the PFS itself. The tweak key is the first 16 bytes of the HMAC result, while the data key is the second 16 bytes. | |||
The PFS image in a PKG is different from the decrypted image exposed by the system in <code>/mnt/sandbox/pfsmnt/CUSA00001-app0-nest/pfs_image.dat</code>. This image uses <code>dinode_s32</code>, the signed inode variant, which includes a 32-byte signature for every direct and indirect block. Additionally, the indirect block blocks also have a 32-byte signature for each block within. | |||
The PFS image in a PKG | |||
Inside the PFS image in a PKG is a single file: <code>pfs_image.dat</code> which is a special type of compressed PFS image with a <code>PFSC</code> header. Inside <code>pfs_image.dat</code> is where the actual game/theme/DLC data lives. | Inside the PFS image in a PKG is a single file: <code>pfs_image.dat</code> which is a special type of compressed PFS image with a <code>PFSC</code> header. Inside <code>pfs_image.dat</code> is where the actual game/theme/DLC data lives. | ||
== Delivery == | == Delivery == | ||
=== Title XML === | === Title XML === | ||
The PS4 fetches information about pkg files (including where to download them) from an XML file. | |||
The PS4 fetches information about | This XML file contains information such as if the latest patch is mandatory, the latest package version, the manifest, as well as param.sfo information. Below is an example of a typical title XML file: | ||
<titlepatch titleid="CUSAXXXXX"> | <titlepatch titleid="CUSAXXXXX"> | ||
Line 182: | Line 101: | ||
=== Manifest === | === Manifest === | ||
It should be noted that PS4 package files have a maximum size of 4GB (or 4096MB), therefore large (most) games are split into chunks or pieces. This is kept track of in the manifest file, which contains json fields which document things such as the size of the final package after the chunks are spliced together, the digest of the final package, the number of chunks, as well as information for each chunk such as the pkg url, offset for splicing, size of the file, and the sha1 hash value of the individual chunk. | |||
It should be noted that PS4 package files have a maximum size of 4GB (or 4096MB), therefore large (most) games are split into chunks or pieces. This is kept track of in the manifest file, which contains | |||
originalFileSize: [size] | originalFileSize: [size] | ||
Line 195: | Line 113: | ||
fileSize: [size, often 4294967296 until last chunk] | fileSize: [size, often 4294967296 until last chunk] | ||
hashValue: "[sha1 hash of chunk]" | hashValue: "[sha1 hash of chunk]" | ||
== Sample Packages == | == Sample Packages == | ||
=== Apps/Games === | === Apps/Games === | ||
* Amazon/LOVEFiLM App | * Amazon/LOVEFiLM App | ||
http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA00126_00/1/f_012ccf9936265867696e3906c9bd9f0fd1869111fa372b2d1fad0ca4127ba67b/f/EP4183-CUSA00126_00-AIV00000000000EU.pkg | http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA00126_00/1/f_012ccf9936265867696e3906c9bd9f0fd1869111fa372b2d1fad0ca4127ba67b/f/EP4183-CUSA00126_00-AIV00000000000EU.pkg | ||
Line 562: | Line 134: | ||
=== Themes === | === Themes === | ||
* 20th Anniversary Dynamic Theme | * 20th Anniversary Dynamic Theme | ||
http://gs2.ww.prod.dl.playstation.net/gs2/acpkgo/prod/CUSA01501_00/5/f_3074fd8eb8322540c8742865a722c6773b031f68d517df3e18d7037fe58af7b0/f/EP9000-CUSA01501_00-20THANNITHEME001.pkg | http://gs2.ww.prod.dl.playstation.net/gs2/acpkgo/prod/CUSA01501_00/5/f_3074fd8eb8322540c8742865a722c6773b031f68d517df3e18d7037fe58af7b0/f/EP9000-CUSA01501_00-20THANNITHEME001.pkg | ||
Line 577: | Line 148: | ||
* Spiralen Dynamic Theme | * Spiralen Dynamic Theme | ||
http://gs2.ww.prod.dl.playstation.net/gs2/acpkgo/prod/CUSA01501_00/1/f_a6fb07c75a9776ca2f71e557a98620318bf11378c69d812f147c9f0fe12ee1c6/f/EP9000-CUSA01501_00-0000000000000003.pkg | http://gs2.ww.prod.dl.playstation.net/gs2/acpkgo/prod/CUSA01501_00/1/f_a6fb07c75a9776ca2f71e557a98620318bf11378c69d812f147c9f0fe12ee1c6/f/EP9000-CUSA01501_00-0000000000000003.pkg | ||
'''Source:''' https://boerse.to/thema/datenbank-fuer-ps4-psn-links.1979635/ | '''Source:''' https://boerse.to/thema/datenbank-fuer-ps4-psn-links.1979635/ | ||
See also: [[ | See also: [[PKG_files/rawlist1]], [[PKG_files/rawlist2]] | ||
{{File Formats}} | {{File Formats}} | ||
<noinclude>[[Category:Main]]</noinclude> | <noinclude>[[Category:Main]]</noinclude> |