Difference between revisions of "セーブデータ"

From 3dbrew
Jump to navigation Jump to search
Line 4: Line 4:
 
DSではこのようなセーブデータはそのまま保存されていましたが、3DSにおいては暗号化して保存する仕組みが加わりました。
 
DSではこのようなセーブデータはそのまま保存されていましたが、3DSにおいては暗号化して保存する仕組みが加わりました。
 
これはとてもストリームの暗号化に似ています。排他的論理和を取ることによって、セーブデータの復号鍵が
 
これはとてもストリームの暗号化に似ています。排他的論理和を取ることによって、セーブデータの復号鍵が
得られます。 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.
+
得られます。                                           このアルゴリズムを解読できるのは、たった512バイトのキーによって暗号化されているためです。言ってみれば、512バイトごとに同じように復号しているわけです。つまり、暗号化されても、その排他的論理和を取る事によってキーを作ることができます。残念ながら、 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.
 
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.
Line 34: Line 34:
 
=== ファイルシステム ===
 
=== ファイルシステム ===
 
   
 
   
Savefiles stored on the FLASH are using a custom FS.
+
セーブデータstored on the FLASH are using a custom FS.
 
   
 
   
 
It seems the file entries are stored at a static offset of 0x3a00.  
 
It seems the file entries are stored at a static offset of 0x3a00.  

Revision as of 14:42, 9 April 2011

暗号化方式

3DSのセーブデータはゲームカートにまさにDSのそれと同じように保存されています。 DSではこのようなセーブデータはそのまま保存されていましたが、3DSにおいては暗号化して保存する仕組みが加わりました。 これはとてもストリームの暗号化に似ています。排他的論理和を取ることによって、セーブデータの復号鍵が 得られます。                                           このアルゴリズムを解読できるのは、たった512バイトのキーによって暗号化されているためです。言ってみれば、512バイトごとに同じように復号しているわけです。つまり、暗号化されても、その排他的論理和を取る事によってキーを作ることができます。残念ながら、 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.

Wearleveling

The 3DS employs a wearleveling scheme on the savegame FLASH chips. This is done trough blockmaps. Depending on the size of the flashchip, these are located somewhere at the beginning of the flashchip, in the first sector. The structure is as follows:

struct sector_entry {
        uint8_t virt_sec;       // Mapped to sector
        uint8_t prev_virt_sec;  // Physical sector previously mapped to
        uint8_t phys_sec;       // Mapped from sector
        uint8_t prev_phys_sec;  // Virtual sector previously mapped to
        uint8_t virt_realloc_cnt;// Amount of times virtual sector has been remapped
        uint8_t phys_realloc_cnt;// Amount of times physical sector has been remapped
        uint8_t chksums[8];
} __attribute__((packed));

struct long_sector_entry {
        struct sector_entry sector;
        struct sector_entry dupe;
        uint32_t magic;
};

With magic being a constant 0x080d6ce0.

ファイルシステム

セーブデータstored on the FLASH are using a custom FS.

It seems the file entries are stored at a static offset of 0x3a00.

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