mirror of
https://github.com/rvtr/ctr_test_tools.git
synced 2025-06-19 09:05:31 -04:00
TwlBkpCheck/Windows:ヘッダ情報の更新(今までのは Legacy としてクラス分け)
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_test_tools@27 6b0af911-cb57-b745-895f-eec5701120e1
This commit is contained in:
parent
82f3c9c94c
commit
f26671db85
@ -49,6 +49,7 @@ namespace FalsifyTwlBackup
|
||||
private const int CAT300 = 3;
|
||||
private const int CAT400 = 4;
|
||||
private const int CAT500 = 5;
|
||||
private const int VERIFY = 9; // TORIAEZU : 上記が Mode == Pattern なのが引っかかる・・・
|
||||
|
||||
// 各カテゴリでの最大番号
|
||||
private const int MAX_OF_CAT100 = 118;
|
||||
@ -92,6 +93,7 @@ namespace FalsifyTwlBackup
|
||||
Console.WriteLine(" ex) -cat 100 -> falsifying 100,101,102....");
|
||||
Console.WriteLine(" -each PAT_NUM : output PAT_NUM pattern");
|
||||
Console.WriteLine(" ex) -each 204 -> falsifying 204 only");
|
||||
Console.WriteLine(" -verify : verify backup file");
|
||||
Environment.Exit(-1);
|
||||
}
|
||||
|
||||
@ -178,7 +180,14 @@ namespace FalsifyTwlBackup
|
||||
return Convert.ToInt16(args[4]);
|
||||
}
|
||||
}
|
||||
|
||||
// -verify
|
||||
else if (args[3].ToUpper().TrimStart('-') == "VERIFY")
|
||||
{
|
||||
return VERIFY;
|
||||
}
|
||||
}
|
||||
|
||||
// それ以外
|
||||
return ALL;
|
||||
}
|
||||
@ -265,12 +274,24 @@ namespace FalsifyTwlBackup
|
||||
break;
|
||||
|
||||
case INDEX_TMD:
|
||||
case INDEX_CONTENT:
|
||||
case INDEX_PUBLIC_SAVE:
|
||||
case INDEX_SUB_BANNER:
|
||||
hash.CopyTo(signature.digest.section[index - (INDEX_SIGNATURE + 1)], 0);
|
||||
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 INDEX_PUBLIC_SAVE:
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.PUBLIC_SAVE], 0);
|
||||
break;
|
||||
|
||||
case INDEX_SUB_BANNER:
|
||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.SUB_BANNER], 0);
|
||||
break;
|
||||
|
||||
// TODO : Private Save 追加
|
||||
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
@ -286,38 +307,6 @@ namespace FalsifyTwlBackup
|
||||
/// <returns>連結後のbyte列</returns>
|
||||
static byte[] MergeByteArray(byte[] front, byte[] rear)
|
||||
{
|
||||
/* 私のコード(色々アレだよ;;)
|
||||
byte[] merged = new byte[front.Length + rear.Length];
|
||||
for (int i = 0; i < (front.Length + rear.Length); i++)
|
||||
{
|
||||
if (i < front.Length)
|
||||
{
|
||||
merged[i] = front[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
merged[i] = rear[i - front.Length];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* 田中さん案1(中にifは使わないほうがいいよ)
|
||||
for (int i = 0; i < front.Length; i++)
|
||||
{
|
||||
merged[i] = front[i];
|
||||
}
|
||||
for (int i = 0; i < rear.Length; i++)
|
||||
{
|
||||
merged[i + front.Length] = rear[i];
|
||||
}
|
||||
*/
|
||||
|
||||
/* 田中さん案2(ライブラリを使うとコピーしてるのも分かりやすいよ^^)
|
||||
Array.Copy(front, 0, merged, 0, front.Length);
|
||||
Array.Copy(rear, 0, merged, front.Length, rear.Length);
|
||||
*/
|
||||
|
||||
// 田中さん案3(結局1行で出来ちゃったよ;;)
|
||||
return front.Concat(rear).ToArray();
|
||||
}
|
||||
|
||||
@ -395,7 +384,7 @@ namespace FalsifyTwlBackup
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 各ブロックを暗号化した後、1つのbute列に結合します。
|
||||
/// 各ブロックを暗号化した後、1つの byte 列に結合します。
|
||||
/// </summary>
|
||||
/// <param name="dataBlocks">暗号化するデータ</param>
|
||||
/// <param name="prop">バックアップデータに関するインスタンス</param>
|
||||
@ -662,7 +651,10 @@ namespace FalsifyTwlBackup
|
||||
break;
|
||||
|
||||
case 211:
|
||||
header.contentId++;
|
||||
for (int i = 0; i < header.contentId.Length; i++)
|
||||
{
|
||||
header.contentId[i]++;
|
||||
}
|
||||
outData = MergeEncryptBody(blocksForFalsifying, prop, improperData, NONE, NC_MAC_AND_HASHSET);
|
||||
OutputFalsifiedData(improperNo, prop.outFolderPath, outData);
|
||||
break;
|
||||
@ -1072,7 +1064,6 @@ namespace FalsifyTwlBackup
|
||||
|
||||
Properties prop = new Properties(); // インスタンスの作成
|
||||
byte[] twlBackupData = File.ReadAllBytes(twlBackupName); // バックアップデータの読み込み
|
||||
prop.SetOutputFolderPath(twlBackupName); // 出力フォルダを作成
|
||||
|
||||
// 鍵データの読み込み
|
||||
string[] keyString = File.ReadAllLines(keyName);
|
||||
@ -1092,14 +1083,25 @@ namespace FalsifyTwlBackup
|
||||
|
||||
// ファイル名の出力 + 鍵データの dump
|
||||
Console.WriteLine("Twl Backup File : {0}", twlBackupName);
|
||||
Console.Write("Block Key File : {0}, ", keyName);
|
||||
dumpArray("", prop.keyData);
|
||||
Console.Write("MAC Key Data : {0}, ", macKeyData);
|
||||
dumpArray("", prop.macKeyData);
|
||||
Console.WriteLine("Block Key File : {0} ({1})", keyName, dumpArray(prop.keyData));
|
||||
Console.WriteLine("MAC Key File : {0} ({1})", macKeyData, dumpArray(prop.macKeyData));
|
||||
|
||||
// TORIAEZU : ひとまず VERIFY だったら検証して終了
|
||||
if (falsifyingType == VERIFY)
|
||||
{
|
||||
if (Utility.Verify(twlBackupData, prop.keyData, prop.macKeyData))
|
||||
{
|
||||
Console.WriteLine("{0} は検証に成功しました。", twlBackupName);
|
||||
}
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
// バックアップデータを復号化
|
||||
prop.decryptedBlocks = Utility.DecryptBackupData(twlBackupData, prop.keyData);
|
||||
|
||||
// 出力フォルダを作成
|
||||
prop.SetOutputFolderPath(twlBackupName);
|
||||
|
||||
//==========================================
|
||||
// 改ざん&ファイル出力
|
||||
Console.WriteLine("Start ------------");
|
||||
@ -1111,14 +1113,14 @@ namespace FalsifyTwlBackup
|
||||
}
|
||||
|
||||
// byte 配列の 16 進表示
|
||||
static void dumpArray(String msg, byte[] array)
|
||||
static string dumpArray(byte[] array)
|
||||
{
|
||||
Console.Write(msg);
|
||||
string str = "";
|
||||
foreach (byte b in array)
|
||||
{
|
||||
Console.Write(String.Format("{0,0:X2} ", b));
|
||||
str += String.Format("{0,0:X2} ", b);
|
||||
}
|
||||
Console.WriteLine();
|
||||
return str.TrimEnd();
|
||||
}
|
||||
|
||||
}
|
@ -43,7 +43,7 @@
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="FalsifyTwlBackup.cs" />
|
||||
<Compile Include="Properties.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
@ -123,6 +123,18 @@ namespace TwlBackupBlock
|
||||
br.Read(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 現在のストリームから指定した配列に2バイト符号なし整数を読み取り、ストリームの現在位置を指定した配列のバイト数だけ進めます。
|
||||
/// </summary>
|
||||
/// <param name="buffer">データを読み取るバッファ</param>
|
||||
public void Read(UInt16[] buffer)
|
||||
{
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
Read(ref buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 現在のストリームから指定した配列に4バイト符号なし整数を読み取り、ストリームの現在位置を指定した配列のバイト数だけ進めます。
|
||||
/// </summary>
|
||||
|
@ -9,13 +9,14 @@ namespace TwlBackupBlock
|
||||
/// </summary>
|
||||
public class HeaderBody : AbstractBody
|
||||
{
|
||||
public const int HEADER_SIZE = 160;
|
||||
public const int HEADER_SIZE = 240;
|
||||
|
||||
public const int UNIQUE_ID_SIZE = 32;
|
||||
public const int HARDWARE_ID_SIZE = 16;
|
||||
public const int NUM_OF_SECTION = 4;
|
||||
public const int MAX_CONTENTS = 8;
|
||||
public const int NUM_OF_SECTION = 11;
|
||||
public const int TMD_RESERVED_SIZE = 62;
|
||||
public const int RESERVED_SIZE = 4;
|
||||
public const int RESERVED_SIZE = 13;
|
||||
|
||||
public UInt32 signature;
|
||||
public UInt16 companyCode;
|
||||
@ -25,9 +26,10 @@ namespace TwlBackupBlock
|
||||
public UInt64 titleId;
|
||||
public Int64 requiredSize;
|
||||
public readonly UInt32[] fileSizes;
|
||||
public UInt32 contentId;
|
||||
public readonly UInt32[] contentId;
|
||||
public readonly UInt16[] contentIndex;
|
||||
public readonly TmdReserved tmdReserved;
|
||||
public UInt16 contentIndex;
|
||||
public Byte headerVersion;
|
||||
public readonly Byte[] reserved;
|
||||
|
||||
public HeaderBody(byte[] data)
|
||||
@ -45,6 +47,8 @@ namespace TwlBackupBlock
|
||||
uniqueId = new Byte[UNIQUE_ID_SIZE];
|
||||
hardwareId = new Byte[HARDWARE_ID_SIZE];
|
||||
fileSizes = new UInt32[NUM_OF_SECTION];
|
||||
contentId = new UInt32[MAX_CONTENTS];
|
||||
contentIndex = new UInt16[MAX_CONTENTS];
|
||||
tmdReserved = new TmdReserved();
|
||||
reserved = new Byte[RESERVED_SIZE];
|
||||
|
||||
@ -130,9 +134,16 @@ namespace TwlBackupBlock
|
||||
{
|
||||
bw.Write(e);
|
||||
}
|
||||
bw.Write(contentId);
|
||||
foreach (UInt32 e in contentId)
|
||||
{
|
||||
bw.Write(e);
|
||||
}
|
||||
foreach (UInt16 e in contentIndex)
|
||||
{
|
||||
bw.Write(e);
|
||||
}
|
||||
bw.Write(tmdReserved.GetBytes());
|
||||
bw.Write(contentIndex);
|
||||
bw.Write(headerVersion);
|
||||
bw.Write(reserved);
|
||||
|
||||
Debug.Assert(ms.Position == HEADER_SIZE);
|
||||
@ -164,13 +175,14 @@ namespace TwlBackupBlock
|
||||
br.Read(ref titleId);
|
||||
br.Read(ref requiredSize);
|
||||
br.Read(fileSizes);
|
||||
br.Read(ref contentId);
|
||||
br.Read(contentId);
|
||||
br.Read(contentIndex);
|
||||
{
|
||||
byte[] tmdReservedBytes = new byte[TMD_RESERVED_SIZE];
|
||||
br.Read(tmdReservedBytes);
|
||||
tmdReserved.SetBytes(tmdReservedBytes);
|
||||
}
|
||||
br.Read(ref contentIndex);
|
||||
br.Read(ref headerVersion);
|
||||
br.Read(reserved);
|
||||
|
||||
Debug.Assert(ms.Position == HEADER_SIZE);
|
||||
@ -182,79 +194,4 @@ namespace TwlBackupBlock
|
||||
return new HeaderBody(GetBytes());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ヘッダブロック中のTMDReserved。
|
||||
/// </summary>
|
||||
public class TmdReserved
|
||||
{
|
||||
private const int TMD_RESERVED_SIZE = 62;
|
||||
|
||||
public const int RESERVED8_SIZE = 3;
|
||||
public const int PARENTAL_CONTROL_SIZE = 16;
|
||||
public const int RESERVED_SIZE = 30;
|
||||
|
||||
public UInt32 publicSaveSize;
|
||||
public UInt32 privateSaveSize;
|
||||
public UInt32 reserved32;
|
||||
public Byte flags;
|
||||
public readonly Byte[] reserved8;
|
||||
public readonly Byte[] parentalControl;
|
||||
public readonly Byte[] reserved;
|
||||
|
||||
public TmdReserved()
|
||||
{
|
||||
reserved8 = new Byte[RESERVED8_SIZE];
|
||||
parentalControl = new Byte[PARENTAL_CONTROL_SIZE];
|
||||
reserved = new Byte[RESERVED_SIZE];
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] bytes = new byte[TMD_RESERVED_SIZE];
|
||||
|
||||
using (var ms = new MemoryStream(bytes))
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(publicSaveSize);
|
||||
bw.Write(privateSaveSize);
|
||||
bw.Write(reserved32);
|
||||
bw.Write(flags);
|
||||
bw.Write(reserved8);
|
||||
bw.Write(parentalControl);
|
||||
bw.Write(reserved);
|
||||
|
||||
Debug.Assert(ms.Position == TMD_RESERVED_SIZE);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void SetBytes(byte[] bytes)
|
||||
{
|
||||
if (bytes == null)
|
||||
{
|
||||
throw new ArgumentNullException("bytes");
|
||||
}
|
||||
if (bytes.Length != TMD_RESERVED_SIZE)
|
||||
{
|
||||
string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", TMD_RESERVED_SIZE, bytes.Length);
|
||||
throw new ArgumentException("bytes", message);
|
||||
}
|
||||
|
||||
using (var ms = new MemoryStream(bytes))
|
||||
using (var br = new ExtBinaryReader(ms))
|
||||
{
|
||||
br.Read(ref publicSaveSize);
|
||||
br.Read(ref privateSaveSize);
|
||||
br.Read(ref reserved32);
|
||||
br.Read(ref flags);
|
||||
br.Read(reserved8);
|
||||
br.Read(parentalControl);
|
||||
br.Read(reserved);
|
||||
|
||||
Debug.Assert(ms.Position == TMD_RESERVED_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
185
TwlBkpCheck/Windows/TWLBackupBlock/LegacyHeaderBody.cs
Normal file
185
TwlBkpCheck/Windows/TWLBackupBlock/LegacyHeaderBody.cs
Normal file
@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TwlBackupBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// ヘッダブロックのデータ本体。
|
||||
/// </summary>
|
||||
public class LegacyHeaderBody : AbstractBody
|
||||
{
|
||||
public const int HEADER_SIZE = 160;
|
||||
|
||||
public const int UNIQUE_ID_SIZE = 32;
|
||||
public const int HARDWARE_ID_SIZE = 16;
|
||||
public const int NUM_OF_SECTION = 4;
|
||||
public const int TMD_RESERVED_SIZE = 62;
|
||||
public const int RESERVED_SIZE = 4;
|
||||
|
||||
public UInt32 signature;
|
||||
public UInt16 companyCode;
|
||||
public UInt16 version;
|
||||
public readonly Byte[] uniqueId;
|
||||
public readonly Byte[] hardwareId;
|
||||
public UInt64 titleId;
|
||||
public Int64 requiredSize;
|
||||
public readonly UInt32[] fileSizes;
|
||||
public UInt32 contentId;
|
||||
public readonly TmdReserved tmdReserved;
|
||||
public UInt16 contentIndex;
|
||||
public readonly Byte[] reserved;
|
||||
|
||||
public LegacyHeaderBody(byte[] data)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
throw new ArgumentNullException("data");
|
||||
}
|
||||
if (data.Length != HEADER_SIZE)
|
||||
{
|
||||
string message = string.Format("data.Length % {0} != 0 (data.Length:{1})", HEADER_SIZE, data.Length);
|
||||
throw new ArgumentException("data", message);
|
||||
}
|
||||
|
||||
uniqueId = new Byte[UNIQUE_ID_SIZE];
|
||||
hardwareId = new Byte[HARDWARE_ID_SIZE];
|
||||
fileSizes = new UInt32[NUM_OF_SECTION];
|
||||
tmdReserved = new TmdReserved();
|
||||
reserved = new Byte[RESERVED_SIZE];
|
||||
|
||||
SetBytes(data);
|
||||
}
|
||||
|
||||
public override byte this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index >= HEADER_SIZE)
|
||||
{
|
||||
throw new ArgumentException("index");
|
||||
}
|
||||
return ReadByte(index);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index >= HEADER_SIZE)
|
||||
{
|
||||
throw new ArgumentException("index");
|
||||
}
|
||||
WriteByte(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
public override int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return HEADER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定したバイトを取得します。
|
||||
/// </summary>
|
||||
/// <param name="index">取得したいバイトのインデックス。</param>
|
||||
/// <returns><paramref name="index"/>で指定したバイト</returns>
|
||||
public byte ReadByte(int index)
|
||||
{
|
||||
if (index < 0 || index >= HEADER_SIZE)
|
||||
{
|
||||
throw new ArgumentException("index");
|
||||
}
|
||||
// TODO 処理が遅ければ効率化
|
||||
byte[] bytes = GetBytes();
|
||||
return bytes[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指定したバイトを書き換えます。
|
||||
/// </summary>
|
||||
/// <param name="index">書き換えたいバイトのインデックス。</param>
|
||||
/// <param name="b">上書きに使うバイト。</param>
|
||||
public void WriteByte(int index, byte b)
|
||||
{
|
||||
if (index < 0 || index >= HEADER_SIZE)
|
||||
{
|
||||
throw new ArgumentException("index");
|
||||
}
|
||||
// TODO 処理が遅ければ効率化
|
||||
byte[] bytes = GetBytes();
|
||||
bytes[index] = b;
|
||||
SetBytes(bytes);
|
||||
}
|
||||
|
||||
public override byte[] GetBytes()
|
||||
{
|
||||
byte[] bytes = new byte[HEADER_SIZE];
|
||||
|
||||
using (var ms = new MemoryStream(bytes))
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(signature);
|
||||
bw.Write(companyCode);
|
||||
bw.Write(version);
|
||||
bw.Write(uniqueId);
|
||||
bw.Write(hardwareId);
|
||||
bw.Write(titleId);
|
||||
bw.Write(requiredSize);
|
||||
foreach (UInt32 e in fileSizes)
|
||||
{
|
||||
bw.Write(e);
|
||||
}
|
||||
bw.Write(contentId);
|
||||
bw.Write(tmdReserved.GetBytes());
|
||||
bw.Write(contentIndex);
|
||||
bw.Write(reserved);
|
||||
|
||||
Debug.Assert(ms.Position == HEADER_SIZE);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public override void SetBytes(byte[] bytes)
|
||||
{
|
||||
if (bytes == null)
|
||||
{
|
||||
throw new ArgumentNullException("bytes");
|
||||
}
|
||||
if (bytes.Length != HEADER_SIZE)
|
||||
{
|
||||
string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", HEADER_SIZE, bytes.Length);
|
||||
throw new ArgumentException("bytes", message);
|
||||
}
|
||||
|
||||
using (var ms = new MemoryStream(bytes))
|
||||
using (var br = new ExtBinaryReader(ms))
|
||||
{
|
||||
br.Read(ref signature);
|
||||
br.Read(ref companyCode);
|
||||
br.Read(ref version);
|
||||
br.Read(uniqueId);
|
||||
br.Read(hardwareId);
|
||||
br.Read(ref titleId);
|
||||
br.Read(ref requiredSize);
|
||||
br.Read(fileSizes);
|
||||
br.Read(ref contentId);
|
||||
{
|
||||
byte[] tmdReservedBytes = new byte[TMD_RESERVED_SIZE];
|
||||
br.Read(tmdReservedBytes);
|
||||
tmdReserved.SetBytes(tmdReservedBytes);
|
||||
}
|
||||
br.Read(ref contentIndex);
|
||||
br.Read(reserved);
|
||||
|
||||
Debug.Assert(ms.Position == HEADER_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
public override object Clone()
|
||||
{
|
||||
return new HeaderBody(GetBytes());
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,8 @@ namespace TwlBackupBlock
|
||||
public class TwlBackupHashSet
|
||||
{
|
||||
public const int HASH_SIZE = 32;
|
||||
public const int NUM_OF_SECTION = 4;
|
||||
public const int NUM_OF_SECTION = 11;
|
||||
public const int NUM_OF_LEGACY_SECTION = 4;
|
||||
|
||||
public readonly byte[] banner;
|
||||
public readonly byte[] header;
|
||||
@ -19,11 +20,12 @@ namespace TwlBackupBlock
|
||||
/// <summary>
|
||||
/// コンストラクタ。
|
||||
/// </summary>
|
||||
public TwlBackupHashSet()
|
||||
public TwlBackupHashSet(bool isLegacy = false)
|
||||
{
|
||||
banner = new byte[HASH_SIZE];
|
||||
header = new byte[HASH_SIZE];
|
||||
section = new byte[NUM_OF_SECTION][];
|
||||
section = isLegacy ?
|
||||
new byte[NUM_OF_LEGACY_SECTION][] : new byte[NUM_OF_SECTION][];
|
||||
for (int i = 0; i < section.Length; i++)
|
||||
{
|
||||
section[i] = new byte[HASH_SIZE];
|
||||
@ -35,7 +37,8 @@ namespace TwlBackupBlock
|
||||
/// </summary>
|
||||
public class SignatureBody : AbstractBody
|
||||
{
|
||||
public const int SIGNATURE_SIZE = 1024;
|
||||
public const int SIGNATURE_SIZE = 1248;
|
||||
public const int LEGACY_SIGNATURE_SIZE = 1024;
|
||||
|
||||
public const int ECC_SIGN_SIZE = 60;
|
||||
public const int ECC_CERT_SIZE = 384;
|
||||
|
82
TwlBkpCheck/Windows/TWLBackupBlock/TmdReserved.cs
Normal file
82
TwlBkpCheck/Windows/TWLBackupBlock/TmdReserved.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TwlBackupBlock
|
||||
{
|
||||
/// <summary>
|
||||
/// ヘッダブロック中のTMDReserved。
|
||||
/// Normal, Legacy 共に共通。
|
||||
/// </summary>
|
||||
public class TmdReserved
|
||||
{
|
||||
private const int TMD_RESERVED_SIZE = 62;
|
||||
|
||||
public const int RESERVED8_SIZE = 3;
|
||||
public const int PARENTAL_CONTROL_SIZE = 16;
|
||||
public const int RESERVED_SIZE = 30;
|
||||
|
||||
public UInt32 publicSaveSize;
|
||||
public UInt32 privateSaveSize;
|
||||
public UInt32 reserved32;
|
||||
public Byte flags;
|
||||
public readonly Byte[] reserved8;
|
||||
public readonly Byte[] parentalControl;
|
||||
public readonly Byte[] reserved;
|
||||
|
||||
public TmdReserved()
|
||||
{
|
||||
reserved8 = new Byte[RESERVED8_SIZE];
|
||||
parentalControl = new Byte[PARENTAL_CONTROL_SIZE];
|
||||
reserved = new Byte[RESERVED_SIZE];
|
||||
}
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
byte[] bytes = new byte[TMD_RESERVED_SIZE];
|
||||
|
||||
using (var ms = new MemoryStream(bytes))
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(publicSaveSize);
|
||||
bw.Write(privateSaveSize);
|
||||
bw.Write(reserved32);
|
||||
bw.Write(flags);
|
||||
bw.Write(reserved8);
|
||||
bw.Write(parentalControl);
|
||||
bw.Write(reserved);
|
||||
|
||||
Debug.Assert(ms.Position == TMD_RESERVED_SIZE);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void SetBytes(byte[] bytes)
|
||||
{
|
||||
if (bytes == null)
|
||||
{
|
||||
throw new ArgumentNullException("bytes");
|
||||
}
|
||||
if (bytes.Length != TMD_RESERVED_SIZE)
|
||||
{
|
||||
string message = string.Format("bytes.Length != {0} (bytes.Length:{1})", TMD_RESERVED_SIZE, bytes.Length);
|
||||
throw new ArgumentException("bytes", message);
|
||||
}
|
||||
|
||||
using (var ms = new MemoryStream(bytes))
|
||||
using (var br = new ExtBinaryReader(ms))
|
||||
{
|
||||
br.Read(ref publicSaveSize);
|
||||
br.Read(ref privateSaveSize);
|
||||
br.Read(ref reserved32);
|
||||
br.Read(ref flags);
|
||||
br.Read(reserved8);
|
||||
br.Read(parentalControl);
|
||||
br.Read(reserved);
|
||||
|
||||
Debug.Assert(ms.Position == TMD_RESERVED_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -58,6 +58,7 @@
|
||||
<Compile Include="AesCmac.cs" />
|
||||
<Compile Include="Body.cs" />
|
||||
<Compile Include="ExtBinaryReader.cs" />
|
||||
<Compile Include="LegacyHeaderBody.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
@ -68,6 +69,7 @@
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="TmdReserved.cs" />
|
||||
<Compile Include="Utility.cs" />
|
||||
<Compile Include="AbstractBody.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
@ -13,6 +13,16 @@ namespace TwlBackupBlock
|
||||
/// </summary>
|
||||
public class Utility
|
||||
{
|
||||
public const int MAX_CONTENTS = 8;
|
||||
public enum SectionIndex
|
||||
{
|
||||
TMD,
|
||||
CONTENT,
|
||||
PUBLIC_SAVE = CONTENT + MAX_CONTENTS,
|
||||
SUB_BANNER,
|
||||
PRIVATE_SAVE
|
||||
};
|
||||
|
||||
private const int KEY_SIZE = 16;
|
||||
private const int ROUND_SCALE = 16;
|
||||
|
||||
@ -21,8 +31,10 @@ namespace TwlBackupBlock
|
||||
private const int AES_SIGN_HEADER_SIZE = 32;
|
||||
|
||||
private const int BANNER_SIZE = 16 * 1024;
|
||||
private const int HEADER_SIZE = 160;
|
||||
private const int SIGNATURE_SIZE = 1024;
|
||||
private const int HEADER_SIZE = 240;
|
||||
private const int SIGNATURE_SIZE = 1248;
|
||||
private const int LEGACY_HEADER_SIZE = 160;
|
||||
private const int LEGACY_SIGNATURE_SIZE = 1024;
|
||||
|
||||
private const int ENCRYPT_BANNER_SIZE = BANNER_SIZE + AES_SIGN_HEADER_SIZE;
|
||||
private const int ENCRYPT_HEADER_SIZE = HEADER_SIZE + AES_SIGN_HEADER_SIZE;
|
||||
@ -74,14 +86,16 @@ namespace TwlBackupBlock
|
||||
|
||||
blocks.signature.body = new SignatureBody(DecryptBlock(br, SIGNATURE_SIZE, key, out blocks.signature.mac, out blocks.signature.iv));
|
||||
|
||||
int TMD_SIZE = (int)headerBody.fileSizes[0];
|
||||
int CONTENT_SIZE = (int)headerBody.fileSizes[1];
|
||||
int SAVE_DATA_SIZE = (int)headerBody.fileSizes[2];
|
||||
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[3];
|
||||
// TORIAEZU
|
||||
// TODO : 複数コンテンツ対応
|
||||
int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD];
|
||||
int CONTENT_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT];
|
||||
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));
|
||||
blocks.saveData.body = new Body(DecryptBlock(br, SAVE_DATA_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));
|
||||
|
||||
Debug.Assert(ms.Position == data.Length);
|
||||
@ -386,13 +400,14 @@ namespace TwlBackupBlock
|
||||
return false;
|
||||
}
|
||||
|
||||
int TMD_SIZE = (int)headerBody.fileSizes[0];
|
||||
int CONTENT_SIZE = (int)headerBody.fileSizes[1];
|
||||
int SAVE_DATA_SIZE = (int)headerBody.fileSizes[2];
|
||||
int SUB_BANNER_SIZE = (int)headerBody.fileSizes[3];
|
||||
// TODO : 複数コンテンツ対応
|
||||
int TMD_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.TMD];
|
||||
int CONTENT_SIZE = (int)headerBody.fileSizes[(int)SectionIndex.CONTENT];
|
||||
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) +
|
||||
RoundUp(SAVE_DATA_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;
|
||||
if (data.Length - ms.Position != restSize)
|
||||
{
|
||||
@ -405,7 +420,7 @@ namespace TwlBackupBlock
|
||||
Console.WriteLine("TMDブロックのMACが一致しません");
|
||||
return false;
|
||||
}
|
||||
if (!CheckHash(blocks.tmd, signatureBody.digest.section[0]))
|
||||
if (!CheckHash(blocks.tmd, signatureBody.digest.section[(int)SectionIndex.TMD]))
|
||||
{
|
||||
Console.WriteLine("TMDブロックのハッシュが一致しません");
|
||||
return false;
|
||||
@ -416,18 +431,18 @@ namespace TwlBackupBlock
|
||||
Console.WriteLine("コンテンツブロックのMACが一致しません");
|
||||
return false;
|
||||
}
|
||||
if (!CheckHash(blocks.content, signatureBody.digest.section[1]))
|
||||
if (!CheckHash(blocks.content, signatureBody.digest.section[(int)SectionIndex.CONTENT]))
|
||||
{
|
||||
Console.WriteLine("コンテンツブロックのハッシュが一致しません");
|
||||
return false;
|
||||
}
|
||||
blocks.saveData.body = new Body(DecryptBlock(br, SAVE_DATA_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))
|
||||
{
|
||||
Console.WriteLine("publicセーブデータブロックのMACが一致しません");
|
||||
return false;
|
||||
}
|
||||
if (!CheckHash(blocks.saveData, signatureBody.digest.section[2]))
|
||||
if (!CheckHash(blocks.saveData, signatureBody.digest.section[(int)SectionIndex.PUBLIC_SAVE]))
|
||||
{
|
||||
Console.WriteLine("publicセーブデータブロックのハッシュが一致しません");
|
||||
return false;
|
||||
@ -438,7 +453,7 @@ namespace TwlBackupBlock
|
||||
Console.WriteLine("サブバナーブロックの内容とMACが一致しません");
|
||||
return false;
|
||||
}
|
||||
if (!CheckHash(blocks.subBanner, signatureBody.digest.section[3]))
|
||||
if (!CheckHash(blocks.subBanner, signatureBody.digest.section[(int)SectionIndex.SUB_BANNER]))
|
||||
{
|
||||
Console.WriteLine("サブバナーブロックのハッシュが一致しません");
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user