diff --git a/CMakeLists.txt b/CMakeLists.txt index d237f046..0b4b79ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ if(APPLE) endif() set(_3DSTOOL_MAJOR 1) set(_3DSTOOL_MINOR 2) -set(_3DSTOOL_PATCHLEVEL 2) +set(_3DSTOOL_PATCHLEVEL 3) if(NOT MSVC_IDE AND NOT XCODE_VERSION AND NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() diff --git a/README.md b/README.md index 54274bba..81eb48bc 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ An all-in-one tool for extracting/creating 3ds roms. - v1.2.0 @ 2018.06.03 - Support auto encryption fully - v1.2.1 @ 2018.07.26 - Support openssl 1.1.0 - v1.2.2 @ 2018.08.27 - Fix not encrypt bug +- v1.2.3 @ 2018.09.03 - Fix extract cxi without exefs bug ### v1.1 diff --git a/bin/ext_key.txt b/bin/ext_key.txt index 4d9bfbfc..cba51343 100644 --- a/bin/ext_key.txt +++ b/bin/ext_key.txt @@ -1661,5 +1661,6 @@ 000400000F711300 1D7C4C84CD379BF6F5C761A9FF231394 000400000F711400 05ECFDAF4523E89731D6C7DAF8F2187E 000400000F711900 D626917A7152D30EB538365D644569E8 +000400000F711F00 AC73C3A018E83E89FA41A139BF054569 000400000F712000 60423DBB2E17052D3E04ABB04351F74D 000400000FF3E300 AA9B98FB66563D5E847A619E4D03DF15 diff --git a/src/ncch.cpp b/src/ncch.cpp index 9492a738..93a4818c 100644 --- a/src/ncch.cpp +++ b/src/ncch.cpp @@ -162,52 +162,63 @@ bool CNcch::ExtractFile() { bResult = false; } - if (m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1] != 0) + if (!m_sExeFsFileName.empty()) { - Fseek(m_fpNcch, m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2], SEEK_SET); - ExeFsSuperBlock exeFsSuperBlock; - fread(&exeFsSuperBlock, sizeof(exeFsSuperBlock), 1, m_fpNcch); - calculateCounter(kAesCtrTypeExeFs); - if (m_nEncryptMode == kEncryptModeFixedKey || m_nEncryptMode == kEncryptModeAuto) - { - FEncryptAesCtrData(&exeFsSuperBlock, m_Key[kEncryptKeyIndexOld], m_Counter, sizeof(exeFsSuperBlock), 0); - } - if (CExeFs::IsExeFsSuperBlock(exeFsSuperBlock)) + if (m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1] != 0) { Fseek(m_fpNcch, m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2], SEEK_SET); - u8* pExeFs = new u8[static_cast(m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1])]; - fread(pExeFs, 1, static_cast(m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1]), m_fpNcch); + ExeFsSuperBlock exeFsSuperBlock; + fread(&exeFsSuperBlock, sizeof(exeFsSuperBlock), 1, m_fpNcch); + calculateCounter(kAesCtrTypeExeFs); if (m_nEncryptMode == kEncryptModeFixedKey || m_nEncryptMode == kEncryptModeAuto) { - n64 nXorOffset = 0; - FEncryptAesCtrData(pExeFs + nXorOffset, m_Key[kEncryptKeyIndexOld], m_Counter, sizeof(exeFsSuperBlock), nXorOffset); - nXorOffset += sizeof(exeFsSuperBlock); - FEncryptAesCtrData(pExeFs + nXorOffset, m_Key[kEncryptKeyIndexNew], m_Counter, exeFsSuperBlock.m_Header[0].size, nXorOffset); - nXorOffset += exeFsSuperBlock.m_Header[0].size; - FEncryptAesCtrData(pExeFs + nXorOffset, m_Key[kEncryptKeyIndexOld], m_Counter, m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1] - nXorOffset, nXorOffset); + FEncryptAesCtrData(&exeFsSuperBlock, m_Key[kEncryptKeyIndexOld], m_Counter, sizeof(exeFsSuperBlock), 0); } - FILE* fp = UFopen(m_sExeFsFileName.c_str(), USTR("wb")); - if (fp == nullptr) + if (CExeFs::IsExeFsSuperBlock(exeFsSuperBlock)) { - bResult = false; + Fseek(m_fpNcch, m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2], SEEK_SET); + u8* pExeFs = new u8[static_cast(m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1])]; + fread(pExeFs, 1, static_cast(m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1]), m_fpNcch); + if (m_nEncryptMode == kEncryptModeFixedKey || m_nEncryptMode == kEncryptModeAuto) + { + n64 nXorOffset = 0; + FEncryptAesCtrData(pExeFs + nXorOffset, m_Key[kEncryptKeyIndexOld], m_Counter, sizeof(exeFsSuperBlock), nXorOffset); + nXorOffset += sizeof(exeFsSuperBlock); + FEncryptAesCtrData(pExeFs + nXorOffset, m_Key[kEncryptKeyIndexNew], m_Counter, exeFsSuperBlock.m_Header[0].size, nXorOffset); + nXorOffset += exeFsSuperBlock.m_Header[0].size; + FEncryptAesCtrData(pExeFs + nXorOffset, m_Key[kEncryptKeyIndexOld], m_Counter, m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1] - nXorOffset, nXorOffset); + } + FILE* fp = UFopen(m_sExeFsFileName.c_str(), USTR("wb")); + if (fp == nullptr) + { + bResult = false; + } + else + { + if (m_bVerbose) + { + UPrintf(USTR("save: %") PRIUS USTR("\n"), m_sExeFsFileName.c_str()); + } + fwrite(pExeFs, 1, static_cast(m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1]), fp); + fclose(fp); + } + delete[] pExeFs; } else { - if (m_bVerbose) - { - UPrintf(USTR("save: %") PRIUS USTR("\n"), m_sExeFsFileName.c_str()); - } - fwrite(pExeFs, 1, static_cast(m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1]), fp); - fclose(fp); + bResult = false; + extractFile(m_sExeFsFileName, m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2], m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1], true, USTR("exefs")); } - delete[] pExeFs; } - else + else if (m_bVerbose) { - bResult = false; - extractFile(m_sExeFsFileName, m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2], m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1], true, USTR("exefs")); + UPrintf(USTR("INFO: %") PRIUS USTR(" is not exists, %") PRIUS USTR(" will not be create\n"), USTR("exefs"), m_sExeFsFileName.c_str()); } } + else if (m_nOffsetAndSize[kOffsetSizeIndexExeFs * 2 + 1] != 0 && m_bVerbose) + { + UPrintf(USTR("INFO: %") PRIUS USTR(" is not extract\n"), USTR("exefs")); + } m_nKeyIndex = kEncryptKeyIndexNew; calculateCounter(kAesCtrTypeRomFs); if (!extractFile(m_sRomFsFileName, m_nOffsetAndSize[kOffsetSizeIndexRomFs * 2], m_nOffsetAndSize[kOffsetSizeIndexRomFs * 2 + 1], false, USTR("romfs")))