Skip to content

Instantly share code, notes, and snippets.

@dosomder
Last active July 19, 2023 01:17
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save dosomder/8ed79b26a5e063efa5ef to your computer and use it in GitHub Desktop.
Xperia SIN Structure analysis
// ==========================================================
// Sony Xperia SIN (Firmware flashable files) analysis
//
// Author: zxz0O0
// Started: 2014-06-05
// Notes: Numbers are big endian
// Credits: Androxyde
// ==========================================================
struct SinFile
{
SinHeader sinheader;
SinDataHeader sindataheader;
byte[??] data; //until eof
}
struct SinHeader
{
byte Version; //The following was done on version 0x03
byte[3] magic; //0x53, 0x49, 0x4E -> SIN
int SinHeaderLength;
int SinType; //not sure, if correct -> 0x20 for loader.sin, 0x24 for gpt table, 0x27 for MMCF partitions
byte[8] unknown;
int SinHeaderHashLength; //seems this does not exist anymore in newer sinv3 files with compression
SinHeaderHash[(SinHeaderHashLength / 0x24)] Hashes; //first one has size of SIN Data Header, others usually have 0x800
//dataSize of all Hashes + SinHeaderLength should equal size of file
byte[??] unknown2;
byte[0x100] RSASig; //RSA2048 Signature of a hash, probably SHA256 of SinHeader (excluding signature of course)
//not sure what is verifying the RSA signature, probably it's TZ (trust zone)
}
struct SinHeaderHash
{
int dataSize;
byte[0x20] SHA256; //SHA256 is calculated from data after SinHeader over the length of dataSize
//it's a data flow, i.e. the next data follows the last data (no need for start address)
}
struct SinDataHeader
{
byte[4] MMCFmagic; //0x4D, 0x4D, 0x43, 0x46 -> MMCF
int mmcfLength; //mmcfLength + 4 (the length itself) + 4 (the magic) = SinDataHeader length
byte[4] GPTPmagic; //0x47, 0x50, 0x54, 0x50 -> GPTP
int GPTPsize; //usually 0x18
byte[0x10] GPTGUID; //GPT Unique partition GUID
BlockInfoHeader[??] blockinformation;
//we do not know the actually size as BIH size is variable (compressed / uncompressed)
}
struct BlockInfoHeader
{
byte[4] magic;
//0x4C, 0x5A, 0x34, 0x41 -> LZ4A (compressed)
//0x41, 0x44, 0x44, 0x52 -> ADDR (uncompressed)
int BIHLength; //0x54 for LZ4A and 0x44 for ADDR
long dataStart;
long blockSize; //only for LZ4A
long dataLength;
long dataDest; //Address of destination in new file, everything else in the file is 0xFF (kind of 'compression')
long destLength; //only for LZ4A, should be the same as blockSize
int HashType; //not sure about that, if correct 2 = SHA256
byte[0x20] SHA256; //again SHA256 hash, probably for verifying in the destination
}
// And that is the reason why we can not create custom firmwares for Xperia. If you still don't understand, RSA is an asymmetric function.
// This means it's using a private key to create the signature and a public key to read it. So even if we find the public key
// (which is somewhere on the device), we can never find or guess the private key. Therefore we can not create a valid signature.
//Yes I know that the syntax is not correct in C#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment