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:
n2460 2011-10-22 07:47:10 +00:00
parent f20e008a2d
commit feaf55c5d1
7 changed files with 232 additions and 130 deletions

View File

@ -36,7 +36,7 @@ partial class Program
break; break;
case 101: case 101:
ReplaceImproperData(blocksForFalsifying[INDEX_BANNER].body, improperData); ReplaceImproperData(blocksForFalsifying[SECTION_BANNER].body, improperData);
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
@ -72,7 +72,7 @@ partial class Program
break; break;
case 108: case 108:
ReplaceImproperData(blocksForFalsifying[INDEX_TMD].body, improperData); ReplaceImproperData(blocksForFalsifying[SECTION_TMD].body, improperData);
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
@ -88,7 +88,7 @@ partial class Program
break; break;
case 111: case 111:
ReplaceImproperData(blocksForFalsifying[INDEX_CONTENT].body, improperData); ReplaceImproperData(blocksForFalsifying[SECTION_CONTENT].body, improperData);
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
@ -104,7 +104,7 @@ partial class Program
break; break;
case 114: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
@ -120,7 +120,7 @@ partial class Program
break; break;
case 117: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;

View File

@ -72,26 +72,30 @@ partial class Program
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// TMD の fileSize を変更
case 207: case 207:
header.fileSizes[0]++; header.fileSizes[(int)Utility.SectionIndex.TMD]++;
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// コンテンツ[0] の fileSize を変更
case 208: case 208:
header.fileSizes[1]++; header.fileSizes[(int)Utility.SectionIndex.CONTENT]++;
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize を変更
case 209: case 209:
header.fileSizes[2]++; header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE]++;
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// sub banner の fileSize を変更
case 210: case 210:
header.fileSizes[3]++; header.fileSizes[(int)Utility.SectionIndex.SUB_BANNER]++;
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
@ -117,8 +121,9 @@ partial class Program
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize, TMD Reserved の publicSaveSize を変更
case 214: case 214:
header.fileSizes[2]++; header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE]++;
header.tmdReserved.publicSaveSize++; header.tmdReserved.publicSaveSize++;
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);

View File

@ -42,50 +42,58 @@ partial class Program
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// TMD の fileSize を大きくした上で、コンテンツデータの前に不正なデータを入れる
case 402: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_TMD, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// TMD の fileSize を大きくした上で、コンテンツデータの後ろに不正なデータを入れる
case 403: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_TMD, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// コンテンツ[0] の fileSize を大きくした上で、コンテンツデータの前に不正なデータを入れる
case 404: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_CONTENT, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// コンテンツ[0] の fileSize を大きくした上で、コンテンツデータの後ろに不正なデータを入れる
case 405: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_CONTENT, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize を大きくした上で、public save の前に不正なデータを入れる
case 406: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize を大きくした上で、public save の後ろに不正なデータを入れる
case 407: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// サブバナーの fileSize を大きくした上で、サブバナーの前に不正なデータを入れる
case 408: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_SUB_BANNER, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// サブバナーの fileSize を大きくした上で、サブバナーの後ろに不正なデータを入れる
case 409: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_SUB_BANNER, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
@ -102,15 +110,17 @@ partial class Program
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize, TMD Reserved の publicSave を変更し、public save の前にデータを入れる
case 412: case 412:
header.fileSizes[2] += IMPROPER_DATA_SIZE; header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE; header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE;
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize, TMD Reserved の publicSave を変更し、public save の後ろにデータを入れる
case 413: case 413:
header.fileSizes[2] += IMPROPER_DATA_SIZE; header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE; header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE;
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, NC_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, NC_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);

View File

@ -42,50 +42,66 @@ partial class Program
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// TMD の fileSize を大きくした上で、コンテンツデータの前に不正なデータを入れる
// TMD ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 502: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_TMD, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// TMD の fileSize を大きくした上で、コンテンツデータの後ろに不正なデータを入れる
// TMD ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 503: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_TMD, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// コンテンツ[0] の fileSize を大きくした上で、コンテンツデータの前に不正なデータを入れる
// コンテンツ[0] ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 504: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_CONTENT, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// コンテンツ[0] の fileSize を大きくした上で、コンテンツデータの後ろに不正なデータを入れる
// コンテンツ[0] ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 505: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_CONTENT, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize を大きくした上で、public save の前に不正なデータを入れる
// public save ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 506: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize を大きくした上で、public save の後ろに不正なデータを入れる
// public save ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 507: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// サブバナーの fileSize を大きくした上で、サブバナーの前に不正なデータを入れる
// サブバナーブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 508: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_SUB_BANNER, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// サブバナーの fileSize を大きくした上で、サブバナーの後ろに不正なデータを入れる
// サブバナーブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 509: 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); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_SUB_BANNER, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
@ -102,15 +118,19 @@ partial class Program
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize, TMD Reserved の publicSave を変更し、public save の前にデータを入れる
// public save ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 512: case 512:
header.fileSizes[2] += IMPROPER_DATA_SIZE; header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE; header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE;
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, CHG_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, FRONT_PUBLIC_SAVE, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
break; break;
// public save の fileSize, TMD Reserved の publicSave を変更し、public save の後ろにデータを入れる
// public save ブロックの MAC を更新し、署名ブロック内ハッシュも更新する
case 513: case 513:
header.fileSizes[2] += IMPROPER_DATA_SIZE; header.fileSizes[(int)Utility.SectionIndex.PUBLIC_SAVE] += IMPROPER_DATA_SIZE;
header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE; header.tmdReserved.publicSaveSize += IMPROPER_DATA_SIZE;
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, CHG_MAC_AND_HASHSET); outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, REAR_PUBLIC_SAVE, CHG_MAC_AND_HASHSET);
OutputFalsifiedData(improperNo, prop.outFolderPath, outData); OutputFalsifiedData(improperNo, prop.outFolderPath, outData);

View File

