diff --git a/TwlBkpCheck/Windows/FalsifyTwlBackup/Properties.cs b/TwlBkpCheck/Windows/FalsifyTwlBackup/Properties.cs index 3f3c8a9..fafb379 100644 --- a/TwlBkpCheck/Windows/FalsifyTwlBackup/Properties.cs +++ b/TwlBkpCheck/Windows/FalsifyTwlBackup/Properties.cs @@ -7,22 +7,24 @@ using TwlBackupBlock; namespace FalsifyTwlBackup { - class Properties - { - public Blocks decryptedBlocks; // 復号化されたバックアップデータ - public byte[] keyData; // ブロック暗号化のための鍵データ - public byte[] macKeyData; // MAC生成のための鍵データ - - public string outFolderPath; // 出力フォルダ名 - - public void SetOutputFolderPath(string twlBackupDataName) + class Properties { - // 出力フォルダを入力ファイルと同じディレクトリに - outFolderPath = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(twlBackupDataName)), @"FalsifiedTwlBackup"); - Directory.CreateDirectory(outFolderPath); // 出力フォルダを作成 - } + public Blocks decryptedBlocks; // 復号化されたバックアップデータ + public byte[] keyData; // ブロック暗号化のための鍵データ + public byte[] macKeyData; // MAC生成のための鍵データ - // TODO SetKeyData()とGetKeyData()的なものを用意して、privateにしたい - // TODO 出力ディレクトリを変更可能に - } + public BkpType bkpType; // バックアップの形式。 + + 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 出力ディレクトリを変更可能に + } } diff --git a/TwlBkpCheck/Windows/FalsifyTwlBackup/main.cs b/TwlBkpCheck/Windows/FalsifyTwlBackup/main.cs index 7997da1..7d6969c 100644 --- a/TwlBkpCheck/Windows/FalsifyTwlBackup/main.cs +++ b/TwlBkpCheck/Windows/FalsifyTwlBackup/main.cs @@ -22,6 +22,7 @@ partial class Program 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 SECTION_PRIVATE_SAVE = SECTION_SUB_BANNER + 1; // データの挿入位置 private const int NONE = -1; @@ -45,13 +46,13 @@ partial class Program private const int REAR_DATA = 99; // データ全体の後 // 改ざんパターンの引き数 - private const int ALL = 0; - private const int CAT100 = 1; - private const int CAT200 = 2; - 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 MODE_ALL = 0; + private const int MODE_CAT100 = 1; + private const int MODE_CAT200 = 2; + private const int MODE_CAT300 = 3; + private const int MODE_CAT400 = 4; + private const int MODE_CAT500 = 5; + private const int MODE_VERIFY = 9; // 各カテゴリでの最小番号 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 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 KEY_SIZE = 16; // 鍵のサイズ(16 Byte) private const int HASH_SIZE = 32; // ハッシュのサイズ(32 Byte) @@ -93,22 +94,20 @@ partial class Program static void Usage() { Console.WriteLine("Usage: "); - Console.WriteLine("./FalsifyingTwlBackup.exe BACKUPFILE_NAME KEYFILE_NAME MACKEYFALE_NAME MODE"); - Console.WriteLine(" BACKUPFILE_NAME : *.bin"); - Console.WriteLine(" KEYFILE_NAME : *.txt"); - Console.WriteLine(" MACKEYFALE_NAME : *.txt\n"); + Console.WriteLine("./FalsifyingTwlBackup.exe BACKUP_FILE ENC_KEY_FILE MAC_KEY_FILE [-mode MODE] [-type TYPE]"); + Console.WriteLine(" BACKUP_FILE : *.bin"); + Console.WriteLine(" ENC_KEY_FILE : *.txt"); + Console.WriteLine(" MAC_KEY_FILE : *.txt\n"); Console.WriteLine(" MODE"); - Console.WriteLine(" -all (default) : output all falsifying pattern"); - Console.WriteLine(" -cat CAT_NUM : output all pattern of CAT_NUM category"); - 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"); + Console.WriteLine(" all (default) : output all falsifying pattern"); + Console.WriteLine(" cat:CAT_NUM : output all pattern of CAT_NUM category"); + Console.WriteLine(" ex) -mode cat:100 -> falsifying 100,101,102...."); + Console.WriteLine(" each:PAT_NUM : output PAT_NUM pattern"); + Console.WriteLine(" ex) -mode each:204 -> falsifying 204 only"); + Console.WriteLine(" verify : verify backup file"); Environment.Exit(-1); } - - /// /// 拡張子の判別を行います。 /// @@ -120,13 +119,12 @@ partial class Program if (args.ToLower().EndsWith(extension) == false) { - Console.WriteLine("{0} is not [\"{1}\"] file!", args, extension); - Usage(); + Console.WriteLine("{0} is not [\"{1}\"] file!", args, extension); + Usage(); } return; } - /// /// ファイルの有無を確認します。 /// @@ -136,550 +134,188 @@ partial class Program Debug.Assert(args.Length != 0); if (!File.Exists(args)) { - Console.WriteLine("\"{0}\" is not exists!\n", args); - Usage(); + Console.WriteLine("\"{0}\" is not exists!\n", args); + Usage(); } } - /// /// コマンドライン引数のオプションから処理を決定するためのフラグを立てる /// - /// コマンドライン引数の格納された文字列 + /// コマンドライン引数の格納された文字列 /// 処理判別のためのフラグ - 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のとき - if (args[3].ToUpper().TrimStart('-') == "ALL") - { - return ALL; + return MODE_ALL; } - // -catのとき - else if (args[3].ToUpper().TrimStart('-') == "CAT") + // cat:xxx のとき + 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(); - } - switch (args[4]) - { - case "100": return CAT100; - case "200": return CAT200; - case "300": return CAT300; - case "400": return CAT400; - case "500": return CAT500; - default: Usage(); break; // never reach + case "100": return MODE_CAT100; + case "200": return MODE_CAT200; + case "300": return MODE_CAT300; + case "400": return MODE_CAT400; + case "500": return MODE_CAT500; + default: Usage(); break; // never reach } } - // -eachのとき - else if (args[3].ToUpper().TrimStart('-') == "EACH") + // each:xxx のとき + 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 存在しない処理番号をはじくように - else - { - return Convert.ToInt16(args[4]); - } + return Convert.ToInt16(arg.Substring(PREFIX_STR_EACH.Length)); } // -verify - else if (args[3].ToUpper().TrimStart('-') == "VERIFY") + else if (arg.ToUpper() == "VERIFY") { - return VERIFY; - } + return MODE_VERIFY; } // それ以外 - return ALL; + return MODE_ALL; } - /// - /// 指定されたbyteサイズで、0のみのbyte列を作成します。 + /// コマンドライン引数のオプションからバックアップ形式を指定する /// - /// 作成するデータのサイズ[単位:byte] - /// 作成したデータのbyte列 - // TODO 不正データの作成方法を選べるようにしてもいいかも - static byte[] CreateImproperData(int dataSize) + /// コマンドライン引数の格納された文字列 + /// 処理判別のためのフラグ + static BkpType GetBackupType(string arg) { - byte[] data = new byte[dataSize]; - for (int i = 0; i < data.Length; i++) + // normal のとき + if (arg.ToUpper() == "NORMAL") { - //data[i] = (byte)(i); - data[i] = 0; + return BkpType.NORMAL; } - return data; + + // wps のとき + if (arg.ToUpper() == "WPS") + { + return BkpType.WITH_PRIVATE_SAVE; + } + + // legacy のとき + if (arg.ToUpper() == "LEGACY") + { + return BkpType.LEGACY; + } + + // それ以外 + return BkpType.NORMAL; } - - /// - /// データの差し替えを行います。 - /// - /// 上書き対象となるデータ本体 - /// 上書きする不正データ - static void ReplaceImproperData(AbstractBody dataBlocks, byte[] impData) - { - for (int i = 0; i < impData.Length; i++) - { - if (i < dataBlocks.Length) // 上書き先のデータサイズを超えませんように - { - dataBlocks[i] = impData[i]; - } - } - return; - } - - - /// - /// ※未使用 - /// 暗号化に使用するIVを作成します。 - /// AES方式で、ブロックサイズはAES_BLOCK_SIZE[bit]と同じです。 - /// - /// 生成したivのbyte列 - 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; - } - - - /// - /// 署名のハッシュセットを変更します。 - /// - /// 変更対象となる署名ブロックを有するBlocks - /// 新しいハッシュ値 - /// 変更するブロックセクション - 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; - } - } - } - - - /// - /// byte列を結合します。 - /// - /// 前半部分に来るbyte列 - /// 後半部分に来るbyte列 - /// 連結後のbyte列 - static byte[] MergeByteArray(byte[] front, byte[] rear) - { - return front.Concat(rear).ToArray(); - } - - - /// - /// byte列をbinファイルに出力します。 - /// - /// ファイル名となる改ざんパターンの番号 - /// 出力ディレクトリのパス - /// ファイルに出力するデータ - static void OutputFalsifiedData(int improperNo, string outFolderPath, byte[] data) - { - string outFalsifiedDataPath = Convert.ToString(improperNo) + EXTENSION; // ファイル名を改ざん番号から生成 - outFalsifiedDataPath = Path.Combine(outFolderPath, outFalsifiedDataPath); // 出力ディレクトリとファイル名を結合 - File.WriteAllBytes(outFalsifiedDataPath, data); // 出力 - } - - - /// - /// データ本体とMACとIVをひとつのブロックに結合します。 - /// 必要に応じて不正データを挿入します。 - /// - /// 暗号化するBlockを持つBlocks - /// 暗号化するBlockのセクション - /// バックアップデータに関するインスタンス - /// 挿入する不正データ - /// 挿入する位置 - /// 格納するMAC - /// MACを算出するためのハッシュ値 - /// データ本体、MAC、IVを順に結合したbyte列 - 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; - } - - - /// - /// 各ブロックを暗号化した後、1つの byte 列に結合します。 - /// - /// 暗号化するデータ - /// バックアップデータに関するインスタンス - /// 不正データ - /// 不正データを挿入する位置 - /// ハッシュセット更新の有無 - /// 全てのBlockを暗号化し、連結したbyte列 - 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 : 改ざんに使用する不正データ - //------------------------------------------------------------ - /// - /// パターン番号に応じた改ざんを実行 - /// - /// - /// - /// - 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 : バックアップデータに関するインスタンス - //------------------------------------------------------------ - - /// - /// - /// - /// - /// - 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) { - // コマンドライン引数の数チェック - 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++) + // コマンドライン引数の数チェック + if (args.Length < 3) // データ、ブロック鍵、MAC鍵 { - 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]; - string macKeyData = args[2]; + // ファイルが存在するかを確認 + for (int i = 0; i < 3; i++) + { + CheckFileExists(args[i]); + } + } - int falsifyingType = GetFalsifyingType(args); // オプションがあれば、改ざんのパターン決定 + string twlBackupName = args[0]; + string keyName = args[1]; + string macKeyData = args[2]; - Properties prop = new Properties(); // インスタンスの作成 - byte[] twlBackupData = File.ReadAllBytes(twlBackupName); // バックアップデータの読み込み + int falsifyingMode = MODE_ALL; + bool isSpecifyMode = false; + if (args.Length >= 5 && args[3].ToUpper().TrimStart('-') == "MODE") + { + falsifyingMode = GetFalsifyingMode(args[4]); // オプションがあれば、改ざんのパターン決定 + isSpecifyMode = true; + } - // 鍵データの読み込み - string[] keyString = File.ReadAllLines(keyName); - prop.keyData = new byte[KEY_SIZE]; - for (int i = 0; i < prop.keyData.Length; i++) - { - prop.keyData[i] = Convert.ToByte(keyString[i], 16); - } + Properties prop = new Properties(); // インスタンスの作成 + + int argTypeIndex = (isSpecifyMode) ? 6 : 4; + prop.bkpType = BkpType.NORMAL; + if (args.Length >= argTypeIndex + 1 && args[argTypeIndex - 1].ToUpper().TrimStart('-') == "TYPE") + { + prop.bkpType = GetBackupType(args[argTypeIndex]); + } - // 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); - } + // バックアップデータの読み込み + byte[] twlBackupData = File.ReadAllBytes(twlBackupName); + + // 鍵データの読み込み + string[] keyString = File.ReadAllLines(keyName); + 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 - Console.WriteLine("Twl Backup File : {0}", twlBackupName); - Console.WriteLine("Block Key File : {0} ({1})", keyName, dumpArray(prop.keyData)); - Console.WriteLine("MAC Key File : {0} ({1})", macKeyData, dumpArray(prop.macKeyData)); + // ファイル名の出力 + 鍵データの dump + Console.WriteLine("Twl Backup File : {0}", twlBackupName); + Console.WriteLine("Block Key File : {0} ({1})", keyName, dumpArray(prop.keyData)); + 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) - { - if (Utility.Verify(twlBackupData, prop.keyData, prop.macKeyData)) - { - Console.WriteLine("{0} は検証に成功しました。", twlBackupName); - } - Environment.Exit(0); - } + //========================================== + // 改ざん&ファイル出力 + Console.WriteLine("Start ------------"); - // バックアップデータを復号化 - prop.decryptedBlocks = Utility.DecryptBackupData(twlBackupData, prop.keyData); + SwitchFalsifyingPattern(falsifyingMode, prop); - // 出力フォルダを作成 - prop.SetOutputFolderPath(twlBackupName); - - //========================================== - // 改ざん&ファイル出力 - Console.WriteLine("Start ------------"); - - SwitchFalsifyingPattern(falsifyingType, prop); - - Console.WriteLine("Complete --------"); - Console.WriteLine("Output Dir: {0}", prop.outFolderPath); + Console.WriteLine("Complete --------"); + Console.WriteLine("Output Dir: {0}", prop.outFolderPath); } // byte 配列の 16 進表示 @@ -693,5 +329,44 @@ partial class Program 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 ""; + } + } +} }