SELF - SPRX: Difference between revisions

From PS3 Developer wiki
Jump to navigation Jump to search
(Created page with "Will be Updated Soon")
 
No edit summary
Line 1: Line 1:
Will be Updated Soon
File Format
 
Notes:
 
    * Numbers are stored in big endian format.
 
SELF Header
 
typedef struct
{
uint32_t magic;                  // "SCE\0"
uint32_t version;                // 2
uint16_t attribute;              // 0x8000 - fself
uint16_t category;
uint32_t metadataInfoOffset;
uint64_t fileOffset;
uint64_t fileSize;
uint64_t unknown06;
uint64_t programInfoOffset;
uint64_t elfHeaderOffset;
uint64_t elfProgramHeadersOffset;
uint64_t elfSectionHeadersOffset;
uint64_t sInfoOffset;
uint64_t versionInfoOffset;
uint64_t controlInfoOffset;
uint64_t controlInfoSize;
uint64_t unknown15;
 
}
SELFHEADER_t;
 
Program Info
 
typedef struct
{
  uint64_t programAuthId;
  uint64_t unknown01;
  uint16_t programVersion[4];
  uint64_t unknown03;
}
PROGRAMINFO_t;
 
ELF Header
 
 
 
Notes:
 
    * e_type: ET_PS3PRX=0xFFA4
    * EI_OSABI: ELFOSABI_CELL_LV2=0x66
 
ELF Program Headers
 
 
Segment Information
 
typedef struct
{
  uint64_t dataOffset;
  uint64_t dataSize;
  uint32_t compressed;  //1:NO, 2:YES
  uint32_t unknown03;
  uint32_t unknown04;
  uint32_t encrypted;  //0:NA, 1:YES, 2:NO
}
SEGMENTINFO_t;
 
Notes:
 
    * There is one Segment Information for each ELF Program Header.
 
Control Information
 
typedef struct
{
  uint32_t unknown00;
  uint32_t unknown01;
  uint32_t unknown02;
  uint32_t unknown03;
  uint32_t controlFlags[8];
  uint32_t unknown05;
  uint32_t unknown06;
  uint32_t unknown07;
  uint32_t unknown08;
  char digest[64];
  uint32_t unknown10;
  uint32_t unknown11;
}
CONTROLINFO_t;
 
Metadata Information
 
typedef struct
{
  uint8_t unknown00[32];
  uint8_t key[32];
  uint8_t ivec[32];
}
METADATAINFO_t;
 
Notes:
 
    * The key and ivec fields are encrypted using AES256CBC.
    * This is not present if it is an FSELF.
 
Metadata Header
 
typedef struct
{
  uint64_t signatureInputLength;
  uint32_t unknown02;
  uint32_t sectionCount;
  uint32_t keyCount;
  uint32_t signatureInfoSize;
  uint32_t unknown06;
  uint32_t unknown07;
}
METADATAHEADER_t;
 
Notes:
 
    * The metadata header is located after the metadata info in the SELF file.
    * It is decrypted using AES128CTR with the key and ivec entries from the metadata information.
    * The signature input length is the number of bytes which are used to generate the SHA-1 which is used to generate the ECDSA signature.
      The length should be eveything from the beginning until the signature itself. The decrypted version of the input data is used.
    * This is only present if the metadata Information is present.
 
Metadata Section Headers
 
typedef struct
{
  uint64_t dataOffset;
  uint64_t dataSize;
  uint32_t unknown02;
  uint32_t programIndex;
  uint32_t unknown04;
  uint32_t sha1Index;
  uint32_t encrypted;  //1:NO, 3:YES
  uint32_t keyIndex;
  uint32_t ivecIndex;
  uint32_t compressed; //1:NO, 2:YES
}
METADATASECTIONHEADER_t;
 
Notes:
 
    * The metadata section headers are located after the metadata header in the SELF file.
    * The number of sections is indicated by the sectionCount entry in the metadata header.
    * They are decrypted using AES128CTR with the key and ivec entries from the metadata information.
    * Section data is decrypted using AES128CTR with the key and ivec from the metadata keys specified by keyIndex and ivecIndex.
    * Section data will also need to be uncompressed using zlib.
    * The dataOffsets of the metadata section headers match in general the segment information dataOffsets.
    * This is only present if the metadata header is present.
 