@ -12,33 +12,35 @@ namespace FalsifyTwlBackup
{ {
partial class Program partial class Program
{ {
// ブロックのインデックス private const int MAX_CONTENTS = 8;
private const int INDEX_BANNER = 0;
private const int INDEX_HEADER = 1; // ブロックセクション
private const int INDEX_SIGNATURE = 2; private const int SECTION_BANNER = 0;
private const int INDEX_TMD = 3; private const int SECTION_HEADER = 1;
private const int INDEX_CONTENT = 4; private const int SECTION_SIGNATURE = 2;
private const int INDEX_PUBLIC_SAVE = 5; private const int SECTION_TMD = 3;
private const int INDEX_SUB_BANNER = 6; 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 NONE = -1;
private const int FRONT_BANNER = 10; // ブロック内データ本体の前 private const int FRONT_BANNER = 100; // ブロック内データ本体の前
private const int FRONT_HEADER = 11; private const int FRONT_HEADER = 101;
private const int FRONT_SIGNATURE = 12; private const int FRONT_SIGNATURE = 102;
private const int FRONT_TMD = 13; private const int FRONT_TMD = 103;
private const int FRONT_CONTENT = 14; private const int FRONT_CONTENT = 104;
private const int FRONT_PUBLIC_SAVE = 15; private const int FRONT_PUBLIC_SAVE = FRONT_CONTENT + MAX_CONTENTS;
private const int FRONT_SUB_BANNER = 16; private const int FRONT_SUB_BANNER = FRONT_PUBLIC_SAVE + 1;
private const int REAR_BANNER = 20; // ブロック内データ本体の後 private const int REAR_BANNER = 200; // ブロック内データ本体の後
private const int REAR_HEADER = 21; private const int REAR_HEADER = 201;
private const int REAR_SIGNATURE = 22; private const int REAR_SIGNATURE = 202;
private const int REAR_TMD = 23; private const int REAR_TMD = 203;
private const int REAR_CONTENT = 24; private const int REAR_CONTENT = 204;
private const int REAR_PUBLIC_SAVE = 25; private const int REAR_PUBLIC_SAVE = REAR_CONTENT + MAX_CONTENTS;
private const int REAR_SUB_BANNER = 26; private const int REAR_SUB_BANNER = REAR_PUBLIC_SAVE + 1;
private const int REAR_DATA = 99; // データ全体の後 private const int REAR_DATA = 99; // データ全体の後
@ -78,14 +80,13 @@ partial class Program
private const int NC_MAC_AND_HASHSET = 0; private const int NC_MAC_AND_HASHSET = 0;
private const int CHG_MAC_AND_HASHSET = 1; 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 IMPROPER_DATA_SIZE = 16 * 1024; // 不正なデータのサイズ(16 KB)
private const int KEY_SIZE = 16; // 鍵のサイズ(16 Byte) private const int KEY_SIZE = 16; // 鍵のサイズ(16 Byte)
private const int HASH_SIZE = 32; // ハッシュのサイズ(32 Byte) private const int HASH_SIZE = 32; // ハッシュのサイズ(32 Byte)
private const int AES_BLOCK_SIZE = 16 * 8; // 暗号化のブロックサイズ(16Byte) private const int AES_BLOCK_SIZE = 16 * 8; // 暗号化のブロックサイズ(16Byte)
private const string EXTENSION = ".bin"; // TwlBackupファイルの拡張子 private const string EXTENSION = ".bin"; // TwlBackupファイルの拡張子
/// <summary> /// <summary>
/// 使用方法を表示します。 /// 使用方法を表示します。
/// </summary> /// </summary>
@ -265,37 +266,38 @@ partial class Program
/// </summary> /// </summary>
/// <param name="dataBlocks">変更対象となる署名ブロックを有するBlocks</param> /// <param name="dataBlocks">変更対象となる署名ブロックを有するBlocks</param>
/// <param name="hash">新しいハッシュ値</param> /// <param name="hash">新しいハッシュ値</param>
/// <param name="index">変更するブロックのインデックス</param> /// <param name="section">変更するブロックセクション</param>
static void ChangeHashSet(Blocks dataBlocks, byte[] hash, int index) 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; SignatureBody signature;
signature = (SignatureBody)dataBlocks.signature.body; signature = (SignatureBody)dataBlocks.signature.body;
switch (index) if (SECTION_CONTENT <= section && section < SECTION_CONTENT + MAX_CONTENTS)
{ {
case INDEX_BANNER: 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); hash.CopyTo(signature.digest.banner, 0);
break; break;
case INDEX_HEADER: case SECTION_HEADER:
hash.CopyTo(signature.digest.header, 0); hash.CopyTo(signature.digest.header, 0);
break; break;
case INDEX_TMD: case SECTION_TMD:
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.TMD], 0); hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.TMD], 0);
break; break;
// TODO : マルチコンテンツ対応 case SECTION_PUBLIC_SAVE:
case INDEX_CONTENT:
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.CONTENT], 0);
break;
case INDEX_PUBLIC_SAVE:
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.PUBLIC_SAVE], 0); hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.PUBLIC_SAVE], 0);
break; break;
case INDEX_SUB_BANNER: case SECTION_SUB_BANNER:
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.SUB_BANNER], 0); hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.SUB_BANNER], 0);
break; break;
@ -306,6 +308,7 @@ partial class Program
break; break;
} }
} }
}
/// <summary> /// <summary>
@ -339,33 +342,33 @@ partial class Program
/// 必要に応じて不正データを挿入します。 /// 必要に応じて不正データを挿入します。
/// </summary> /// </summary>
/// <param name="dataBlocks">暗号化するBlockを持つBlocks</param> /// <param name="dataBlocks">暗号化するBlockを持つBlocks</param>
/// <param name="index">暗号化するBlockのインデックス</param> /// <param name="section">暗号化するBlockのセクション</param>
/// <param name="prop">バックアップデータに関するインスタンス</param> /// <param name="prop">バックアップデータに関するインスタンス</param>
/// <param name="impData">挿入する不正データ</param> /// <param name="impData">挿入する不正データ</param>
/// <param name="insertPos">挿入する位置</param> /// <param name="insertPos">挿入する位置</param>
/// <param name="byteMac">格納するMAC</param> /// <param name="byteMac">格納するMAC</param>
/// <param name="byteHash">MACを算出するためのハッシュ値</param> /// <param name="byteHash">MACを算出するためのハッシュ値</param>
/// <returns>データ本体、MAC、IVを順に結合したbyte列</returns> /// <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]; byte[] encryptedBlock = new byte[0];
// (データ本体の前に不正データ挿入) // (データ本体の前に不正データ挿入)
if (insertPos >= FRONT_BANNER && insertPos <= FRONT_SUB_BANNER) if (insertPos >= FRONT_BANNER && insertPos <= FRONT_SUB_BANNER)
{ {
if (index == insertPos - 10) if (section == insertPos - FRONT_BANNER)
{ {
encryptedBlock = MergeByteArray(encryptedBlock, impData); 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 (insertPos >= REAR_BANNER && insertPos <= REAR_SUB_BANNER)
{ {
if (index == insertPos - 20) if (section == insertPos - REAR_BANNER)
{ {
encryptedBlock = MergeByteArray(encryptedBlock, impData); encryptedBlock = MergeByteArray(encryptedBlock, impData);
} }
@ -378,12 +381,12 @@ partial class Program
byteMac = Utility.GetAesCmac(byteHash, prop.macKeyData); // SHA256ハッシュからMACを算出 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, 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); encryptedBlock = MergeByteArray(encryptedBlock, impData);
} }
@ -417,33 +420,50 @@ partial class Program
for (int i = 0; i < BLOCK_NUM; i++) // 署名部以外を暗号化byte列に結合 for (int i = 0; i < BLOCK_NUM; i++) // 署名部以外を暗号化byte列に結合
{ {
byteHash[i] = new byte[HASH_SIZE]; byteHash[i] = new byte[HASH_SIZE];
if (i != INDEX_SIGNATURE) if (i != SECTION_SIGNATURE)
{
if (dataBlocks[i].body != null)
{ {
encryptedBlocks[i] = EncryptBlock(dataBlocks, i, prop, impData, insertPos, byteMac[i], byteHash[i]); // ブロックを暗号化&結合 encryptedBlocks[i] = EncryptBlock(dataBlocks, i, prop, impData, insertPos, byteMac[i], byteHash[i]); // ブロックを暗号化&結合
ChangeHashSet(dataBlocks, byteHash[i], i); // ハッシュセットを更新 ChangeHashSet(dataBlocks, byteHash[i], i); // ハッシュセットを更新
} }
else
{
encryptedBlocks[i] = null;
}
}
} }
// 最後に署名部を暗号化byte列に結合 // 最後に署名部を暗号化byte列に結合
byteHash[INDEX_SIGNATURE] = Utility.GetSha256(dataBlocks[INDEX_SIGNATURE].body.GetBytes()); // 平文からSHA256ハッシュ算出 byteHash[SECTION_SIGNATURE] = Utility.GetSha256(dataBlocks[SECTION_SIGNATURE].body.GetBytes()); // 平文からSHA256ハッシュ算出
byteMac[INDEX_SIGNATURE] = Utility.GetAesCmac(byteHash[INDEX_SIGNATURE], prop.macKeyData); // SHA256ハッシュからMACを算出 byteMac[SECTION_SIGNATURE] = Utility.GetAesCmac(byteHash[SECTION_SIGNATURE], prop.macKeyData); // SHA256ハッシュからMACを算出
encryptedBlocks[INDEX_SIGNATURE] = EncryptBlock(dataBlocks, INDEX_SIGNATURE, prop, impData, insertPos, byteMac[INDEX_SIGNATURE]); encryptedBlocks[SECTION_SIGNATURE] = EncryptBlock(dataBlocks, SECTION_SIGNATURE, prop, impData, insertPos, byteMac[SECTION_SIGNATURE]);
} }
// ( MAC & HASH SET更新しない場合 ) // ( MAC & HASH SET更新しない場合 )
else else
{ {
for (int i = 0; i < BLOCK_NUM; i++) for (int i = 0; i < BLOCK_NUM; i++)
{
if (dataBlocks[i].body != null)
{ {
encryptedBlocks[i] = EncryptBlock(dataBlocks, i, prop, impData, insertPos, dataBlocks[i].mac); // ブロックを暗号化&結合 encryptedBlocks[i] = EncryptBlock(dataBlocks, i, prop, impData, insertPos, dataBlocks[i].mac); // ブロックを暗号化&結合
} }
else
{
encryptedBlocks[i] = null;
}
}
} }
//---------------------- //----------------------
// 暗号化した各ブロックを結合 // 暗号化した各ブロックを結合
for (int i = 0; i < BLOCK_NUM; i++) for (int i = 0; i < BLOCK_NUM; i++)
{
if (encryptedBlocks[i] != null)
{ {
outData = MergeByteArray(outData, encryptedBlocks[i]); outData = MergeByteArray(outData, encryptedBlocks[i]);
} }
}
return outData; return outData;
} }

