SELF - SPRX: Difference between revisions

From PS3 Developer wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
File Format
[[Category:PS3]]
''' Source: http://ps3wiki.lan.st/index.php?title=SELF_File_Format_and_Decryption '''
----
= File Format =


Notes:
Notes:  


    * Numbers are stored in big endian format.  
*Numbers are stored in big endian format.


SELF Header
=== SELF Header ===


typedef struct
typedef struct
{
{
  uint32_t magic;                  // "SCE\0"
  uint32_t magic;                  // "SCE\0"
  uint32_t version;                // 2
  uint32_t version;                // 2
Line 26: Line 29:
  uint64_t controlInfoSize;
  uint64_t controlInfoSize;
  uint64_t unknown15;
  uint64_t unknown15;
}
SELFHEADER_t;


}
=== Program Info  ===
SELFHEADER_t;


Program Info
typedef struct
{
  uint64_t programAuthId;
  uint64_t unknown01;
  uint16_t programVersion[4];
  uint64_t unknown03;
}
PROGRAMINFO_t;


typedef struct
=== ELF Header  ===
{
  uint64_t programAuthId;
  uint64_t unknown01;
  uint16_t programVersion[4];
  uint64_t unknown03;
}
PROGRAMINFO_t;


ELF Header
See Spec here: [http://www.sco.com/developers/gabi/latest/ch4.eheader.html ELF Header]


Notes:


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


Notes:
=== ELF Program Headers  ===


    * e_type: ET_PS3PRX=0xFFA4
See Spec here: [http://www.sco.com/developers/gabi/latest/ch5.pheader.html ELF Program Headers]
    * 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;


Segment Information
Notes:


typedef struct
*There is one Segment Information for each ELF Program Header.<br>
{
  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:
=== Control Information  ===


    * There is one Segment Information for each ELF Program Header.
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;


Control Information
=== Metadata Information ===


typedef struct
typedef struct
{  
{
  uint32_t unknown00;
  uint8_t unknown00[32];
  uint32_t unknown01;
  uint8_t key[32];
  uint32_t unknown02;
  uint8_t ivec[32];
  uint32_t unknown03;
}
  uint32_t controlFlags[8];
METADATAINFO_t;
  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
Notes:


typedef struct
*The key and ivec fields are encrypted using AES256CBC.
{
*This is not present if it is an FSELF.
  uint8_t unknown00[32];
  uint8_t key[32];
  uint8_t ivec[32];
}
METADATAINFO_t;


Notes:
=== Metadata Header  ===


    * The key and ivec fields are encrypted using AES256CBC.
typedef struct
    * This is not present if it is an FSELF.
{
  uint64_t signatureInputLength;
  uint32_t unknown02;
  uint32_t sectionCount;
  uint32_t keyCount;
  uint32_t signatureInfoSize;
  uint32_t unknown06;
  uint32_t unknown07;
}
METADATAHEADER_t;


Metadata Header
Notes:


typedef struct
*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.
  uint64_t signatureInputLength;
*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.
  uint32_t unknown02;
*This is only present if the metadata Information is present.
  uint32_t sectionCount;
  uint32_t keyCount;
  uint32_t signatureInfoSize;
  uint32_t unknown06;
  uint32_t unknown07;
}
METADATAHEADER_t;


Notes:
=== Metadata Section Headers  ===


    * The metadata header is located after the metadata info in the SELF file.
typedef struct
    * 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.
  uint64_t dataOffset;
      The length should be eveything from the beginning until the signature itself. The decrypted version of the input data is used.
  uint64_t dataSize;
    * This is only present if the metadata Information is present.
  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;


Metadata Section Headers
Notes:


typedef struct
*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.
  uint64_t dataOffset;
*They are decrypted using AES128CTR with the key and ivec entries from the metadata information.
  uint64_t dataSize;
*Section data is decrypted using AES128CTR&nbsp;with the key and ivec from the metadata keys specified by keyIndex and ivecIndex.
  uint32_t unknown02;
*Section data will also need to be uncompressed using zlib.
  uint32_t programIndex;
*The dataOffsets of the metadata section headers match in general the segment information dataOffsets.
  uint32_t unknown04;
*This is only present if the metadata header is present.
  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:
=== Metadata Keys  ===


    * The metadata section headers are located after the metadata header in the SELF file.
typedef uint8_t METADATAKEY_t [16];
    * 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
Notes:


typedef uint8_t METADATAKEY_t [16];
*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.


Notes:
=== Signature Information  ===


    * The metadata keys are located after the metadata section headers in the SELF file.
typedef struct
    * 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.
  uint32_t unknown00;
    * If the sha1Index points to a key, then key[sha1Index] and key[sha1Index+1] form the 160-bit hash. key[sha1Index+2]
  uint32_t signatureSize;
    to key[key[sha1Index+6] form the 512-bit key for the HMAC-SHA1.
  uint64_t unknown02;
    The HMAC-SHA1 is calculated on the decrypted data and before the decompression.
  uint64_t unknown03;
  uint64_t unknown04;
  uint64_t unknown05;
  uint32_t unknown06;
  uint32_t unknown07;
}
SIGNATUREINFO_t;


Signature Information
Notes:


typedef struct
*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.
  uint32_t unknown00;
*It is decrypted using AES128CTR with the key and ivec entries from the metadata information.
  uint32_t signatureSize;
  uint64_t unknown02;
  uint64_t unknown03;
  uint64_t unknown04;
  uint64_t unknown05;
  uint32_t unknown06;
  uint32_t unknown07;
}
SIGNATUREINFO_t;


Notes:
=== Signature  ===


    * The signature information is located after the metadata keys in the SELF file.
typedef struct
    * 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.
  uint8_t r[21];
  uint8_t s[21];
  uint8_t padding[6];
}
SIGNATURE_t;


Signature
Notes:


typedef struct
*The signature is located after the the signature information in the SELF file.
{
*It is even present if the signature information is not present.
  uint8_t r[21];
*It is decrypted using AES128CTR with the key and ivec entries from the metadata information.
  uint8_t s[21];
  uint8_t padding[6];
}
SIGNATURE_t;


Notes:
= Extracting an ELF<br> =


    * The signature is located after the the signature information in the SELF file.
=== ELF Header  ===
    * 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
Elf64_Ehdr elfHeader;
ELF Header
fseek ( selfFile, fix64 ( selfHeader.elfHeaderOffset ), SEEK_SET );
fread ( &amp;elfHeader, sizeof ( Elf64_Ehdr ), 1, selfFile );
fseek ( elfFile, 0, SEEK_SET );
fwrite ( &amp;elfHeader, sizeof ( Elf64_Ehdr ), 1, elfFile );


Elf64_Ehdr elfHeader;
=== Section Headers  ===


fseek ( selfFile, fix64 ( selfHeader.elfHeaderOffset ), SEEK_SET );
Elf64_Shdr elfSectionHeaders[100];
fread ( &elfHeader, sizeof ( Elf64_Ehdr ), 1, selfFile );
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 );


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