Metadata Keys
 
typedef uint8_t METADATAKEY_t [16];
 
Notes:
 
    * The metadata keys are located after the metadata section headers in the SELF file.
    * The number of keys is indicated by the keyCount entry in the metadata header.
    * They are decrypted using AES128CTR with the key and ivec entries from the metadata information.
    * If the sha1Index points to a key, then key[sha1Index] and key[sha1Index+1] form the 160-bit hash. key[sha1Index+2]
    to key[key[sha1Index+6] form the 512-bit key for the HMAC-SHA1.
    The HMAC-SHA1 is calculated on the decrypted data and before the decompression.
 
Signature Information
 
typedef struct
{
  uint32_t unknown00;
  uint32_t signatureSize;
  uint64_t unknown02;
  uint64_t unknown03;
  uint64_t unknown04;
  uint64_t unknown05;
  uint32_t unknown06;
  uint32_t unknown07;
}
SIGNATUREINFO_t;
 
Notes:
 
    * The signature information is located after the metadata keys in the SELF file.
    * It is only present if the signatureInfoSize in the metadata header is not zero.
    * It is decrypted using AES128CTR with the key and ivec entries from the metadata information.
 
Signature
 
typedef struct
{
  uint8_t r[21];
  uint8_t s[21];
  uint8_t padding[6];
}
SIGNATURE_t;
 
Notes:
 
    * The signature is located after the the signature information in the SELF file.
    * It is even present if the signature information is not present.
    * It is decrypted using AES128CTR with the key and ivec entries from the metadata information.
 
Extracting an ELF
ELF Header
 
Elf64_Ehdr elfHeader;
 
fseek ( selfFile, fix64 ( selfHeader.elfHeaderOffset ), SEEK_SET );
fread ( &elfHeader, sizeof ( Elf64_Ehdr ), 1, selfFile );
 
fseek ( elfFile, 0, SEEK_SET );
fwrite ( &elfHeader, sizeof ( Elf64_Ehdr ), 1, elfFile );
 
Section Headers
 
Elf64_Shdr elfSectionHeaders[100];
 
fseek ( selfFile, fix64 ( selfHeader.elfSectionHeadersOffset ), SEEK_SET );
fread ( elfSectionHeaders, sizeof ( Elf64_Shdr ), fix16 ( elfHeader.e_shnum ), selfFile );
 
fseek ( elfFile, fix64 ( elfHeader.e_shoff ), SEEK_SET );
fwrite ( elfSectionHeaders, sizeof ( Elf64_Shdr ), fix16 ( elfHeader.e_shnum ), elfFile );
 
Section Data
 
Notes:
 
    * Unknown, manually copying the data over works for now.
    * There should be a section data offset somewhere.
 
Program Headers
 
Elf64_Phdr elfProgramHeaders[100];
 
fseek ( selfFile, fix64 ( selfHeader.elfProgramHeadersOffset ), SEEK_SET );
fread ( elfProgramHeaders, sizeof ( Elf64_Phdr ), fix16 ( elfHeader.e_phnum ), selfFile );
 
fseek ( elfFile, fix64 ( elfHeader.e_phoff ), SEEK_SET );
fwrite ( elfProgramHeaders, sizeof ( Elf64_Phdr ), fix16 ( elfHeader.e_phnum ), elfFile );
 
Program Data
 
Notes:
 
    * Load the metadata information and decrypt the key and ivec entries using AES256CBC using erk and riv.
    * Load the metadata header and decrypt it using AES128CTR with the key and ivec entries from the metadata information.
    * Load sectionCount metadata section headers and decrypt them using AES128CTR with the key and ivec entries from the metadata information.
    * Load keyCount metadata keys and decrypt them using AES128CTR with the key and ivec entries from the metadata information.
    * For each metadata section:
          o In the SELF file, fseek to dataOffset and read in dataSize bytes.
          o Decrypt the data using AES128CTR with the key and ivec from the metadata keys specified by keyIndex and ivecIndex from the
            metadata section header.
          o Uncompress the data using zlib.
          o Write it to the ELF file as the program section specified by sectionIndex in the metadata section header.
source:[http://ps3wiki.lan.st/index.php?title=SELF_File_Format_and_Decryption]

Revision as of 23:10, 24 February 2011

File Format

Notes:

   * Numbers are stored in big endian format. 

SELF Header

typedef struct {

uint32_t magic;                   // "SCE\0"
uint32_t version;                 // 2
uint16_t attribute;               // 0x8000 - fself
uint16_t category;
uint32_t metadataInfoOffset;
uint64_t fileOffset;
uint64_t fileSize;
uint64_t unknown06;
uint64_t programInfoOffset;
uint64_t elfHeaderOffset;
uint64_t elfProgramHeadersOffset;
uint64_t elfSectionHeadersOffset;
uint64_t sInfoOffset;
uint64_t versionInfoOffset;
uint64_t controlInfoOffset;
uint64_t controlInfoSize;
uint64_t unknown15;

} SELFHEADER_t;

Program Info

typedef struct {

 uint64_t programAuthId;
 uint64_t unknown01;
 uint16_t programVersion[4];
 uint64_t unknown03;

} PROGRAMINFO_t;

ELF Header


Notes:

   * e_type: ET_PS3PRX=0xFFA4
   * EI_OSABI: ELFOSABI_CELL_LV2=0x66 

ELF Program Headers


Segment Information

typedef struct {

 uint64_t dataOffset;
 uint64_t dataSize;
 uint32_t compressed;  //1:NO, 2:YES
 uint32_t unknown03;
 uint32_t unknown04;
 uint32_t encrypted;   //0:NA, 1:YES, 2:NO

} SEGMENTINFO_t;

Notes:

   * There is one Segment Information for each ELF Program Header.

Control Information

typedef struct {

 uint32_t unknown00;
 uint32_t unknown01;
 uint32_t unknown02;
 uint32_t unknown03;
 uint32_t controlFlags[8];
 uint32_t unknown05;
 uint32_t unknown06;
 uint32_t unknown07;
 uint32_t unknown08;
 char digest[64];
 uint32_t unknown10;
 uint32_t unknown11;

} CONTROLINFO_t;

Metadata Information

typedef struct {

 uint8_t unknown00[32];
 uint8_t key[32];
 uint8_t ivec[32];

} METADATAINFO_t;

Notes:

   * The key and ivec fields are encrypted using AES256CBC.
   * This is not present if it is an FSELF. 

Metadata Header

typedef struct {

 uint64_t signatureInputLength;
 uint32_t unknown02;
 uint32_t sectionCount;
 uint32_t keyCount;
 uint32_t signatureInfoSize;
 uint32_t unknown06;
 uint32_t unknown07;

} METADATAHEADER_t;

Notes:

   * The metadata header is located after the metadata info in the SELF file.
   * It is decrypted using AES128CTR with the key and ivec entries from the metadata information.
   * The signature input length is the number of bytes which are used to generate the SHA-1 which is used to generate the ECDSA signature.
     The length should be eveything from the beginning until the signature itself. The decrypted version of the input data is used.
   * This is only present if the metadata Information is present. 

Metadata Section Headers

typedef struct {

 uint64_t dataOffset;
 uint64_t dataSize;
 uint32_t unknown02;
 uint32_t programIndex;
 uint32_t unknown04;
 uint32_t sha1Index;
 uint32_t encrypted;  //1:NO, 3:YES
 uint32_t keyIndex;
 uint32_t ivecIndex;
 uint32_t compressed; //1:NO, 2:YES

} METADATASECTIONHEADER_t;

Notes:

   * The metadata section headers are located after the metadata header in the SELF file.
   * The number of sections is indicated by the sectionCount entry in the metadata header.
   * They are decrypted using AES128CTR with the key and ivec entries from the metadata information.
   * Section data is decrypted using AES128CTR with the key and ivec from the metadata keys specified by keyIndex and ivecIndex.
   * Section data will also need to be uncompressed using zlib.
   * The dataOffsets of the metadata section headers match in general the segment information dataOffsets.
   * This is only present if the metadata header is present. 

Metadata Keys

typedef uint8_t METADATAKEY_t [16];

Notes:

   * The metadata keys are located after the metadata section headers in the SELF file.
   * The number of keys is indicated by the keyCount entry in the metadata header.
   * They are decrypted using AES128CTR with the key and ivec entries from the metadata information.
   * If the sha1Index points to a key, then key[sha1Index] and key[sha1Index+1] form the 160-bit hash. key[sha1Index+2]
   to key[key[sha1Index+6] form the 512-bit key for the HMAC-SHA1.
   The HMAC-SHA1 is calculated on the decrypted data and before the decompression. 

Signature Information

typedef struct {

 uint32_t unknown00;
 uint32_t signatureSize;
 uint64_t unknown02;
 uint64_t unknown03;
 uint64_t unknown04;
 uint64_t unknown05;
 uint32_t unknown06;
 uint32_t unknown07;

} SIGNATUREINFO_t;

Notes:

   * The signature information is located after the metadata keys in the SELF file.
   * It is only present if the signatureInfoSize in the metadata header is not zero.
   * It is decrypted using AES128CTR with the key and ivec entries from the metadata information. 

Signature

typedef struct {

 uint8_t r[21];
 uint8_t s[21];
 uint8_t padding[6];

} SIGNATURE_t;

Notes:

   * The signature is located after the the signature information in the SELF file.
   * It is even present if the signature information is not present.
   * It is decrypted using AES128CTR with the key and ivec entries from the metadata information. 

Extracting an ELF ELF Header

Elf64_Ehdr elfHeader;

fseek ( selfFile, fix64 ( selfHeader.elfHeaderOffset ), SEEK_SET ); fread ( &elfHeader, sizeof ( Elf64_Ehdr ), 1, selfFile );

fseek ( elfFile, 0, SEEK_SET ); fwrite ( &elfHeader, sizeof ( Elf64_Ehdr ), 1, elfFile );

Section Headers

Elf64_Shdr elfSectionHeaders[100];

fseek ( selfFile, fix64 ( selfHeader.elfSectionHeadersOffset ), SEEK_SET ); fread ( elfSectionHeaders, sizeof ( Elf64_Shdr ), fix16 ( elfHeader.e_shnum ), selfFile );

fseek ( elfFile, fix64 ( elfHeader.e_shoff ), SEEK_SET ); fwrite ( elfSectionHeaders, sizeof ( Elf64_Shdr ), fix16 ( elfHeader.e_shnum ), elfFile );

Section Data

Notes:

   * Unknown, manually copying the data over works for now.
   * There should be a section data offset somewhere. 

Program Headers

Elf64_Phdr elfProgramHeaders[100];

fseek ( selfFile, fix64 ( selfHeader.elfProgramHeadersOffset ), SEEK_SET ); fread ( elfProgramHeaders, sizeof ( Elf64_Phdr ), fix16 ( elfHeader.e_phnum ), selfFile );

fseek ( elfFile, fix64 ( elfHeader.e_phoff ), SEEK_SET ); fwrite ( elfProgramHeaders, sizeof ( Elf64_Phdr ), fix16 ( elfHeader.e_phnum ), elfFile );

Program Data

Notes:

   * Load the metadata information and decrypt the key and ivec entries using AES256CBC using erk and riv.
   * Load the metadata header and decrypt it using AES128CTR with the key and ivec entries from the metadata information.
   * Load sectionCount metadata section headers and decrypt them using AES128CTR with the key and ivec entries from the metadata information.
   * Load keyCount metadata keys and decrypt them using AES128CTR with the key and ivec entries from the metadata information.
   * For each metadata section:
         o In the SELF file, fseek to dataOffset and read in dataSize bytes.
         o Decrypt the data using AES128CTR with the key and ivec from the metadata keys specified by keyIndex and ivecIndex from the
           metadata section header.
         o Uncompress the data using zlib.
         o Write it to the ELF file as the program section specified by sectionIndex in the metadata section header.

source:[1]