mirror of
https://github.com/rvtr/ctr_test_tools.git
synced 2025-06-19 00:55:31 -04:00
FalsifyTwlBackup:Properties に BkpType 追加。
オプションの一新により、-type で BkpType を指定できるようにした(処理は NORMAL と WPS のみ) git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-09-30%20-%20paladin.7z/paladin/ctr_test_tools@36 6b0af911-cb57-b745-895f-eec5701120e1
This commit is contained in:
parent
dbd09789ba
commit
40682e103a
@ -7,22 +7,24 @@ using TwlBackupBlock;
|
|||||||
|
|
||||||
namespace FalsifyTwlBackup
|
namespace FalsifyTwlBackup
|
||||||
{
|
{
|
||||||
class Properties
|
class Properties
|
||||||
{
|
|
||||||
public Blocks decryptedBlocks; // 復号化されたバックアップデータ
|
|
||||||
public byte[] keyData; // ブロック暗号化のための鍵データ
|
|
||||||
public byte[] macKeyData; // MAC生成のための鍵データ
|
|
||||||
|
|
||||||
public string outFolderPath; // 出力フォルダ名
|
|
||||||
|
|
||||||
public void SetOutputFolderPath(string twlBackupDataName)
|
|
||||||
{
|
{
|
||||||
// 出力フォルダを入力ファイルと同じディレクトリに
|
public Blocks decryptedBlocks; // 復号化されたバックアップデータ
|
||||||
outFolderPath = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(twlBackupDataName)), @"FalsifiedTwlBackup");
|
public byte[] keyData; // ブロック暗号化のための鍵データ
|
||||||
Directory.CreateDirectory(outFolderPath); // 出力フォルダを作成
|
public byte[] macKeyData; // MAC生成のための鍵データ
|
||||||
}
|
|
||||||
|
|
||||||
// TODO SetKeyData()とGetKeyData()的なものを用意して、privateにしたい
|
public BkpType bkpType; // バックアップの形式。
|
||||||
// TODO 出力ディレクトリを変更可能に
|
|
||||||
}
|
public string outFolderPath; // 出力フォルダ名
|
||||||
|
|
||||||
|
public void SetOutputFolderPath(string twlBackupDataName)
|
||||||
|
{
|
||||||
|
// 出力フォルダを入力ファイルと同じディレクトリに
|
||||||
|
outFolderPath = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(twlBackupDataName)), @"FalsifiedTwlBackup");
|
||||||
|
Directory.CreateDirectory(outFolderPath); // 出力フォルダを作成
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO SetKeyData()とGetKeyData()的なものを用意して、privateにしたい
|
||||||
|
// TODO 出力ディレクトリを変更可能に
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ partial class Program
|
|||||||
private const int SECTION_CONTENT = 4;
|
private const int SECTION_CONTENT = 4;
|
||||||
private const int SECTION_PUBLIC_SAVE = SECTION_CONTENT + MAX_CONTENTS;
|
private const int SECTION_PUBLIC_SAVE = SECTION_CONTENT + MAX_CONTENTS;
|
||||||
private const int SECTION_SUB_BANNER = SECTION_PUBLIC_SAVE + 1;
|
private const int SECTION_SUB_BANNER = SECTION_PUBLIC_SAVE + 1;
|
||||||
|
private const int SECTION_PRIVATE_SAVE = SECTION_SUB_BANNER + 1;
|
||||||
|
|
||||||
// データの挿入位置
|
// データの挿入位置
|
||||||
private const int NONE = -1;
|
private const int NONE = -1;
|
||||||
@ -45,13 +46,13 @@ partial class Program
|
|||||||
private const int REAR_DATA = 99; // データ全体の後
|
private const int REAR_DATA = 99; // データ全体の後
|
||||||
|
|
||||||
// 改ざんパターンの引き数
|
// 改ざんパターンの引き数
|
||||||
private const int ALL = 0;
|
private const int MODE_ALL = 0;
|
||||||
private const int CAT100 = 1;
|
private const int MODE_CAT100 = 1;
|
||||||
private const int CAT200 = 2;
|
private const int MODE_CAT200 = 2;
|
||||||
private const int CAT300 = 3;
|
private const int MODE_CAT300 = 3;
|
||||||
private const int CAT400 = 4;
|
private const int MODE_CAT400 = 4;
|
||||||
private const int CAT500 = 5;
|
private const int MODE_CAT500 = 5;
|
||||||
private const int VERIFY = 9; // TORIAEZU : 上記が Mode == Pattern なのが引っかかる・・・
|
private const int MODE_VERIFY = 9;
|
||||||
|
|
||||||
// 各カテゴリでの最小番号
|
// 各カテゴリでの最小番号
|
||||||
private const int MIN_OF_CAT100 = 100;
|
private const int MIN_OF_CAT100 = 100;
|
||||||
@ -80,7 +81,7 @@ 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 = 14; // バックアップデータのブロックの個数
|
private const int BLOCK_NUM = 15; // バックアップデータのブロックの個数
|
||||||
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)
|
||||||
@ -93,22 +94,20 @@ partial class Program
|
|||||||
static void Usage()
|
static void Usage()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Usage: ");
|
Console.WriteLine("Usage: ");
|
||||||
Console.WriteLine("./FalsifyingTwlBackup.exe BACKUPFILE_NAME KEYFILE_NAME MACKEYFALE_NAME MODE");
|
Console.WriteLine("./FalsifyingTwlBackup.exe BACKUP_FILE ENC_KEY_FILE MAC_KEY_FILE [-mode MODE] [-type TYPE]");
|
||||||
Console.WriteLine(" BACKUPFILE_NAME : *.bin");
|
Console.WriteLine(" BACKUP_FILE : *.bin");
|
||||||
Console.WriteLine(" KEYFILE_NAME : *.txt");
|
Console.WriteLine(" ENC_KEY_FILE : *.txt");
|
||||||
Console.WriteLine(" MACKEYFALE_NAME : *.txt\n");
|
Console.WriteLine(" MAC_KEY_FILE : *.txt\n");
|
||||||
Console.WriteLine(" MODE");
|
Console.WriteLine(" MODE");
|
||||||
Console.WriteLine(" -all (default) : output all falsifying pattern");
|
Console.WriteLine(" all (default) : output all falsifying pattern");
|
||||||
Console.WriteLine(" -cat CAT_NUM : output all pattern of CAT_NUM category");
|
Console.WriteLine(" cat:CAT_NUM : output all pattern of CAT_NUM category");
|
||||||
Console.WriteLine(" ex) -cat 100 -> falsifying 100,101,102....");
|
Console.WriteLine(" ex) -mode cat:100 -> falsifying 100,101,102....");
|
||||||
Console.WriteLine(" -each PAT_NUM : output PAT_NUM pattern");
|
Console.WriteLine(" each:PAT_NUM : output PAT_NUM pattern");
|
||||||
Console.WriteLine(" ex) -each 204 -> falsifying 204 only");
|
Console.WriteLine(" ex) -mode each:204 -> falsifying 204 only");
|
||||||
Console.WriteLine(" -verify : verify backup file");
|
Console.WriteLine(" verify : verify backup file");
|
||||||
Environment.Exit(-1);
|
Environment.Exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 拡張子の判別を行います。
|
/// 拡張子の判別を行います。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -120,13 +119,12 @@ partial class Program
|
|||||||
|
|
||||||
if (args.ToLower().EndsWith(extension) == false)
|
if (args.ToLower().EndsWith(extension) == false)
|
||||||
{
|
{
|
||||||
Console.WriteLine("{0} is not [\"{1}\"] file!", args, extension);
|
Console.WriteLine("{0} is not [\"{1}\"] file!", args, extension);
|
||||||
Usage();
|
Usage();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ファイルの有無を確認します。
|
/// ファイルの有無を確認します。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -136,550 +134,188 @@ partial class Program
|
|||||||
Debug.Assert(args.Length != 0);
|
Debug.Assert(args.Length != 0);
|
||||||
if (!File.Exists(args))
|
if (!File.Exists(args))
|
||||||
{
|
{
|
||||||
Console.WriteLine("\"{0}\" is not exists!\n", args);
|
Console.WriteLine("\"{0}\" is not exists!\n", args);
|
||||||
Usage();
|
Usage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// コマンドライン引数のオプションから処理を決定するためのフラグを立てる
|
/// コマンドライン引数のオプションから処理を決定するためのフラグを立てる
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">コマンドライン引数の格納された文字列</param>
|
/// <param name="arg">コマンドライン引数の格納された文字列</param>
|
||||||
/// <returns>処理判別のためのフラグ</returns>
|
/// <returns>処理判別のためのフラグ</returns>
|
||||||
static int GetFalsifyingType(string[] args)
|
static int GetFalsifyingMode(string arg)
|
||||||
{
|
{
|
||||||
Debug.Assert(args.Length >= 3);
|
const string PREFIX_STR_CAT = "CAT:";
|
||||||
|
const string PREFIX_STR_EACH = "EACH:";
|
||||||
|
|
||||||
if (args.Length > 3)
|
// all のとき
|
||||||
|
if (arg.ToUpper() == "ALL")
|
||||||
{
|
{
|
||||||
// -allのとき
|
return MODE_ALL;
|
||||||
if (args[3].ToUpper().TrimStart('-') == "ALL")
|
|
||||||
{
|
|
||||||
return ALL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -catのとき
|
// cat:xxx のとき
|
||||||
else if (args[3].ToUpper().TrimStart('-') == "CAT")
|
else if (arg.Length > PREFIX_STR_CAT.Length &&
|
||||||
|
arg.ToUpper().Substring(0, PREFIX_STR_CAT.Length) == PREFIX_STR_CAT)
|
||||||
{
|
{
|
||||||
if (4 >= args.Length) // CATなのに次の引数が無かったら帰れ!
|
switch (arg.Substring(PREFIX_STR_CAT.Length, "XXX".Length))
|
||||||
{
|
{
|
||||||
Usage();
|
case "100": return MODE_CAT100;
|
||||||
}
|
case "200": return MODE_CAT200;
|
||||||
switch (args[4])
|
case "300": return MODE_CAT300;
|
||||||
{
|
case "400": return MODE_CAT400;
|
||||||
case "100": return CAT100;
|
case "500": return MODE_CAT500;
|
||||||
case "200": return CAT200;
|
default: Usage(); break; // never reach
|
||||||
case "300": return CAT300;
|
|
||||||
case "400": return CAT400;
|
|
||||||
case "500": return CAT500;
|
|
||||||
default: Usage(); break; // never reach
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -eachのとき
|
// each:xxx のとき
|
||||||
else if (args[3].ToUpper().TrimStart('-') == "EACH")
|
else if (arg.Length > PREFIX_STR_EACH.Length &&
|
||||||
|
arg.ToUpper().Substring(0, PREFIX_STR_EACH.Length) == PREFIX_STR_EACH)
|
||||||
{
|
{
|
||||||
if (4 >= args.Length) // EACHなのに次の引数が無かったら帰れ!
|
|
||||||
{
|
|
||||||
Usage();
|
|
||||||
}
|
|
||||||
// TODO 存在しない処理番号をはじくように
|
// TODO 存在しない処理番号をはじくように
|
||||||
else
|
return Convert.ToInt16(arg.Substring(PREFIX_STR_EACH.Length));
|
||||||
{
|
|
||||||
return Convert.ToInt16(args[4]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -verify
|
// -verify
|
||||||
else if (args[3].ToUpper().TrimStart('-') == "VERIFY")
|
else if (arg.ToUpper() == "VERIFY")
|
||||||
{
|
{
|
||||||
return VERIFY;
|
return MODE_VERIFY;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// それ以外
|
// それ以外
|
||||||
return ALL;
|
return MODE_ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 指定されたbyteサイズで、0のみのbyte列を作成します。
|
/// コマンドライン引数のオプションからバックアップ形式を指定する
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataSize">作成するデータのサイズ[単位:byte]</param>
|
/// <param name="arg">コマンドライン引数の格納された文字列</param>
|
||||||
/// <returns>作成したデータのbyte列</returns>
|
/// <returns>処理判別のためのフラグ</returns>
|
||||||
// TODO 不正データの作成方法を選べるようにしてもいいかも
|
static BkpType GetBackupType(string arg)
|
||||||
static byte[] CreateImproperData(int dataSize)
|
|
||||||
{
|
{
|
||||||
byte[] data = new byte[dataSize];
|
// normal のとき
|
||||||
for (int i = 0; i < data.Length; i++)
|
if (arg.ToUpper() == "NORMAL")
|
||||||
{
|
{
|
||||||
//data[i] = (byte)(i);
|
return BkpType.NORMAL;
|
||||||
data[i] = 0;
|
|
||||||
}
|
}
|
||||||
return data;
|
|
||||||
|
// wps のとき
|
||||||
|
if (arg.ToUpper() == "WPS")
|
||||||
|
{
|
||||||
|
return BkpType.WITH_PRIVATE_SAVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy のとき
|
||||||
|
if (arg.ToUpper() == "LEGACY")
|
||||||
|
{
|
||||||
|
return BkpType.LEGACY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// それ以外
|
||||||
|
return BkpType.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// データの差し替えを行います。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dataBlocks">上書き対象となるデータ本体</param>
|
|
||||||
/// <param name="impData">上書きする不正データ</param>
|
|
||||||
static void ReplaceImproperData(AbstractBody dataBlocks, byte[] impData)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < impData.Length; i++)
|
|
||||||
{
|
|
||||||
if (i < dataBlocks.Length) // 上書き先のデータサイズを超えませんように
|
|
||||||
{
|
|
||||||
dataBlocks[i] = impData[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// ※未使用
|
|
||||||
/// 暗号化に使用するIVを作成します。
|
|
||||||
/// AES方式で、ブロックサイズはAES_BLOCK_SIZE[bit]と同じです。
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>生成したivのbyte列</returns>
|
|
||||||
static byte[] GenerateNewIv()
|
|
||||||
{
|
|
||||||
// 暗号化用IV作成
|
|
||||||
/*
|
|
||||||
* [参考] C#(.NET Framework)のAESを使ってファイルを暗号化してみる
|
|
||||||
* http://hibara.sblo.jp/article/43505136.html
|
|
||||||
*/
|
|
||||||
System.Security.Cryptography.AesCryptoServiceProvider
|
|
||||||
aes = new System.Security.Cryptography.AesCryptoServiceProvider();
|
|
||||||
aes.BlockSize = AES_BLOCK_SIZE; // AESはブロックサイズ、キー長ともに16byte
|
|
||||||
aes.GenerateIV(); // IVの設定(ブロックサイズと同サイズ = 16byte)
|
|
||||||
byte[] byteIV = aes.IV; // IVをバイト列に
|
|
||||||
return byteIV;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 署名のハッシュセットを変更します。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dataBlocks">変更対象となる署名ブロックを有するBlocks</param>
|
|
||||||
/// <param name="hash">新しいハッシュ値</param>
|
|
||||||
/// <param name="section">変更するブロックセクション</param>
|
|
||||||
static void ChangeHashSet(Blocks dataBlocks, byte[] hash, int section)
|
|
||||||
{
|
|
||||||
Debug.Assert((section <= BLOCK_NUM - 1) && (section >= 0));
|
|
||||||
|
|
||||||
SignatureBody signature;
|
|
||||||
signature = (SignatureBody)dataBlocks.signature.body;
|
|
||||||
if (SECTION_CONTENT <= section && section < SECTION_CONTENT + MAX_CONTENTS)
|
|
||||||
{
|
|
||||||
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 SECTION_HEADER:
|
|
||||||
hash.CopyTo(signature.digest.header, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SECTION_TMD:
|
|
||||||
hash.CopyTo(signature.digest.section[(int)Utility.SectionIndex.TMD], 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SECTION_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;
|
|
||||||
|
|
||||||
// TODO : Private Save 追加
|
|
||||||
|
|
||||||
default:
|
|
||||||
Debug.Assert(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// byte列を結合します。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="front">前半部分に来るbyte列</param>
|
|
||||||
/// <param name="rear">後半部分に来るbyte列</param>
|
|
||||||
/// <returns>連結後のbyte列</returns>
|
|
||||||
static byte[] MergeByteArray(byte[] front, byte[] rear)
|
|
||||||
{
|
|
||||||
return front.Concat(rear).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// byte列をbinファイルに出力します。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="improperNo">ファイル名となる改ざんパターンの番号</param>
|
|
||||||
/// <param name="outFolderPath">出力ディレクトリのパス</param>
|
|
||||||
/// <param name="data">ファイルに出力するデータ</param>
|
|
||||||
static void OutputFalsifiedData(int improperNo, string outFolderPath, byte[] data)
|
|
||||||
{
|
|
||||||
string outFalsifiedDataPath = Convert.ToString(improperNo) + EXTENSION; // ファイル名を改ざん番号から生成
|
|
||||||
outFalsifiedDataPath = Path.Combine(outFolderPath, outFalsifiedDataPath); // 出力ディレクトリとファイル名を結合
|
|
||||||
File.WriteAllBytes(outFalsifiedDataPath, data); // 出力
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// データ本体とMACとIVをひとつのブロックに結合します。
|
|
||||||
/// 必要に応じて不正データを挿入します。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dataBlocks">暗号化するBlockを持つBlocks</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 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 (section == insertPos - FRONT_BANNER)
|
|
||||||
{
|
|
||||||
encryptedBlock = MergeByteArray(encryptedBlock, impData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// データ本体を暗号化
|
|
||||||
encryptedBlock = MergeByteArray(encryptedBlock, dataBlocks[section].body.GetBytes()); // bodyを暗号化
|
|
||||||
|
|
||||||
// (データ本体の後に不正データ挿入)
|
|
||||||
if (insertPos >= REAR_BANNER && insertPos <= REAR_SUB_BANNER)
|
|
||||||
{
|
|
||||||
if (section == insertPos - REAR_BANNER)
|
|
||||||
{
|
|
||||||
encryptedBlock = MergeByteArray(encryptedBlock, impData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byteHash != null)
|
|
||||||
{
|
|
||||||
byte[] buff = Utility.GetSha256(encryptedBlock); // 平文からSHA256ハッシュ算出
|
|
||||||
buff.CopyTo(byteHash, 0);
|
|
||||||
byteMac = Utility.GetAesCmac(byteHash, prop.macKeyData); // SHA256ハッシュからMACを算出
|
|
||||||
}
|
|
||||||
|
|
||||||
encryptedBlock = Utility.EncryptBody(encryptedBlock, prop.keyData, dataBlocks[section].iv); // データ本体を暗号化
|
|
||||||
encryptedBlock = MergeByteArray(encryptedBlock, byteMac); // MACを結合
|
|
||||||
encryptedBlock = MergeByteArray(encryptedBlock, dataBlocks[section].iv); // IVを結合
|
|
||||||
|
|
||||||
// (データブロックの後に不正データ挿入)
|
|
||||||
if (section == SECTION_SUB_BANNER && insertPos == REAR_DATA)
|
|
||||||
{
|
|
||||||
encryptedBlock = MergeByteArray(encryptedBlock, impData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return encryptedBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 各ブロックを暗号化した後、1つの byte 列に結合します。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dataBlocks">暗号化するデータ</param>
|
|
||||||
/// <param name="prop">バックアップデータに関するインスタンス</param>
|
|
||||||
/// <param name="impData">不正データ</param>
|
|
||||||
/// <param name="insertPos">不正データを挿入する位置</param>
|
|
||||||
/// <param name="chgMacHash">ハッシュセット更新の有無</param>
|
|
||||||
/// <returns>全てのBlockを暗号化し、連結したbyte列</returns>
|
|
||||||
static byte[] MergeEncryptBody(Blocks dataBlocks, Properties prop, byte[] impData, int insertPos, int chgMacHash)
|
|
||||||
{
|
|
||||||
byte[] outData = new byte[0];
|
|
||||||
byte[][] encryptedBlocks = new byte[BLOCK_NUM][];
|
|
||||||
|
|
||||||
byte[][] byteHash = new byte[BLOCK_NUM][];
|
|
||||||
byte[][] byteMac = new byte[BLOCK_NUM][];
|
|
||||||
|
|
||||||
//----------------------
|
|
||||||
// 各ブロックを暗号化
|
|
||||||
// ( MAC & HASH SET更新する場合 )
|
|
||||||
if (chgMacHash == CHG_MAC_AND_HASHSET)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < BLOCK_NUM; i++) // 署名部以外を暗号化&byte列に結合
|
|
||||||
{
|
|
||||||
byteHash[i] = new byte[HASH_SIZE];
|
|
||||||
if (i != SECTION_SIGNATURE)
|
|
||||||
{
|
|
||||||
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[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更新しない場合 )
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < BLOCK_NUM; i++)
|
|
||||||
{
|
|
||||||
if (dataBlocks[i].body != null)
|
|
||||||
{
|
|
||||||
encryptedBlocks[i] = EncryptBlock(dataBlocks, i, prop, impData, insertPos, dataBlocks[i].mac); // ブロックを暗号化&結合
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
encryptedBlocks[i] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------
|
|
||||||
// 暗号化した各ブロックを結合
|
|
||||||
for (int i = 0; i < BLOCK_NUM; i++)
|
|
||||||
{
|
|
||||||
if (encryptedBlocks[i] != null)
|
|
||||||
{
|
|
||||||
outData = MergeByteArray(outData, encryptedBlocks[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return outData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static void FalsifyingData(int improperNo, Properties prop, byte[] improperData)
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// パターン番号に応じた改ざんを実行
|
|
||||||
// [in] int improperNo : 改ざんパターン番号
|
|
||||||
// [in] Properties prop : バックアップデータに関するインスタンス
|
|
||||||
// [in] byte[] improperData : 改ざんに使用する不正データ
|
|
||||||
//------------------------------------------------------------
|
|
||||||
/// <summary>
|
|
||||||
/// パターン番号に応じた改ざんを実行
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="improperNo"></param>
|
|
||||||
/// <param name="prop"></param>
|
|
||||||
/// <param name="improperData"></param>
|
|
||||||
static void FalsifyingData(int improperNo, Properties prop, byte[] improperData)
|
|
||||||
{
|
|
||||||
if (MIN_OF_CAT100 <= improperNo && improperNo <= MAX_OF_CAT100)
|
|
||||||
{
|
|
||||||
FalsifyingDataCategory1xx(improperNo, prop, improperData);
|
|
||||||
}
|
|
||||||
else if (MIN_OF_CAT200 <= improperNo && improperNo <= MAX_OF_CAT200)
|
|
||||||
{
|
|
||||||
FalsifyingDataCategory2xx(improperNo, prop, improperData);
|
|
||||||
}
|
|
||||||
else if (MIN_OF_CAT300 <= improperNo && improperNo <= MAX_OF_CAT300)
|
|
||||||
{
|
|
||||||
FalsifyingDataCategory3xx(improperNo, prop, improperData);
|
|
||||||
}
|
|
||||||
else if (MIN_OF_CAT400 <= improperNo && improperNo <= MAX_OF_CAT400)
|
|
||||||
{
|
|
||||||
FalsifyingDataCategory4xx(improperNo, prop, improperData);
|
|
||||||
}
|
|
||||||
else if (MIN_OF_CAT500 <= improperNo && improperNo <= MAX_OF_CAT500)
|
|
||||||
{
|
|
||||||
FalsifyingDataCategory5xx(improperNo, prop, improperData);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FalsifyingDataCategory9xx(improperNo, prop, improperData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static void SwitchFalsifyingPattern(int falsifyingType, Properties prop)
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// 作成する改ざんデータのパターンを決定。
|
|
||||||
// [in] int falsifyingType : 出力する改ざんデータのパターン
|
|
||||||
// [in] Properties prop : バックアップデータに関するインスタンス
|
|
||||||
//------------------------------------------------------------
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="falsifyingType"></param>
|
|
||||||
/// <param name="prop"></param>
|
|
||||||
static void SwitchFalsifyingPattern(int falsifyingType, Properties prop)
|
|
||||||
{
|
|
||||||
// 改ざんに使用する不正なデータ作成
|
|
||||||
byte[] improperData = CreateImproperData(IMPROPER_DATA_SIZE);
|
|
||||||
|
|
||||||
switch (falsifyingType)
|
|
||||||
{
|
|
||||||
case ALL: // 全パターン
|
|
||||||
Console.WriteLine(" Falsifying \"all pattern\".");
|
|
||||||
for (int i = 0; i < NUM_OF_PATTERN.GetLength(0); i++)
|
|
||||||
{
|
|
||||||
for (int j = NUM_OF_PATTERN[i, 0]; j <= NUM_OF_PATTERN[i, 1]; j++)
|
|
||||||
{
|
|
||||||
FalsifyingData(j, prop, improperData);
|
|
||||||
Console.WriteLine(" Complete falsifying No.{0}.", j);
|
|
||||||
}
|
|
||||||
Console.WriteLine(" Complete falsifying Cat.{0}.\n", NUM_OF_PATTERN[i, 0]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAT100: // 1xx系列全て
|
|
||||||
Console.WriteLine(" Falsifying category No.{0}.", NUM_OF_PATTERN[CAT100 - 1, 0]);
|
|
||||||
for (int i = 100; i <= MAX_OF_CAT100; i++)
|
|
||||||
{
|
|
||||||
FalsifyingData(i, prop, improperData);
|
|
||||||
Console.WriteLine(" Complete falsifying No.{0}.", i);
|
|
||||||
}
|
|
||||||
Console.WriteLine(" Complete falsifying Cat.{0}.\n", NUM_OF_PATTERN[CAT100 - 1, 0]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAT200: // 2xx系列全て
|
|
||||||
Console.WriteLine(" Falsifying category No.{0}.", NUM_OF_PATTERN[CAT200 - 1, 0]);
|
|
||||||
for (int i = 200; i <= MAX_OF_CAT200; i++)
|
|
||||||
{
|
|
||||||
FalsifyingData(i, prop, improperData);
|
|
||||||
Console.WriteLine(" Complete falsifying No.{0}.", i);
|
|
||||||
}
|
|
||||||
Console.WriteLine(" Complete falsifying Cat.{0}.\n", NUM_OF_PATTERN[CAT200 - 1, 0]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAT300: // 3xx系列全て
|
|
||||||
Console.WriteLine(" Falsifying category No.{0}.", NUM_OF_PATTERN[CAT300 - 1, 0]);
|
|
||||||
for (int i = 300; i <= MAX_OF_CAT300; i++)
|
|
||||||
{
|
|
||||||
FalsifyingData(i, prop, improperData);
|
|
||||||
Console.WriteLine(" Complete falsifying No.{0}.", i);
|
|
||||||
}
|
|
||||||
Console.WriteLine(" Complete falsifying Cat.{0}.\n", NUM_OF_PATTERN[CAT300 - 1, 0]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAT400: // 4xx系列全て
|
|
||||||
Console.WriteLine(" Falsifying category No.{0}.", NUM_OF_PATTERN[CAT400 - 1, 0]);
|
|
||||||
for (int i = 400; i <= MAX_OF_CAT400; i++)
|
|
||||||
{
|
|
||||||
FalsifyingData(i, prop, improperData);
|
|
||||||
Console.WriteLine(" Complete falsifying No.{0}.", i);
|
|
||||||
}
|
|
||||||
Console.WriteLine(" Complete falsifying Cat.{0}.\n", NUM_OF_PATTERN[CAT400 - 1, 0]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CAT500: // 5xx系列全て
|
|
||||||
Console.WriteLine(" Falsifying category No.{0}.", NUM_OF_PATTERN[CAT500 - 1, 0]);
|
|
||||||
for (int i = 500; i <= MAX_OF_CAT500; i++)
|
|
||||||
{
|
|
||||||
FalsifyingData(i, prop, improperData);
|
|
||||||
Console.WriteLine(" Complete falsifying No.{0}.", i);
|
|
||||||
}
|
|
||||||
Console.WriteLine(" Complete falsifying Cat.{0}.\n", NUM_OF_PATTERN[CAT500 - 1, 0]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // 1パターンのみを個別指定
|
|
||||||
Console.WriteLine(" Falsifying pattern No.{0}.", falsifyingType);
|
|
||||||
FalsifyingData(falsifyingType, prop, improperData);
|
|
||||||
Console.WriteLine(" Complete falsifying No.{0}.\n", falsifyingType);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==================================================
|
//==================================================
|
||||||
// メイン関数
|
// メイン関数
|
||||||
//==================================================
|
//==================================================
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
// コマンドライン引数の数チェック
|
// コマンドライン引数の数チェック
|
||||||
if (args.Length < 3) // データ、ブロック鍵、MAC鍵
|
if (args.Length < 3) // データ、ブロック鍵、MAC鍵
|
||||||
{
|
|
||||||
Usage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 拡張子の判定
|
|
||||||
CheckExtension(args[0], ".bin"); // 入力ファイル名
|
|
||||||
CheckExtension(args[1], ".txt"); // ブロック鍵ファイル名
|
|
||||||
CheckExtension(args[2], ".txt"); // MAC鍵ファイル名
|
|
||||||
|
|
||||||
// ファイルが存在するかを確認
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
{
|
||||||
CheckFileExists(args[i]);
|
Usage();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
// 拡張子の判定
|
||||||
|
CheckExtension(args[0], ".bin"); // 入力ファイル名
|
||||||
|
CheckExtension(args[1], ".txt"); // ブロック鍵ファイル名
|
||||||
|
CheckExtension(args[2], ".txt"); // MAC鍵ファイル名
|
||||||
|
|
||||||
string twlBackupName = args[0];
|
// ファイルが存在するかを確認
|
||||||
string keyName = args[1];
|
for (int i = 0; i < 3; i++)
|
||||||
string macKeyData = args[2];
|
{
|
||||||
|
CheckFileExists(args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int falsifyingType = GetFalsifyingType(args); // オプションがあれば、改ざんのパターン決定
|
string twlBackupName = args[0];
|
||||||
|
string keyName = args[1];
|
||||||
|
string macKeyData = args[2];
|
||||||
|
|
||||||
Properties prop = new Properties(); // インスタンスの作成
|
int falsifyingMode = MODE_ALL;
|
||||||
byte[] twlBackupData = File.ReadAllBytes(twlBackupName); // バックアップデータの読み込み
|
bool isSpecifyMode = false;
|
||||||
|
if (args.Length >= 5 && args[3].ToUpper().TrimStart('-') == "MODE")
|
||||||
|
{
|
||||||
|
falsifyingMode = GetFalsifyingMode(args[4]); // オプションがあれば、改ざんのパターン決定
|
||||||
|
isSpecifyMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
// 鍵データの読み込み
|
Properties prop = new Properties(); // インスタンスの作成
|
||||||
string[] keyString = File.ReadAllLines(keyName);
|
|
||||||
prop.keyData = new byte[KEY_SIZE];
|
int argTypeIndex = (isSpecifyMode) ? 6 : 4;
|
||||||
for (int i = 0; i < prop.keyData.Length; i++)
|
prop.bkpType = BkpType.NORMAL;
|
||||||
{
|
if (args.Length >= argTypeIndex + 1 && args[argTypeIndex - 1].ToUpper().TrimStart('-') == "TYPE")
|
||||||
prop.keyData[i] = Convert.ToByte(keyString[i], 16);
|
{
|
||||||
}
|
prop.bkpType = GetBackupType(args[argTypeIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
// MAC鍵データの読み込み
|
// バックアップデータの読み込み
|
||||||
string[] macKeyString = File.ReadAllLines(macKeyData);
|
byte[] twlBackupData = File.ReadAllBytes(twlBackupName);
|
||||||
prop.macKeyData = new byte[KEY_SIZE];
|
|
||||||
for (int i = 0; i < prop.keyData.Length; i++)
|
// 鍵データの読み込み
|
||||||
{
|
string[] keyString = File.ReadAllLines(keyName);
|
||||||
prop.macKeyData[i] = Convert.ToByte(macKeyString[i], 16);
|
prop.keyData = new byte[KEY_SIZE];
|
||||||
}
|
for (int i = 0; i < prop.keyData.Length; i++)
|
||||||
|
{
|
||||||
|
prop.keyData[i] = Convert.ToByte(keyString[i], 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAC鍵データの読み込み
|
||||||
|
string[] macKeyString = File.ReadAllLines(macKeyData);
|
||||||
|
prop.macKeyData = new byte[KEY_SIZE];
|
||||||
|
for (int i = 0; i < prop.keyData.Length; i++)
|
||||||
|
{
|
||||||
|
prop.macKeyData[i] = Convert.ToByte(macKeyString[i], 16);
|
||||||
|
}
|
||||||
|
|
||||||
// ファイル名の出力 + 鍵データの dump
|
// ファイル名の出力 + 鍵データの dump
|
||||||
Console.WriteLine("Twl Backup File : {0}", twlBackupName);
|
Console.WriteLine("Twl Backup File : {0}", twlBackupName);
|
||||||
Console.WriteLine("Block Key File : {0} ({1})", keyName, dumpArray(prop.keyData));
|
Console.WriteLine("Block Key File : {0} ({1})", keyName, dumpArray(prop.keyData));
|
||||||
Console.WriteLine("MAC Key File : {0} ({1})", macKeyData, dumpArray(prop.macKeyData));
|
Console.WriteLine("MAC Key File : {0} ({1})", macKeyData, dumpArray(prop.macKeyData));
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
Console.WriteLine("Mode : {0}", getModeString(falsifyingMode));
|
||||||
|
Console.WriteLine("Type : {0}", getBackupTypeString(prop.bkpType));
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
// ひとまず VERIFY だったら検証して終了
|
||||||
|
if (falsifyingMode == MODE_VERIFY)
|
||||||
|
{
|
||||||
|
if (Utility.Verify(twlBackupData, prop.keyData, prop.macKeyData, prop.bkpType))
|
||||||
|
{
|
||||||
|
Console.WriteLine("{0} は検証に成功しました。", twlBackupName);
|
||||||
|
}
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// バックアップデータを復号化
|
||||||
|
prop.decryptedBlocks = Utility.DecryptBackupData(twlBackupData, prop.keyData, prop.bkpType);
|
||||||
|
|
||||||
|
// 出力フォルダを作成
|
||||||
|
prop.SetOutputFolderPath(twlBackupName);
|
||||||
|
|
||||||
// TORIAEZU : ひとまず VERIFY だったら検証して終了
|
//==========================================
|
||||||
if (falsifyingType == VERIFY)
|
// 改ざん&ファイル出力
|
||||||
{
|
Console.WriteLine("Start ------------");
|
||||||
if (Utility.Verify(twlBackupData, prop.keyData, prop.macKeyData))
|
|
||||||
{
|
|
||||||
Console.WriteLine("{0} は検証に成功しました。", twlBackupName);
|
|
||||||
}
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// バックアップデータを復号化
|
SwitchFalsifyingPattern(falsifyingMode, prop);
|
||||||
prop.decryptedBlocks = Utility.DecryptBackupData(twlBackupData, prop.keyData);
|
|
||||||
|
|
||||||
// 出力フォルダを作成
|
Console.WriteLine("Complete --------");
|
||||||
prop.SetOutputFolderPath(twlBackupName);
|
Console.WriteLine("Output Dir: {0}", prop.outFolderPath);
|
||||||
|
|
||||||
//==========================================
|
|
||||||
// 改ざん&ファイル出力
|
|
||||||
Console.WriteLine("Start ------------");
|
|
||||||
|
|
||||||
SwitchFalsifyingPattern(falsifyingType, prop);
|
|
||||||
|
|
||||||
Console.WriteLine("Complete --------");
|
|
||||||
Console.WriteLine("Output Dir: {0}", prop.outFolderPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// byte 配列の 16 進表示
|
// byte 配列の 16 進表示
|
||||||
@ -693,5 +329,44 @@ partial class Program
|
|||||||
return str.TrimEnd();
|
return str.TrimEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// mode の文字列を取得
|
||||||
|
static string getModeString(int mode)
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case MODE_ALL:
|
||||||
|
return "ALL";
|
||||||
|
case MODE_CAT100:
|
||||||
|
return "CATEGORY 1XX";
|
||||||
|
case MODE_CAT200:
|
||||||
|
return "CATEGORY 2XX";
|
||||||
|
case MODE_CAT300:
|
||||||
|
return "CATEGORY 3XX";
|
||||||
|
case MODE_CAT400:
|
||||||
|
return "CATEGORY 4XX";
|
||||||
|
case MODE_CAT500:
|
||||||
|
return "CATEGORY 5XX";
|
||||||
|
case MODE_VERIFY:
|
||||||
|
return "VERIFY";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// type の文字列を取得
|
||||||
|
static string getBackupTypeString(BkpType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case BkpType.NORMAL :
|
||||||
|
return "NORMAL";
|
||||||
|
case BkpType.WITH_PRIVATE_SAVE :
|
||||||
|
return "WITH_PRIVATE_SAVE";
|
||||||
|
case BkpType.LEGACY :
|
||||||
|
return "LEGACY";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user