View File

@ -8,13 +8,13 @@ namespace TwlBackupBlock
/// </summary> /// </summary>
public class Blocks : ICloneable public class Blocks : ICloneable
{ {
private const int NUM_BLOCKS = 7; private const int NUM_BLOCKS = 14;
public Block banner; public Block banner;
public Block header; public Block header;
public Block signature; public Block signature;
public Block tmd; public Block tmd;
public Block content; public Block[] content;
public Block saveData; public Block saveData;
public Block subBanner; public Block subBanner;
@ -27,7 +27,11 @@ namespace TwlBackupBlock
header = new Block(); header = new Block();
signature = new Block(); signature = new Block();
tmd = 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(); saveData = new Block();
subBanner = new Block(); subBanner = new Block();
} }
@ -40,6 +44,12 @@ namespace TwlBackupBlock
public Block this[int index] public Block this[int index]
{ {
get get
{
if (4 <= index && index < 4 + HeaderBody.MAX_CONTENTS)
{
return content[index - 4];
}
else
{ {
switch (index) switch (index)
{ {
@ -47,18 +57,18 @@ namespace TwlBackupBlock
case 1: return header; case 1: return header;
case 2: return signature; case 2: return signature;
case 3: return tmd; case 3: return tmd;
case 4: return content; case 12: return saveData;
case 5: return saveData; case 13: return subBanner;
case 6: return subBanner;
default: default:
Debug.Assert(false); Debug.Assert(false);
return null; // never reach return null; // never reach
} }
} }
} }
}
/// <summary> /// <summary>
/// ブロック数=7を取得します。 /// ブロック数を取得します。
/// </summary> /// </summary>
public int Length public int Length
{ {
@ -79,7 +89,13 @@ namespace TwlBackupBlock
newBlocks.header = (Block)header.Clone(); newBlocks.header = (Block)header.Clone();
newBlocks.signature = (Block)signature.Clone(); newBlocks.signature = (Block)signature.Clone();
newBlocks.tmd = (Block)tmd.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.saveData = (Block)saveData.Clone();
newBlocks.subBanner = (Block)subBanner.Clone(); newBlocks.subBanner = (Block)subBanner.Clone();
return newBlocks; return newBlocks;

View File

@ -86,15 +86,28 @@ namespace TwlBackupBlock
blocks.signature.body = new SignatureBody(DecryptBlock(br, SIGNATURE_SIZE, key, out blocks.signature.mac, out blocks.signature.iv)); blocks.signature.body = new SignatureBody(DecryptBlock(br, SIGNATURE_SIZE, key, out blocks.signature.mac, out blocks.signature.iv));
// TORIAEZU // TODO : Legacy, WPS 対応
// TODO : 複数コンテンツ対応
int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD]; 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 PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE];
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER]; 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.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.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)); 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 : 複数コンテンツ対応 // TODO : 複数コンテンツ対応
int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD]; 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 PUBLIC_SAVE_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.PUBLIC_SAVE];
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.SUB_BANNER]; 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) + 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) if (data.Length - ms.Position != restSize)
{ {
Console.WriteLine("TMD、コンテンツ、publicセーブデータ、サブバナーブロックサイズが実際のサイズと一致しません"); Console.WriteLine("TMD、コンテンツ、publicセーブデータ、サブバナーブロックサイズが実際のサイズと一致しません");
@ -425,17 +449,24 @@ namespace TwlBackupBlock
Console.WriteLine("TMDブロックのハッシュが一致しません"); Console.WriteLine("TMDブロックのハッシュが一致しません");
return false; return false;
} }
blocks.content.body = new Body(DecryptBlock(br, CONTENT_SIZE, aesCbcKey, out blocks.content.mac, out blocks.content.iv)); for (int i = 0; i < MAX_CONTENTS; i++)
if (!CheckMac(blocks.content, aesCmacKey, blocks.content.mac))
{ {
Console.WriteLine("コンテンツブロックのMACが一致しません"); 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; return false;
} }
if (!CheckHash(blocks.content, signatureBody.digest.section[(int)SectionIndex.CONTENT])) if (!CheckHash(blocks.content[i], signatureBody.digest.section[(int)SectionIndex.CONTENT + i]))
{ {
Console.WriteLine("コンテンツブロックのハッシュが一致しません"); Console.WriteLine("コンテンツブロック[{0}]のハッシュが一致しません", i);
return false; return false;
} }
}
}
blocks.saveData.body = new Body(DecryptBlock(br, PUBLIC_SAVE_SIZE, aesCbcKey, out blocks.saveData.mac, out blocks.saveData.iv)); 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)) if (!CheckMac(blocks.saveData, aesCmacKey, blocks.saveData.mac))
{ {