From 3dbrew
Revision as of 10:58, 2 April 2011 by Crediar (talk | contribs) (Added some info about the FS used in the EEPROM savefiles)
Jump to navigation Jump to search

On the 3DS savegames are stored much like on the DS, that is on an EEPROM in the gamecart. On the DS these savegames were stored in plaintext but on the 3DS a layer of encryption was added. This is highly likely a streamcipher, as the contents of several savegames exhibit the odd behaviour that xor-ing certain parts of the savegame together will result in the plaintext appearing.

The reason this works is because the streamcipher used has a period of 512 bytes. That is to say, it will repeat the same keystream after 512 bytes. The way you encrypt with a streamcipher is you XOR your data with the keystream as it is produced. Unfortunately, if your streamcipher repeats and you are encrypting a known plaintext (in our case, zeroes) you are basically giving away your valuable keystream.

So how do you use this to decrypt a savegame on a 3DS? First off, you chunk up the savegame into 512 byte chunks. Then, you bin these chunks by their contents, discarding any that contain only FF. Now look for the most common chunk. This is your keystream. Now XOR the keystream with your original savegame and you should have a fully decrypted savegame. XOR with the keystream again to produce an encrypted savegame.

Savefiles stored on the EEPROM are using a custom FS.

It is still unknown how to get correctly to the file table, but here is the file entry struct.

struct FileEntry {
    u32 Unknown;
    u8  FileName[0x10];
    u32 EntryID;
    u32 Unknown;
    u32 Unknown;
    u32 FileSize;
    u32 Unknown;
    u32 Unknown;
    u32 Unknown;