Section Headers
Notes:


Elf64_Shdr elfSectionHeaders[100];
*Unknown, manually copying the data over works for now.
*There should be a section data offset somewhere.


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


fseek ( elfFile, fix64 ( elfHeader.e_shoff ), SEEK_SET );
Elf64_Phdr elfProgramHeaders[100];
fwrite ( elfSectionHeaders, sizeof ( Elf64_Shdr ), fix16 ( elfHeader.e_shnum ), elfFile );
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 );


Section Data
=== Program Data ===


Notes:
Notes:  


    * Unknown, manually copying the data over works for now.
*Load the metadata information and decrypt the key and ivec entries using AES256CBC using erk and riv.  
    * There should be a section data offset somewhere.
*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.  
Program Headers
*Load keyCount metadata keys and decrypt them using AES128CTR with the key and ivec entries from the metadata information.  
 
*For each metadata section:  
Elf64_Phdr elfProgramHeaders[100];
**In the SELF file, fseek to dataOffset and read in dataSize bytes.  
 
**Decrypt the data using AES128CTR with the key and ivec from the metadata keys specified by keyIndex and ivecIndex from the metadata section header.  
fseek ( selfFile, fix64 ( selfHeader.elfProgramHeadersOffset ), SEEK_SET );
**Uncompress the data using zlib.  
fread ( elfProgramHeaders, sizeof ( Elf64_Phdr ), fix16 ( elfHeader.e_phnum ), selfFile );
**Write it to the ELF file as the program section specified by sectionIndex in the metadata section header.
 
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 03:46, 25 February 2011

Source: http://ps3wiki.lan.st/index.php?title=SELF_File_Format_and_Decryption


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

See Spec here: ELF Header

Notes:

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

ELF Program Headers

See Spec here: 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:
    • In the SELF file, fseek to dataOffset and read in dataSize bytes.
    • Decrypt the data using AES128CTR with the key and ivec from the metadata keys specified by keyIndex and ivecIndex from the metadata section header.
    • Uncompress the data using zlib.
    • Write it to the ELF file as the program section specified by sectionIndex in the metadata section header.