mirror of
https://github.com/rvtr/ctr_test_tools.git
synced 2025-06-19 00:55:31 -04:00
FalsifyTwlBackup:カテゴリ処理におけるマジックナンバーの排除、マルチコンテンツ対応
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_test_tools@30 6b0af911-cb57-b745-895f-eec5701120e1
This commit is contained in:
parent
f20e008a2d
commit
feaf55c5d1
@ -36,7 +36,7 @@ partial class Program
|
||||
break;
|
||||
|
||||
case 101:
|
||||
ReplaceImproperData(blocksForFalsifying[INDEX_BANNER].body, improperData);
|
||||
ReplaceImproperData(blocksForFalsifying[SECTION_BANNER].body, improperData);
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
@ -72,7 +72,7 @@ partial class Program
|
||||
break;
|
||||
|
||||
case 108:
|
||||
ReplaceImproperData(blocksForFalsifying[INDEX_TMD].body, improperData);
|
||||
ReplaceImproperData(blocksForFalsifying[SECTION_TMD].body, improperData);
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
@ -88,7 +88,7 @@ partial class Program
|
||||
break;
|
||||
|
||||
case 111:
|
||||
ReplaceImproperData(blocksForFalsifying[INDEX_CONTENT].body, improperData);
|
||||
ReplaceImproperData(blocksForFalsifying[SECTION_CONTENT].body, improperData);
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
@ -104,7 +104,7 @@ partial class Program
|
||||
break;
|
||||
|
||||
case 114:
|
||||
ReplaceImproperData(blocksForFalsifying[INDEX_PUBLIC_SAVE].body, improperData);
|
||||
ReplaceImproperData(blocksForFalsifying[SECTION_PUBLIC_SAVE].body, improperData);
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
@ -120,7 +120,7 @@ partial class Program
|
||||
break;
|
||||
|
||||
case 117:
|
||||
ReplaceImproperData(blocksForFalsifying[INDEX_SUB_BANNER].body, improperData);
|
||||
ReplaceImproperData(blocksForFalsifying[SECTION_SUB_BANNER].body, improperData);
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
@ -72,26 +72,30 @@ partial class Program
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// TMD の fileSize を変更
|
||||
case 207:
|
||||
header.fileSizes[0]++;
|
||||
header.fileSizes[(int)Utility.SectionIndex.TMD]++;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// コンテンツ[0] の fileSize を変更
|
||||
case 208:
|
||||
header.fileSizes[1]++;
|
||||
header.fileSizes[(int)Utility.SectionIndex.CONTENT]++;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize を変更
|
||||
case 209:
|
||||
header.fileSizes[2]++;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE]++;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// sub banner の fileSize を変更
|
||||
case 210:
|
||||
header.fileSizes[3]++;
|
||||
header.fileSizes[(int)Utility.SectionIndex.SUB_BANNER]++;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
@ -117,8 +121,9 @@ partial class Program
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize, TMD Reserved の publicSaveSize を変更
|
||||
case 214:
|
||||
header.fileSizes[2]++;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE]++;
|
||||
header.tmdReserved.publicSaveSize++;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
|
@ -42,50 +42,58 @@ partial class Program
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// TMD の fileSize を大きくした上で、コンテンツデータの前に不正なデータを入れる
|
||||
case 402:
|
||||
header.fileSizes[0] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.TMD] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_TMD, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// TMD の fileSize を大きくした上で、コンテンツデータの後ろに不正なデータを入れる
|
||||
case 403:
|
||||
header.fileSizes[0] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.TMD] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_TMD, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// コンテンツ[0] の fileSize を大きくした上で、コンテンツデータの前に不正なデータを入れる
|
||||
case 404:
|
||||
header.fileSizes[1] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.CONTENT] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_CONTENT, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// コンテンツ[0] の fileSize を大きくした上で、コンテンツデータの後ろに不正なデータを入れる
|
||||
case 405:
|
||||
header.fileSizes[1] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.CONTENT] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_CONTENT, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize を大きくした上で、public save の前に不正なデータを入れる
|
||||
case 406:
|
||||
header.fileSizes[2] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize を大きくした上で、public save の後ろに不正なデータを入れる
|
||||
case 407:
|
||||
header.fileSizes[2] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// サブバナーの fileSize を大きくした上で、サブバナーの前に不正なデータを入れる
|
||||
case 408:
|
||||
header.fileSizes[3] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.SUB_BANNER] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_SUB_BANNER, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// サブバナーの fileSize を大きくした上で、サブバナーの後ろに不正なデータを入れる
|
||||
case 409:
|
||||
header.fileSizes[3] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.SUB_BANNER] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_SUB_BANNER, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
@ -102,15 +110,17 @@ partial class Program
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize, TMD Reserved の publicSave を変更し、public save の前にデータを入れる
|
||||
case 412:
|
||||
header.fileSizes[2] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
|
||||
header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize, TMD Reserved の publicSave を変更し、public save の後ろにデータを入れる
|
||||
case 413:
|
||||
header.fileSizes[2] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
|
||||
header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
|
@ -42,50 +42,66 @@ partial class Program
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// TMD の fileSize を大きくした上で、コンテンツデータの前に不正なデータを入れる
|
||||
// TMD ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 502:
|
||||
header.fileSizes[0] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.TMD] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_TMD, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// TMD の fileSize を大きくした上で、コンテンツデータの後ろに不正なデータを入れる
|
||||
// TMD ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 503:
|
||||
header.fileSizes[0] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.TMD] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_TMD, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// コンテンツ[0] の fileSize を大きくした上で、コンテンツデータの前に不正なデータを入れる
|
||||
// コンテンツ[0] ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 504:
|
||||
header.fileSizes[1] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.CONTENT] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_CONTENT, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// コンテンツ[0] の fileSize を大きくした上で、コンテンツデータの後ろに不正なデータを入れる
|
||||
// コンテンツ[0] ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 505:
|
||||
header.fileSizes[1] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.CONTENT] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_CONTENT, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize を大きくした上で、public save の前に不正なデータを入れる
|
||||
// public save ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 506:
|
||||
header.fileSizes[2] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize を大きくした上で、public save の後ろに不正なデータを入れる
|
||||
// public save ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 507:
|
||||
header.fileSizes[2] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// サブバナーの fileSize を大きくした上で、サブバナーの前に不正なデータを入れる
|
||||
// サブバナーブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 508:
|
||||
header.fileSizes[3] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.SUB_BANNER] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_SUB_BANNER, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// サブバナーの fileSize を大きくした上で、サブバナーの後ろに不正なデータを入れる
|
||||
// サブバナーブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 509:
|
||||
header.fileSizes[3] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.SUB_BANNER] += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_SUB_BANNER, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
@ -102,15 +118,19 @@ partial class Program
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize, TMD Reserved の publicSave を変更し、public save の前にデータを入れる
|
||||
// public save ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 512:
|
||||
header.fileSizes[2] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
|
||||
header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
|
||||
// public save の fileSize, TMD Reserved の publicSave を変更し、public save の後ろにデータを入れる
|
||||
// public save ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
|
||||
case 513:
|
||||
header.fileSizes[2] += IMPROPER_DATA_SIZE;
|
||||
header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
|
||||
header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE;
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, CHG_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
|
@ -12,33 +12,35 @@ namespace FalsifyTwlBackup
|
||||
{
|
||||
partial class Program
|
||||
{
|
||||
// ブロックのインデックス
|
||||
private const int INDEX_BANNER = 0;
|
||||
private const int INDEX_HEADER = 1;
|
||||
private const int INDEX_SIGNATURE = 2;
|
||||
private const int INDEX_TMD = 3;
|
||||
private const int INDEX_CONTENT = 4;
|
||||
private const int INDEX_PUBLIC_SAVE = 5;
|
||||
private const int INDEX_SUB_BANNER = 6;
|
||||
private const int MAX_CONTENTS = 8;
|
||||
|
||||
// ブロックセクション
|
||||
private const int SECTION_BANNER = 0;
|
||||
private const int SECTION_HEADER = 1;
|
||||
private const int SECTION_SIGNATURE = 2;
|
||||
private const int SECTION_TMD = 3;
|
||||
private const int SECTION_CONTENT = 4;
|
||||
private const int SECTION_PUBLIC_SAVE = SECTION_CONTENT + MAX_CONTENTS;
|
||||
private const int SECTION_SUB_BANNER = SECTION_PUBLIC_SAVE + 1;
|
||||
|
||||
// データの挿入位置
|
||||
private const int NONE = -1;
|
||||
|
||||
private const int FRONT_BANNER = 10; // ブロック内データ本体の前
|
||||
private const int FRONT_HEADER = 11;
|
||||
private const int FRONT_SIGNATURE = 12;
|
||||
private const int FRONT_TMD = 13;
|
||||
private const int FRONT_CONTENT = 14;
|
||||
private const int FRONT_PUBLIC_SAVE = 15;
|
||||
private const int FRONT_SUB_BANNER = 16;
|
||||
private const int FRONT_BANNER = 100; // ブロック内データ本体の前
|
||||
private const int FRONT_HEADER = 101;
|
||||
private const int FRONT_SIGNATURE = 102;
|
||||
private const int FRONT_TMD = 103;
|
||||
private const int FRONT_CONTENT = 104;
|
||||
private const int FRONT_PUBLIC_SAVE = FRONT_CONTENT + MAX_CONTENTS;
|
||||
private const int FRONT_SUB_BANNER = FRONT_PUBLIC_SAVE + 1;
|
||||
|
||||
private const int REAR_BANNER = 20; // ブロック内データ本体の後
|
||||
private const int REAR_HEADER = 21;
|
||||
private const int REAR_SIGNATURE = 22;
|
||||
private const int REAR_TMD = 23;
|
||||
private const int REAR_CONTENT = 24;
|
||||
private const int REAR_PUBLIC_SAVE = 25;
|
||||
private const int REAR_SUB_BANNER = 26;
|
||||
private const int REAR_BANNER = 200; // ブロック内データ本体の後
|
||||
private const int REAR_HEADER = 201;
|
||||
private const int REAR_SIGNATURE = 202;
|
||||
private const int REAR_TMD = 203;
|
||||
private const int REAR_CONTENT = 204;
|
||||
private const int REAR_PUBLIC_SAVE = REAR_CONTENT + MAX_CONTENTS;
|
||||
private const int REAR_SUB_BANNER = REAR_PUBLIC_SAVE + 1;
|
||||
|
||||
private const int REAR_DATA = 99; // データ全体の後
|
||||
|
||||
@ -78,14 +80,13 @@ partial class Program
|
||||
private const int NC_MAC_AND_HASHSET = 0;
|
||||
private const int CHG_MAC_AND_HASHSET = 1;
|
||||
|
||||
private const int BLOCK_NUM = 7; // バックアップデータのブロックの個数
|
||||
private const int BLOCK_NUM = 14; // バックアップデータのブロックの個数
|
||||
private const int IMPROPER_DATA_SIZE = 16 * 1024; // 不正なデータのサイズ(16 KB)
|
||||
private const int KEY_SIZE = 16; // 鍵のサイズ(16 Byte)
|
||||
private const int HASH_SIZE = 32; // ハッシュのサイズ(32 Byte)
|
||||
private const int AES_BLOCK_SIZE = 16 * 8; // 暗号化のブロックサイズ(16Byte)
|
||||
private const string EXTENSION = ".bin"; // TwlBackupファイルの拡張子
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 使用方法を表示します。
|
||||
/// </summary>
|
||||
@ -265,45 +266,47 @@ partial class Program
|
||||
/// </summary>
|
||||
/// <param name="dataBlocks">変更対象となる署名ブロックを有するBlocks</param>
|
||||
/// <param name="hash">新しいハッシュ値</param>
|
||||
/// <param name="index">変更するブロックのインデックス</param>
|
||||
static void ChangeHashSet(Blocks dataBlocks, byte[] hash, int index)
|
||||
/// <param name="section">変更するブロックセクション</param>
|
||||
static void ChangeHashSet(Blocks dataBlocks, byte[] hash, int section)
|
||||
{
|
||||
Debug.Assert((index <= BLOCK_NUM - 1) && (index >= 0));
|
||||
Debug.Assert((section <= BLOCK_NUM - 1) && (section >= 0));
|
||||
|
||||
SignatureBody signature;
|
||||
signature = (SignatureBody)dataBlocks.signature.body;
|
||||
switch (index)
|
||||
if (SECTION_CONTENT <= section && section < SECTION_CONTENT + MAX_CONTENTS)
|
||||
{
|
||||
case INDEX_BANNER:
|
||||
hash.CopyTo(signature.digest.banner, 0);
|
||||
break;
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.CONTENT + section - SECTION_CONTENT], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case SECTION_BANNER:
|
||||
hash.CopyTo(signature.digest.banner, 0);
|
||||
break;
|
||||
|
||||
case INDEX_HEADER:
|
||||
hash.CopyTo(signature.digest.header, 0);
|
||||
break;
|
||||
case SECTION_HEADER:
|
||||
hash.CopyTo(signature.digest.header, 0);
|
||||
break;
|
||||
|
||||
case INDEX_TMD:
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.TMD], 0);
|
||||
break;
|
||||
case SECTION_TMD:
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.TMD], 0);
|
||||
break;
|
||||
|
||||
// TODO : マルチコンテンツ対応
|
||||
case INDEX_CONTENT:
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.CONTENT], 0);
|
||||
break;
|
||||
case SECTION_PUBLIC_SAVE:
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.PUBLIC_SAVE], 0);
|
||||
break;
|
||||
|
||||
case INDEX_PUBLIC_SAVE:
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.PUBLIC_SAVE], 0);
|
||||
break;
|
||||
case SECTION_SUB_BANNER:
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.SUB_BANNER], 0);
|
||||
break;
|
||||
|
||||
case INDEX_SUB_BANNER:
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.SUB_BANNER], 0);
|
||||
break;
|
||||
// TODO : Private Save 追加
|
||||
|
||||
// TODO : Private Save 追加
|
||||
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,33 +342,33 @@ partial class Program
|
||||
/// 必要に応じて不正データを挿入します。
|
||||
/// </summary>
|
||||
/// <param name="dataBlocks">暗号化するBlockを持つBlocks</param>
|
||||
/// <param name="index">暗号化するBlockのインデックス</param>
|
||||
/// <param name="section">暗号化するBlockのセクション</param>
|
||||
/// <param name="prop">バックアップデータに関するインスタンス</param>
|
||||
/// <param name="impData">挿入する不正データ</param>
|
||||
/// <param name="insertPos">挿入する位置</param>
|
||||
/// <param name="byteMac">格納するMAC</param>
|
||||
/// <param name="byteHash">MACを算出するためのハッシュ値</param>
|
||||
/// <returns>データ本体、MAC、IVを順に結合したbyte列</returns>
|
||||
static byte[] EncryptBlock(Blocks dataBlocks, int index, Properties prop, byte[] impData, int insertPos, byte[] byteMac, byte[] byteHash = null)
|
||||
static byte[] EncryptBlock(Blocks dataBlocks, int section, Properties prop, byte[] impData, int insertPos, byte[] byteMac, byte[] byteHash = null)
|
||||
{
|
||||
byte[] encryptedBlock = new byte[0];
|
||||
|
||||
// (データ本体の前に不正データ挿入)
|
||||
if (insertPos >= FRONT_BANNER && insertPos <= FRONT_SUB_BANNER)
|
||||
{
|
||||
if (index == insertPos - 10)
|
||||
if (section == insertPos - FRONT_BANNER)
|
||||
{
|
||||
encryptedBlock = MergeByteArray(encryptedBlock, impData);
|
||||
}
|
||||
}
|
||||
|
||||
// データ本体を暗号化
|
||||
encryptedBlock = MergeByteArray(encryptedBlock, dataBlocks[index].body.GetBytes()); // bodyを暗号化
|
||||
encryptedBlock = MergeByteArray(encryptedBlock, dataBlocks[section].body.GetBytes()); // bodyを暗号化
|
||||
|
||||
// (データ本体の後に不正データ挿入)
|
||||
if (insertPos >= REAR_BANNER && insertPos <= REAR_SUB_BANNER)
|
||||
{
|
||||
if (index == insertPos - 20)
|
||||
if (section == insertPos - REAR_BANNER)
|
||||
{
|
||||
encryptedBlock = MergeByteArray(encryptedBlock, impData);
|
||||
}
|
||||
@ -378,12 +381,12 @@ partial class Program
|
||||
byteMac = Utility.GetAesCmac(byteHash, prop.macKeyData); // SHA256ハッシュからMACを算出
|
||||
}
|
||||
|
||||
encryptedBlock = Utility.EncryptBody(encryptedBlock, prop.keyData, dataBlocks[index].iv); // データ本体を暗号化
|
||||
encryptedBlock = Utility.EncryptBody(encryptedBlock, prop.keyData, dataBlocks[section].iv); // データ本体を暗号化
|
||||
encryptedBlock = MergeByteArray(encryptedBlock, byteMac); // MACを結合
|
||||
encryptedBlock = MergeByteArray(encryptedBlock, dataBlocks[index].iv); // IVを結合
|
||||
encryptedBlock = MergeByteArray(encryptedBlock, dataBlocks[section].iv); // IVを結合
|
||||
|
||||
// (データブロックの後に不正データ挿入)
|
||||
if (index == INDEX_SUB_BANNER && insertPos == REAR_DATA)
|
||||
if (section == SECTION_SUB_BANNER && insertPos == REAR_DATA)
|
||||
{
|
||||
encryptedBlock = MergeByteArray(encryptedBlock, impData);
|
||||
}
|
||||
@ -417,16 +420,23 @@ partial class Program
|
||||
for (int i = 0; i < BLOCK_NUM; i++) // 署名部以外を暗号化&byte列に結合
|
||||
{
|
||||
byteHash[i] = new byte[HASH_SIZE];
|
||||
if (i != INDEX_SIGNATURE)
|
||||
if (i != SECTION_SIGNATURE)
|
||||
{
|
||||
encryptedBlocks[i] = EncryptBlock(dataBlocks, i, prop, impData, insertPos, byteMac[i], byteHash[i]); // ブロックを暗号化&結合
|
||||
ChangeHashSet(dataBlocks, byteHash[i], i); // ハッシュセットを更新
|
||||
if (dataBlocks[i].body != null)
|
||||
{
|
||||
encryptedBlocks[i] = EncryptBlock(dataBlocks, i, prop, impData, insertPos, byteMac[i], byteHash[i]); // ブロックを暗号化&結合
|
||||
ChangeHashSet(dataBlocks, byteHash[i], i); // ハッシュセットを更新
|
||||
}
|
||||
else
|
||||
{
|
||||
encryptedBlocks[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 最後に署名部を暗号化&byte列に結合
|
||||
byteHash[INDEX_SIGNATURE] = Utility.GetSha256(dataBlocks[INDEX_SIGNATURE].body.GetBytes()); // 平文からSHA256ハッシュ算出
|
||||
byteMac[INDEX_SIGNATURE] = Utility.GetAesCmac(byteHash[INDEX_SIGNATURE], prop.macKeyData); // SHA256ハッシュからMACを算出
|
||||
encryptedBlocks[INDEX_SIGNATURE] = EncryptBlock(dataBlocks, INDEX_SIGNATURE, prop, impData, insertPos, byteMac[INDEX_SIGNATURE]);
|
||||
byteHash[SECTION_SIGNATURE] = Utility.GetSha256(dataBlocks[SECTION_SIGNATURE].body.GetBytes()); // 平文からSHA256ハッシュ算出
|
||||
byteMac[SECTION_SIGNATURE] = Utility.GetAesCmac(byteHash[SECTION_SIGNATURE], prop.macKeyData); // SHA256ハッシュからMACを算出
|
||||
encryptedBlocks[SECTION_SIGNATURE] = EncryptBlock(dataBlocks, SECTION_SIGNATURE, prop, impData, insertPos, byteMac[SECTION_SIGNATURE]);
|
||||
}
|
||||
|
||||
// ( MAC & HASH SET更新しない場合 )
|
||||
@ -434,7 +444,14 @@ partial class Program
|
||||
{
|
||||
for (int i = 0; i < BLOCK_NUM; i++)
|
||||
{
|
||||
encryptedBlocks[i] = EncryptBlock(dataBlocks, i, prop, impData, insertPos, dataBlocks[i].mac); // ブロックを暗号化&結合
|
||||
if (dataBlocks[i].body != null)
|
||||
{
|
||||
encryptedBlocks[i] = EncryptBlock(dataBlocks, i, prop, impData, insertPos, dataBlocks[i].mac); // ブロックを暗号化&結合
|
||||
}
|
||||
else
|
||||
{
|
||||
encryptedBlocks[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,7 +459,10 @@ partial class Program
|
||||
// 暗号化した各ブロックを結合
|
||||
for (int i = 0; i < BLOCK_NUM; i++)
|
||||
{
|
||||
outData = MergeByteArray(outData, encryptedBlocks[i]);
|
||||
if (encryptedBlocks[i] != null)
|
||||
{
|
||||
outData = MergeByteArray(outData, encryptedBlocks[i]);
|
||||
}
|
||||
}
|
||||
return outData;
|
||||
}
|
||||
|
@ -8,13 +8,13 @@ namespace TwlBackupBlock
|
||||
/// </summary>
|
||||
public class Blocks : ICloneable
|
||||
{
|
||||
private const int NUM_BLOCKS = 7;
|
||||
private const int NUM_BLOCKS = 14;
|
||||
|
||||
public Block banner;
|
||||
public Block header;
|
||||
public Block signature;
|
||||
public Block tmd;
|
||||
public Block content;
|
||||
public Block[] content;
|
||||
public Block saveData;
|
||||
public Block subBanner;
|
||||
|
||||
@ -27,7 +27,11 @@ namespace TwlBackupBlock
|
||||
header = new Block();
|
||||
signature = new Block();
|
||||
tmd = new Block();
|
||||
content = new Block();
|
||||
content = new Block[HeaderBody.MAX_CONTENTS];
|
||||
for (int i = 0; i < HeaderBody.MAX_CONTENTS; i++)
|
||||
{
|
||||
content[i] = new Block();
|
||||
}
|
||||
saveData = new Block();
|
||||
subBanner = new Block();
|
||||
}
|
||||
@ -41,24 +45,30 @@ namespace TwlBackupBlock
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (index)
|
||||
if (4 <= index && index < 4 + HeaderBody.MAX_CONTENTS)
|
||||
{
|
||||
case 0: return banner;
|
||||
case 1: return header;
|
||||
case 2: return signature;
|
||||
case 3: return tmd;
|
||||
case 4: return content;
|
||||
case 5: return saveData;
|
||||
case 6: return subBanner;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
return null; // never reach
|
||||
return content[index - 4];
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return banner;
|
||||
case 1: return header;
|
||||
case 2: return signature;
|
||||
case 3: return tmd;
|
||||
case 12: return saveData;
|
||||
case 13: return subBanner;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
return null; // never reach
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ブロック数(=7)を取得します。
|
||||
/// ブロック数を取得します。
|
||||
/// </summary>
|
||||
public int Length
|
||||
{
|
||||
@ -79,7 +89,13 @@ namespace TwlBackupBlock
|
||||
newBlocks.header = (Block)header.Clone();
|
||||
newBlocks.signature = (Block)signature.Clone();
|
||||
newBlocks.tmd = (Block)tmd.Clone();
|
||||
newBlocks.content = (Block)content.Clone();
|
||||
for (int i = 0; i < HeaderBody.MAX_CONTENTS; i++)
|
||||
{
|
||||
if (content[i].body != null)
|
||||
{
|
||||
newBlocks.content[i] = (Block)content[i].Clone();
|
||||
}
|
||||
}
|
||||
newBlocks.saveData = (Block)saveData.Clone();
|
||||
newBlocks.subBanner = (Block)subBanner.Clone();
|
||||
return newBlocks;
|
||||
|
@ -86,15 +86,28 @@ namespace TwlBackupBlock
|
||||
|
||||
blocks.signature.body = new SignatureBody(DecryptBlock(br, SIGNATURE_SIZE, key, out blocks.signature.mac, out blocks.signature.iv));
|
||||
|
||||
// TORIAEZU
|
||||
// TODO : 複数コンテンツ対応
|
||||
// TODO : Legacy, WPS 対応
|
||||
int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD];
|
||||
int CONTENT_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT];
|
||||
int[] CONTENT_SIZE = new int[MAX_CONTENTS];
|
||||
for (int i = 0; i < MAX_CONTENTS; i++)
|
||||
{
|
||||
CONTENT_SIZE[i] = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT + i];
|
||||
}
|
||||
int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE];
|
||||
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER];
|
||||
|
||||
blocks.tmd.body = new Body(DecryptBlock(br, TMD_SIZE, key, out blocks.tmd.mac, out blocks.tmd.iv));
|
||||
blocks.content.body = new Body(DecryptBlock(br, CONTENT_SIZE, key, out blocks.content.mac, out blocks.content.iv));
|
||||
for (int i = 0; i < MAX_CONTENTS; i++)
|
||||
{
|
||||
if (CONTENT_SIZE[i] > 0)
|
||||
{
|
||||
blocks.content[i].body = new Body(DecryptBlock(br, CONTENT_SIZE[i], key, out blocks.content[i].mac, out blocks.content[i].iv));
|
||||
}
|
||||
else
|
||||
{
|
||||
blocks.content[i].body = null;
|
||||
}
|
||||
}
|
||||
blocks.saveData.body = new Body(DecryptBlock(br, PUBLIC_SAVE_SIZE, key, out blocks.saveData.mac, out blocks.saveData.iv));
|
||||
blocks.subBanner.body = new Body(DecryptBlock(br, SUB_BANNER_SIZE, key, out blocks.subBanner.mac, out blocks.subBanner.iv));
|
||||
|
||||
@ -402,13 +415,24 @@ namespace TwlBackupBlock
|
||||
|
||||
// TODO : 複数コンテンツ対応
|
||||
int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD];
|
||||
int CONTENT_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT];
|
||||
int[] CONTENT_SIZE = new int[MAX_CONTENTS];
|
||||
for (int i = 0; i < MAX_CONTENTS; i++)
|
||||
{
|
||||
CONTENT_SIZE[i] = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT + i];
|
||||
}
|
||||
int PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE];
|
||||
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER];
|
||||
|
||||
int restSize = RoundUp(TMD_SIZE, ROUND_SCALE) + RoundUp(CONTENT_SIZE, ROUND_SCALE) +
|
||||
int restSize = RoundUp(TMD_SIZE, ROUND_SCALE) +
|
||||
RoundUp(PUBLIC_SAVE_SIZE, ROUND_SCALE) + RoundUp(SUB_BANNER_SIZE, ROUND_SCALE) +
|
||||
AES_SIGN_HEADER_SIZE * 4;
|
||||
AES_SIGN_HEADER_SIZE * 3;
|
||||
for (int i = 0; i < MAX_CONTENTS; i++)
|
||||
{
|
||||
if (CONTENT_SIZE[i] > 0)
|
||||
{
|
||||
restSize += RoundUp(CONTENT_SIZE[i], ROUND_SCALE) + AES_SIGN_HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
if (data.Length - ms.Position != restSize)
|
||||
{
|
||||
Console.WriteLine("TMD、コンテンツ、publicセーブデータ、サブバナーブロックサイズが実際のサイズと一致しません");
|
||||
@ -425,16 +449,23 @@ namespace TwlBackupBlock
|
||||
Console.WriteLine("TMDブロックのハッシュが一致しません");
|
||||
return false;
|
||||
}
|
||||
blocks.content.body = new Body(DecryptBlock(br, CONTENT_SIZE, aesCbcKey, out blocks.content.mac, out blocks.content.iv));
|
||||
if (!CheckMac(blocks.content, aesCmacKey, blocks.content.mac))
|
||||
for (int i = 0; i < MAX_CONTENTS; i++)
|
||||
{
|
||||
Console.WriteLine("コンテンツブロックのMACが一致しません");
|
||||
return false;
|
||||
}
|
||||
if (!CheckHash(blocks.content, signatureBody.digest.section[(int)SectionIndex.CONTENT]))
|
||||
{
|
||||
Console.WriteLine("コンテンツブロックのハッシュが一致しません");
|
||||
return false;
|
||||
if (CONTENT_SIZE[i] > 0)
|
||||
{
|
||||
blocks.content[i].body =
|
||||
new Body(DecryptBlock(br, CONTENT_SIZE[i], aesCbcKey, out blocks.content[i].mac, out blocks.content[i].iv));
|
||||
if (!CheckMac(blocks.content[i], aesCmacKey, blocks.content[i].mac))
|
||||
{
|
||||
Console.WriteLine("コンテンツブロック[{0}]のMACが一致しません", i);
|
||||
return false;
|
||||
}
|
||||
if (!CheckHash(blocks.content[i], signatureBody.digest.section[(int)SectionIndex.CONTENT + i]))
|
||||
{
|
||||
Console.WriteLine("コンテンツブロック[{0}]のハッシュが一致しません", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
blocks.saveData.body = new Body(DecryptBlock(br, PUBLIC_SAVE_SIZE, aesCbcKey, out blocks.saveData.mac, out blocks.saveData.iv));
|
||||
if (!CheckMac(blocks.saveData, aesCmacKey, blocks.saveData.mac))
|
||||
|
Loading…
Reference in New Issue
Block a user