游戏存档: Difference between revisions
No edit summary |
translate eng.ver www.3dbrew.org/w/index.php?title=Savegames&oldid=7872 |
||
(2 intermediate revisions by the same user not shown) | |||
Line 9: | Line 9: | ||
那么怎么在3DS上运用这种解密方法呢?首先,将游戏存档切成以512字节为单位长度的片段,然后将除了只包含FF以外的片段以二进制方式查看。现在寻找最常见的公共片段,那就是你的关键字序列。现在用你原始的游戏存档和这些关键字序列进行异或操作,你将得到一个完全解密的游戏存档。对关键字序列进行异或操作以产生加密的游戏存档。(译者注:异或运算的一个重要性质是,a^b^b=a;即使用同样的关键字b对a进行两次异或将得到a本身,所以使用关键字序列对加密的游戏存档异或会得到明文,再异或一次又得到加密的存档。) | 那么怎么在3DS上运用这种解密方法呢?首先,将游戏存档切成以512字节为单位长度的片段,然后将除了只包含FF以外的片段以二进制方式查看。现在寻找最常见的公共片段,那就是你的关键字序列。现在用你原始的游戏存档和这些关键字序列进行异或操作,你将得到一个完全解密的游戏存档。对关键字序列进行异或操作以产生加密的游戏存档。(译者注:异或运算的一个重要性质是,a^b^b=a;即使用同样的关键字b对a进行两次异或将得到a本身,所以使用关键字序列对加密的游戏存档异或会得到明文,再异或一次又得到加密的存档。) | ||
==== Savegame keyY ==== | |||
[[ | 所有的游戏卡和SD卡存储的游戏都是用AES-CTR加密的. The base CTR for gamecard savegames is all-zero. The gamecard savegame [[AES|keyslot]] keyY is unique for every region of each game. The [[NCSD]] partition flags determine the method used to generate this keyY. When the save [[NCSD]] flags checked by the running NATIVE_FIRM are all-zero, the system will use the repeating CTR, otherwise a proper CTR which never repeats within the image is used. When all of the flags checked by the running NATIVE_FIRM are clear, the keyY is a 8-byte block decrypted from the main [[NCCH#CXI|CXI]] + two u32 IDs read from gamecard commands. | ||
===== Hashed keyY and [[2.2.0-4]] Savegame Encryption ===== | |||
[[NCSD]] partition的特定标志位被置位时,用CXI数据hash计算一个 SHA-256 (same data used with the original plain keyY), and the 0x40-bytes read from a gamecard command(this 0x40-byte data is also read by [[Process_Services_PXI|GetRomId]]). hash的前0x10-byte用做keyY。当标志位[7]被置位时,CTR不再使用原先的CTR方式使用,在存档镜像中不会使用重复数据。[[2.2.0-4]] 升级后,所有零售版有NCSD的游戏image都被发现在使用这种加密方式。 (含[[2.2.0-4]]以上的[[System Update CFA|System update partition]]), . | |||
' | This keyY generation method was implemented with [[2.0.0-2]] via NCSD partition flag[3], however the proper CTR wasn't implemented for flag[7] until [[2.2.0-4]]. The hashed keyY flag[3] implemented with [[2.0.0-2]] was likely never used with retail gamecards. | ||
===== [[6.0.0-11]] Savegame keyY ===== | |||
[[6.0.0-11]] implemented support for generating the savegame keyY with a new method, this method is much more complex than previous keyY methods. This is enabled via new [[NCSD]] partition flags, all retail games which have the NCSD image finalized after the [[6.0.0-11]] release(and [[6.0.0-11]]+ in the system update partition) will have these flags set for using this new method. | |||
A SHA-256 hash is calculated over the data used with the above hashed keyY method, other data is hashed here as well. An [[AES]] MAC is then calculated over this hash, the output MAC is used for the savegame keyY. | |||
The keyY used for calculating this AES MAC is initialized while NATIVE_FIRM is loading, this keyY is generated via the [[RSA]] engine. The RSA slot used here is slot0(key-data for slot0 is initialized by bootrom), this RSA slot0 key-data is overwritten once the system boots any [[NCCH#CXI|CXIs]] from NAND like [[NS]]. | |||
=== Wear leveling === | === Wear leveling === | ||
3DS在游戏存档闪存芯片上引入了wear leveling 方案。这是通过使用blockmap和journal来实现的。blockmap在闪存上偏移量为0,其后是journal。初始状态由blockmap指定,然后journal对其进行应用。 | 3DS在游戏存档闪存芯片上引入了wear leveling 方案。这是通过使用blockmap和journal来实现的。blockmap在闪存上偏移量为0,其后是journal。初始状态由blockmap指定,然后journal对其进行应用。 | ||
Line 68: | Line 70: | ||
magic 是一个固定值 0x080d6ce0. | magic 是一个固定值 0x080d6ce0. | ||
blockmap/ | blockmap/journal入口的验校和是这样算出的: | ||
* 每个 byte 是一个 0x200 大小加密的块的验校和 | * 每个 byte 是一个 0x200 大小加密的块的验校和 | ||
* 计算一个块的CRC16 (从 0xFFFF 开始) ,两个byte的CRC16一起进行异或运算,以产生 8bit 校验和 | * 计算一个块的CRC16 (从 0xFFFF 开始) ,两个byte的CRC16一起进行异或运算,以产生 8bit 校验和 | ||
Line 77: | Line 79: | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! | ! Image偏移 | ||
! | ! 长度 | ||
! | ! 说明 | ||
|- | |- | ||
| 0x00 | | 0x00 | ||
| 0x10 | | 0x10 | ||
| [[AES]] MAC | | 通过 0x20-byte SHA256 hash的[[AES]]MAC | ||
|- | |- | ||
| 0x10 | | 0x10 | ||
| 0xF0 | | 0xF0 | ||
| | | 填充0 | ||
|} | |} | ||
这个AES MAC是用于"签名" DISA/DIFF header的. 每次更新游戏存档,存储在DISA/DIFF的hash都会更新.每次更改存档时,必然更新MAC. SHA256_Update()用于使用下面的加密方式计算这个 hash . | |||
==== Savegame Types ==== | ==== Savegame Types ==== | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! | ! 类型 | ||
! | ! 说明 | ||
|- | |- | ||
| CTR-EXT0 | | CTR-EXT0 | ||
Line 105: | Line 107: | ||
|- | |- | ||
| CTR-NOR0 | | CTR-NOR0 | ||
| | | 卡带游戏存档 | ||
|- | |- | ||
| CTR-SAV0 | | CTR-SAV0 | ||
| | | 游戏存档 | ||
|- | |- | ||
| CTR-SIGN | | CTR-SIGN | ||
| | | SD卡游戏存档 | ||
|- | |- | ||
| CTR-9DB0 | | CTR-9DB0 | ||
Line 120: | Line 122: | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! | ! 块的长度 | ||
! | ! 说明 | ||
|- | |- | ||
| 0x8 | | 0x8 | ||
| | | 游戏存档类型 | ||
|- | |- | ||
| 0x8 | | 0x8 | ||
Line 317: | Line 319: | ||
* This is the [[extdata]] equivalent of DISA, for extdata which use FS. DIFF is only used for extdata. | * This is the [[extdata]] equivalent of DISA, for extdata which use FS. DIFF is only used for extdata. | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 347: | Line 347: | ||
| 0x20 | | 0x20 | ||
| 8 | | 8 | ||
| | | File Base Offset | ||
|- | |- | ||
| 0x28 | | 0x28 | ||
Line 355: | Line 355: | ||
| 0x30 | | 0x30 | ||
| 4 | | 4 | ||
| | | Active Partition Table (0 = Primary, 1 = Secondary) | ||
|- | |- | ||
| 0x34 | | 0x34 | ||
| 0x20 | | 0x20 | ||
| Hash of the | | Hash of the Active Partition Table | ||
|- | |- | ||
| 0x54 | | 0x54 | ||
Line 635: | Line 635: | ||
00002620: 00000000 00000000 00000000 00000000 ................ | 00002620: 00000000 00000000 00000000 00000000 ................ | ||
00002630: 01000000 73797374 656D2E64 61740000 ....system.dat.. | 00002630: 01000000 73797374 656D2E64 61740000 ....system.dat.. | ||
00002640: 00000000 00000000 D57B1100 02000000 ........ | 00002640: 00000000 00000000 D57B1100 02000000 ........?{...... | ||
00002650: 22000000 00000000 E8121500 00000000 ".......è....... | 00002650: 22000000 00000000 E8121500 00000000 ".......è....... | ||
00002660: 01000000 73617665 30302E62 696E0000 ....save00.bin.. | 00002660: 01000000 73617665 30302E62 696E0000 ....save00.bin.. | ||
00002670: 00000000 01000000 69921100 03000000 ........i’...... | 00002670: 00000000 01000000 69921100 03000000 ........i’...... | ||
00002680: DC140000 00000000 04000000 00000000 | 00002680: DC140000 00000000 04000000 00000000 ü............... | ||
</pre> | </pre> | ||
Line 674: | Line 674: | ||
| 0x24 | | 0x24 | ||
| 4 | | 4 | ||
| | | Media-size for the below sections | ||
|- | |- | ||
| 0x28 | | 0x28 | ||
Line 686: | Line 686: | ||
| 0x34 | | 0x34 | ||
| 4 | | 4 | ||
| FolderMap | | Unknown, FolderMap size-related | ||
|- | |- | ||
| 0x38 | | 0x38 | ||
Line 698: | Line 698: | ||
| 0x44 | | 0x44 | ||
| 4 | | 4 | ||
| FileMap | | Unknown, FileMap size-related | ||
|- | |- | ||
| 0x48 | | 0x48 | ||
Line 710: | Line 710: | ||
| 0x54 | | 0x54 | ||
| 4 | | 4 | ||
| BlockMap | | Uknown, BlockMap size-related | ||
|- | |- | ||
| 0x58 | | 0x58 | ||
Line 722: | Line 722: | ||
| 0x64 | | 0x64 | ||
| 4 | | 4 | ||
| File store | | Unknown, File store size-related | ||
|- | |- | ||
| 0x68 | | 0x68 | ||
Line 738: | Line 738: | ||
| 0x74 | | 0x74 | ||
| 4 | | 4 | ||
| Folders Table | | Unknown, Folders Table size-related | ||
|- | |- | ||
| 0x78 | | 0x78 | ||
Line 754: | Line 754: | ||
| 0x84 | | 0x84 | ||
| 4 | | 4 | ||
| Files Table | | Unknown, Files Table size-related | ||
|- | |- | ||
|} | |} | ||
Line 765: | Line 765: | ||
[[File:Sfsave_drawing.png]] | [[File:Sfsave_drawing.png]] | ||
=== | === 初始化 === | ||
当一个存储FLASH包含所有xFFFF块,它假定由游戏墨盒未初始化,初始化默认数据的地方,不提示用户的情况下。0xFFFFFFFF的块未初始化的数据。当创建一个非游戏卡的秘技和其他图像/文件,它的最初所有0xFFFFFFFF的,直到它的一些块格式化,加密数据覆盖。 | |||
When a save FLASH contains all xFFFF blocks it's assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. The 0xFFFFFFFF blocks are uninitialized data. When creating a non-gamecard savegame and other images/files, it's initially all 0xFFFFFFFF until it's formatted where some of the blocks are overwritten with encrypted data. | When a save FLASH contains all xFFFF blocks it's assumed uninitialized by the game cartridges and it initializes default data in place, without prompting the user. The 0xFFFFFFFF blocks are uninitialized data. When creating a non-gamecard savegame and other images/files, it's initially all 0xFFFFFFFF until it's formatted where some of the blocks are overwritten with encrypted data. | ||
我得到了一个新的游戏 SplinterCell3D-Pal ,它的128KB存档除去开头的0x10 byte是‘Z’(大写),其余都为0xFF --[[User:Elisherer|Elisherer]] 22:41 2011年10月15日(CEST) | |||
=== 事实 === | |||
如果你发现二进制文件的一些事实把它们分享到这里: | |||
=== | * 从一个存档到这个游戏在这个分区的另一个游戏备份,后者全部image的头部变为随机位置.. --[[User:Elisherer|Elisherer]] 22:41 2011年10月15日(CEST) | ||
从一个“随机”位置在分区和整个图像头的最后一个文件,保存到另一个游戏备份.. | |||
=== 工具 === | |||
* [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] | * [https://github.com/3dshax/3ds/tree/master/3dsfuse 3dsfuse] 支持读写游戏存档。在mount的FUSE文件系统中,/output.sav是raw FLASH save-image。When the save was modified, a separate tool to update the MAC must be used with /clean.sav, prior to writing output.sav to a gamecard. | ||
* [[3DSExplorer]] supports reading of savegames, it doesn't support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented). | * [[3DSExplorer]] supports reading of savegames, it doesn't support reading the new encrypted savegames and maybe in the future it will support modifying (some of the modyfing code is already implemented). | ||
[[セーブデータ|Japanese]] | [[セーブデータ|Japanese]] |