Savegame Files
Format
A savegame consists of a Header, followed by a Bk Header and a set of files contained in a files section, and finally a certificate chain. The savgames are signed while being copied to the SD card using the Wii's private NG key.
Header
The Header is 0xF0C0 bytes long. It is encrypted (AES128-CBC) using the "sd-key" and the "sd-iv" initialization vector.
The plaintext header contents are described in the following table.
It's divided in two parts: The "main header" and the "banner"
Main header
Start | End | Length | Description |
---|---|---|---|
0x0000 | 0x0007 | 8 | Savegame ID |
0x0008 | 0x000B | 4 | size of banner (0x72A0 or 0xF0A0, also seen 0xBAA0) |
0x000C | 0x000C | 1 | permissions |
0x000D | 0x000D | 1 | ?? unknown |
0x000E | 0x001D | 16 | md5 of plaintext header with md5 blanker applied |
0x001E | 0x001F | 2 | ?? unknown |
Banner
Start | End | Length | Description |
---|---|---|---|
0x0020 | 0x0023 | 4 | magic ('WIBN') (Wii Banner?) |
0x0024 | 0x0027 | 4 | Flags - (Maskable) if set to 0x000001 the save cannot be copied from NAND via normal means, 0x000010 means to "Bounce" between 0 and the last frame. Setting it to 0x000000 makes the animation loop through all frames resetting to 0 on the final frame. |
0x0028 | 0x002A | 2 | AnimSpeed - Set per frame frameDelay*((animSpeed >> (2*nFrame))&3); 0 being no animation 1-3 being progressively slower, this is a little strange, but if the first two frames are set to 0, don't animate the icon. |
0x002B | 0x003F | 22 | Reserved |
0x0040 | 0x007F | 64 | Game title (big endian Unicode) |
0x0080 | 0x00BF | 64 | Game subtitle (big endian Unicode) |
0x00C0 | 0x60BF | 24576 | banner (192x64) - RGB5A3 GX texture format |
0x60C0 | 0x72BF | 4608 | icon0 (48x48) - RGB5A3 GX texture format |
0x72C0 | 0x84BF | 4608 | icon1 (optional, present if size of header is 0xF0C0) |
0x84C0 | 0x96BF | 4608 | icon2 (optional, present if size of header is 0xF0C0) |
0x96C0 | 0xA8BF | 4608 | icon3 (optional, present if size of header is 0xF0C0) |
0xA8C0 | 0xBABF | 4608 | icon4 (optional, present if size of header is 0xF0C0) |
0xBAC0 | 0xCCBF | 4608 | icon5 (optional, present if size of header is 0xF0C0) |
0xCCC0 | 0xDEBF | 4608 | icon6 (optional, present if size of header is 0xF0C0) |
0xDEC0 | 0xF0BF | 4608 | icon7 (optional, present if size of header is 0xF0C0) |
Bk ("BacKup") Header
The Bk Header is 0x70 bytes long (plus 0x10 bytes of padding/aligning). It is not encrypted.
Start | End | Length | Description |
---|---|---|---|
0x000 | 0x003 | 4 | Size of the header (0x00000070) |
0x004 | 0x005 | 2 | magic ('Bk') |
0x006 | 0x007 | 2 | magic2 or version (0x0001) |
0x008 | 0x00B | 4 | NG id |
0x00C | 0x00F | 4 | number of files |
0x010 | 0x013 | 4 | size of files |
0x014 | 0x017 | 4 | ?? unknown |
0x018 | 0x01B | 4 | ?? unknown |
0x01C | 0x01F | 4 | total size |
0x020 | 0x05F | 64 | ?? unknown |
0x060 | 0x063 | 4 | ?? unknown |
0x064 | 0x067 | 4 | Game ID (ex. 'RMGP' for Super Mario Galaxy) |
0x068 | 0x06D | 6 | Mac address of the wii |
0x06E | 0x06F | 2 | ?? unknown |
0x070 | 0x07F | 16 | null padded |
Files
A savegame consists of several files up to the number specified in the Bk Header. Each file is described using a File Header and a File Data section. Files are stored immediately after the Bk Header using the format described in the next sections.
File Header
The file header is 0x80 bytes long. It is not encrypted.
Start | End | Length | Description |
---|---|---|---|
0x000 | 0x003 | 4 | magic1 (0x03adf17e) |
0x004 | 0x007 | 4 | size of file |
0x008 | 0x008 | 1 | permissions |
0x009 | 0x009 | 1 | attributes |
0x00A | 0x00A | 1 | type (1=file, 2=directory) |
0x00B | variable | variable | name (null terminated) |
... | ... | ... | ... |
0x050 | 0x05F | 16 | IV for file data decryption |
0x060 | 0x07F | ... | ?? unknown |
File Data
File data comes after the File Header. Each file actually occupies the length specified in the file header rounded up to the next 64 byte boundary. Data is encrypted (AES128-CBC) using the "sd-key" and the initialization vector specified in the File Header.
Parsing savegames
Savegames can be decrypted and unpacked with segher's tachtig and created with his twintig.
Plaintext certificate chain area
For more information about each certificate layout, please refer to this page.
Start | End | Length | Description |
---|---|---|---|
0x000 | 0x17F | 0x180 | Copy of the console-specific device certificate (also known as NG certificate), returned by ES_GetDeviceCert.
|
0x180 | 0x2FF | 0x180 | Application-specific certificate (also known as AP certificate), dynamically generated during the data.bin file creation.
|
Both certificates hold a trimmed ECDSA signature and a trimmed 0x3C-byte long ECC public key. Both values must be padded with two leading \x00
before each coordinate in order to be able to use them as part of crypto functions.
The certificate name/identity from the AP
certificate is always set to AP0000000100000002
, because it's always generated by the System Menu.
The ECC public key from the AP
certificate is nothing more than an ECC shared secret generated using the random ECC private key from this very same certificate.
Finally, the ECDSA signature from the AP
certificate is issued by the NG
certificate, using the console-specific ECC private key (stored inside the OTP).