diff --git a/NXTools.sln b/NXTools.sln index 7e78817..89167ac 100644 --- a/NXTools.sln +++ b/NXTools.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2015 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfnd", "lib\libfnd\fnd.vcxproj", "{4D27EDB9-5110-44FE-8CE2-D46C5AD3C55B}" EndProject @@ -36,6 +36,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libes", "lib\libes\es.vcxpr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tiktool", "programs\tiktool\tiktool.vcxproj", "{2200B834-F15A-4C6E-9DDB-6012B9A5C246}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xcitool", "programs\xcitool\xcitool.vcxproj", "{007FF616-7B99-4CB3-84CD-39C47F64FC7E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -108,6 +110,14 @@ Global {2200B834-F15A-4C6E-9DDB-6012B9A5C246}.Release|x64.Build.0 = Release|x64 {2200B834-F15A-4C6E-9DDB-6012B9A5C246}.Release|x86.ActiveCfg = Release|Win32 {2200B834-F15A-4C6E-9DDB-6012B9A5C246}.Release|x86.Build.0 = Release|Win32 + {007FF616-7B99-4CB3-84CD-39C47F64FC7E}.Debug|x64.ActiveCfg = Debug|x64 + {007FF616-7B99-4CB3-84CD-39C47F64FC7E}.Debug|x64.Build.0 = Debug|x64 + {007FF616-7B99-4CB3-84CD-39C47F64FC7E}.Debug|x86.ActiveCfg = Debug|Win32 + {007FF616-7B99-4CB3-84CD-39C47F64FC7E}.Debug|x86.Build.0 = Debug|Win32 + {007FF616-7B99-4CB3-84CD-39C47F64FC7E}.Release|x64.ActiveCfg = Release|x64 + {007FF616-7B99-4CB3-84CD-39C47F64FC7E}.Release|x64.Build.0 = Release|x64 + {007FF616-7B99-4CB3-84CD-39C47F64FC7E}.Release|x86.ActiveCfg = Release|Win32 + {007FF616-7B99-4CB3-84CD-39C47F64FC7E}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -121,5 +131,9 @@ Global {BC2F2D07-BAB3-469C-9C25-8CC54F96F7AB} = {E0863FCC-8E72-490D-BE1B-458F12CA8298} {7BE99936-0D40-410D-944B-4513C2EFF8DC} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C} {2200B834-F15A-4C6E-9DDB-6012B9A5C246} = {E0863FCC-8E72-490D-BE1B-458F12CA8298} + {007FF616-7B99-4CB3-84CD-39C47F64FC7E} = {E0863FCC-8E72-490D-BE1B-458F12CA8298} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {07DCCACC-D10D-47C9-85AE-FB9C54DB7D62} EndGlobalSection EndGlobal diff --git a/programs/xcitool/main.cpp b/programs/xcitool/source/main.cpp similarity index 75% rename from programs/xcitool/main.cpp rename to programs/xcitool/source/main.cpp index def7778..7d66829 100644 --- a/programs/xcitool/main.cpp +++ b/programs/xcitool/source/main.cpp @@ -30,9 +30,10 @@ enum CardClockRate }; static const size_t kXciPageSize = 0x200; -static const size_t kXciHeaderEncOffset = 0xA0; +static const size_t kXciHeaderEncOffset = 0x90; static const size_t kXciHeaderEncSize = 0x70; +#pragma pack (push, 1) struct sXciHeader { char signature[4]; // 0x00 // "HEAD" @@ -86,13 +87,15 @@ struct sKeyDataArea byte_t reserved_01[0x100]; }; // sizeof() = 512*8 (8 pages) -static struct sXciKeyData +#pragma pack (pop) + +struct sXciKeyData { crypto::aes::sAes128Key xci_header_encryption_key; crypto::aes::sAes128Key initial_data_key; crypto::rsa::sRsa2048Key xci_header_signer_key; crypto::rsa::sRsa2048Key card_key_area_oeap_key; -} key_data; +}; /* void getTitleKeyFromInitialData(const byte_t* initialData, crypto::aes::sAes128Key& titleKey) @@ -116,7 +119,7 @@ inline const char* getBoolStr(bool isTrue) inline const char* getRomSizeStr(byte_t rom_size) { - char* str = "unknown"; + const char* str = "unknown"; switch (rom_size) { case (ROM_SIZE_1GB) : @@ -143,7 +146,7 @@ inline const char* getRomSizeStr(byte_t rom_size) inline const char* getCardClockRate(uint32_t acc_ctrl_1) { - char* str = "unknown"; + const char* str = "unknown"; switch (acc_ctrl_1) { case (CLOCK_RATE_25) : @@ -157,18 +160,52 @@ inline const char* getCardClockRate(uint32_t acc_ctrl_1) return str; } +void dumpHxdStyleSector(byte_t* out, size_t len) +{ + // iterate over 0x10 blocks + for (size_t i = 0; i < (len / crypto::aes::kAesBlockSize); i++) + { + // for block i print each byte + for (size_t j = 0; j < crypto::aes::kAesBlockSize; j++) + { + printf("%02X ", out[i*crypto::aes::kAesBlockSize + j]); + } + printf(" "); + for (size_t j = 0; j < crypto::aes::kAesBlockSize; j++) + { + printf("%c", isalnum(out[i*crypto::aes::kAesBlockSize + j]) ? out[i*crypto::aes::kAesBlockSize + j] : '.'); + } + printf("\n"); + } + + /* + for (size_t i = 0; i < len % crypto::aes::kAesBlockSize; i++) + { + printf("%02X ", out[(len / crypto::aes::kAesBlockSize)*crypto::aes::kAesBlockSize + i]); + } + for (size_t i = 0; i < crypto::aes::kAesBlockSize - (len % crypto::aes::kAesBlockSize); i++) + { + printf(" "); + } + for (size_t i = 0; i < len % crypto::aes::kAesBlockSize; i++) + { + printf("%c", out[(len / crypto::aes::kAesBlockSize)*crypto::aes::kAesBlockSize + i]); + } + */ +} + void printXciHeader(const sXciHeader& hdr, bool is_decrypted) { be_uint64_t *aes_iv, *hash; printf("[XCI HEADER]\n"); printf(" Magic: HEAD\n"); - printf(" RomAreaStartPage: 0x%0x (0x" PRIx64 ")\n", hdr.rom_area_start_page.get(), blockToAddr(hdr.rom_area_start_page.get())); + printf(" RomAreaStartPage: 0x%0x (0x%" PRIx64 ")\n", hdr.rom_area_start_page.get(), blockToAddr(hdr.rom_area_start_page.get())); printf(" BackupAreaStartPage: 0x%0x\n", hdr.backup_area_start_page.get()); - printf(" KeyFlag: 0x%x\n", hdr.key_flag); + printf(" KeyFlag: 0x%x\n", hdr.key_flag); printf(" KekIndex: %d\n", hdr.key_flag & 7); printf(" TitleKeyDecIndex: %d\n", (hdr.key_flag >> 4) & 7); - printf(" RomSize: 0x%x (%s)\n", hdr.rom_size, getRomSizeStr(hdr.rom_size)); + printf(" RomSize: 0x%x (%s)\n", hdr.rom_size, getRomSizeStr(hdr.rom_size)); printf(" CardHeaderVersion: %d\n", hdr.card_header_version); printf(" Flags: 0x%x\n", hdr.flags); printf(" AutoBoot: %s\n", getBoolStr(_HAS_BIT(hdr.flags, XCI_FLAG_AUTOBOOT))); @@ -176,15 +213,15 @@ void printXciHeader(const sXciHeader& hdr, bool is_decrypted) printf(" PackageId: 0x%" PRIx64 "\n", hdr.package_id.get()); printf(" ValidDataEndPage: 0x%x (0x%" PRIx64 ")\n", hdr.valid_data_end_page.get(), blockToAddr(hdr.valid_data_end_page.get())); aes_iv = (be_uint64_t*)hdr.encryption_iv; - printf(" AesIv: %" PRIX64 "%" PRIX64"\n", aes_iv[0].get(), aes_iv[1].get()); + printf(" AesIv: %016" PRIX64 "%016" PRIX64"\n", aes_iv[0].get(), aes_iv[1].get()); printf(" PartitionFs:\n"); printf(" Offset: 0x%" PRIx64 "\n", hdr.partition_fs_header_address.get()); printf(" Size: 0x%" PRIx64 "\n", hdr.partition_fs_header_size.get()); hash = (be_uint64_t*)hdr.partition_fs_header_hash; - printf(" Hash: %" PRIX64 "%" PRIX64 "%" PRIX64 "%" PRIX64"\n", hash[0].get(),hash[1].get(),hash[2].get(),hash[3].get()); + printf(" Hash: %016" PRIX64 "%016" PRIX64 "%016" PRIX64 "%016" PRIX64"\n", hash[0].get(),hash[1].get(),hash[2].get(),hash[3].get()); printf(" InitialData:\n"); hash = (be_uint64_t*)hdr.initial_data_hash; - printf(" Hash: %" PRIX64 "%" PRIX64 "%" PRIX64 "%" PRIX64"\n", hash[0].get(),hash[1].get(),hash[2].get(),hash[3].get()); + printf(" Hash: %016" PRIX64 "%016" PRIX64 "%016" PRIX64 "%016" PRIX64"\n", hash[0].get(),hash[1].get(),hash[2].get(),hash[3].get()); printf(" SelSec: 0x%x\n", hdr.sel_sec.get()); printf(" SelT1Key: 0x%x\n", hdr.sel_t1_key.get()); printf(" SelKey: 0x%x\n", hdr.sel_key.get()); @@ -192,7 +229,7 @@ void printXciHeader(const sXciHeader& hdr, bool is_decrypted) if (is_decrypted == true) { - printf(" FwVersion: v%d.%d\n", hdr.fw_version[0].get(), hdr.fw_version[1].get()); + printf(" FwVersion: v%d.%d\n", hdr.fw_version[1].get(), hdr.fw_version[0].get()); printf(" AccCtrl1: 0x%x\n", hdr.acc_ctrl_1.get()); printf(" CardClockRate: %s\n", getCardClockRate(hdr.acc_ctrl_1.get())); printf(" Wait1TimeRead: 0x%x\n", hdr.wait_1_time_read.get()); @@ -202,15 +239,21 @@ void printXciHeader(const sXciHeader& hdr, bool is_decrypted) printf(" FwMode: 0x%x\n", hdr.fw_mode.get()); printf(" CupVersion: %d\n", hdr.cup_version.get()); hash = (be_uint64_t*)hdr.upp_hash; - printf(" UppHash: %" PRIX64 "\n", hash[0].get()); - printf(" CupId: %" PRIx64 "\n", hdr.cup_id.get()); + printf(" UppHash: %016" PRIX64 "\n", hash[0].get()); + printf(" CupId: %016" PRIx64 "\n", hdr.cup_id.get()); + } } void decryptXciHeader(const byte_t* src, byte_t* dst) { + const byte_t* src_iv = ((const sXciHeader*)src)->encryption_iv; byte_t iv[crypto::aes::kAesBlockSize]; - memcpy(iv, ((const sXciHeader*)src)->encryption_iv, crypto::aes::kAesBlockSize); + + for (int i = 0; i < crypto::aes::kAesBlockSize; i++) + { + iv[i] = src_iv[15 - i]; + } // copy plain memcpy(dst, src, kXciHeaderEncOffset); diff --git a/programs/xcitool/xcitool.vcxproj b/programs/xcitool/xcitool.vcxproj new file mode 100644 index 0000000..affaa78 --- /dev/null +++ b/programs/xcitool/xcitool.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {007FF616-7B99-4CB3-84CD-39C47F64FC7E} + xcitool + 10.0.16299.0 + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + true + ..\..\lib\libfnd\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include; + + + + + Level3 + Disabled + true + true + ..\..\lib\libfnd\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include; + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\lib\libfnd\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include; + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\lib\libfnd\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include; + + + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/programs/xcitool/xcitool.vcxproj.filters b/programs/xcitool/xcitool.vcxproj.filters new file mode 100644 index 0000000..bd54fe4 --- /dev/null +++ b/programs/xcitool/xcitool.vcxproj.filters @@ -0,0 +1,25 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Source Files + + + \ No newline at end of file diff --git a/programs/xcitool/xcitool.vcxproj.user b/programs/xcitool/xcitool.vcxproj.user new file mode 100644 index 0000000..be25078 --- /dev/null +++ b/programs/xcitool/xcitool.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file