From cea5fe49f90263d191cbd772089b2a66615c3dfc Mon Sep 17 00:00:00 2001 From: d0k3 Date: Tue, 27 Mar 2018 00:28:24 +0200 Subject: [PATCH] Fix ARM9 crashes with injected H&S apps --- arm9/source/game/ncch.h | 18 ++++++++++++++---- arm9/source/utils/gameutil.c | 22 +++++++++++++--------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/arm9/source/game/ncch.h b/arm9/source/game/ncch.h index f798444..323d33b 100644 --- a/arm9/source/game/ncch.h +++ b/arm9/source/game/ncch.h @@ -33,17 +33,27 @@ // see: https://www.3dbrew.org/wiki/NCCH/Extended_Header // very limited, contains only required stuff typedef struct { + // SCI (system control info) char name[8]; - u8 reserved[0x5]; + u8 reserved0[0x5]; u8 flag; // bit 1 for SD, bit 0 for compressed .code u16 remaster_version; u8 sci_data[0x30]; u8 dependencies[0x180]; - u8 sys_info[0x40]; - u8 aci_data[0x200]; + u64 savedata_size; + u64 jump_id; + u8 reserved1[0x30]; + // ACI (access control info) + u64 aci_title_id; + u32 aci_core_version; + u8 aci_data[0x200 - 0xC]; + // signature and key u8 signature[0x100]; u8 public_key[0x100]; - u8 aci_limit_data[0x200]; + // limitACI (access control info) + u64 aci_limit_title_id; + u32 aci_limit_core_version; + u8 aci_limit_data[0x200 - 0xC]; } __attribute__((packed)) NcchExtHeader; // see: https://www.3dbrew.org/wiki/NCCH#NCCH_Header diff --git a/arm9/source/utils/gameutil.c b/arm9/source/utils/gameutil.c index dc55470..96a2616 100644 --- a/arm9/source/utils/gameutil.c +++ b/arm9/source/utils/gameutil.c @@ -1303,7 +1303,7 @@ u32 BuildCiaFromNcchFile(const char* path_ncch, const char* path_cia) { // load NCCH header / extheader, get save size && title id if (LoadNcchHeaders(&ncch, &exthdr, NULL, path_ncch, 0) == 0) { - save_size = getle32(exthdr.sys_info); + save_size = (u32) exthdr.savedata_size; has_exthdr = true; } else if (LoadNcchHeaders(&ncch, NULL, NULL, path_ncch, 0) != 0) { return 1; @@ -1375,7 +1375,7 @@ u32 BuildCiaFromNcsdFile(const char* path_ncsd, const char* path_cia) { // load first content NCCH / extheader if (LoadNcchHeaders(&ncch, &exthdr, NULL, path_ncsd, NCSD_CNT0_OFFSET) != 0) return 1; - save_size = getle32(exthdr.sys_info); + save_size = (u32) exthdr.savedata_size; // build the CIA stub CiaStub* cia = (CiaStub*) malloc(sizeof(CiaStub)); @@ -1844,6 +1844,7 @@ u32 CheckHealthAndSafetyInject(const char* hsdrv) { u32 InjectHealthAndSafety(const char* path, const char* destdrv) { NcchHeader ncch; + NcchExtHeader exthdr; // write permissions if (!CheckWritePermissions(destdrv)) @@ -1867,12 +1868,12 @@ u32 InjectHealthAndSafety(const char* path, const char* destdrv) { } // check input file / crypto - if ((LoadNcchHeaders(&ncch, NULL, NULL, path, 0) != 0) || + if ((LoadNcchHeaders(&ncch, &exthdr, NULL, path, 0) != 0) || !(NCCH_IS_CXI(&ncch)) || (SetupNcchCrypto(&ncch, NCCH_NOCRYPTO) != 0)) return 1; // check crypto, get sig - if ((LoadNcchHeaders(&ncch, NULL, NULL, path_cxi, 0) != 0) || + if ((LoadNcchHeaders(&ncch, &exthdr, NULL, path_cxi, 0) != 0) || (SetupNcchCrypto(&ncch, NCCH_NOCRYPTO) != 0) || !(NCCH_IS_CXI(&ncch))) return 1; u8 sig[0x100]; @@ -1890,14 +1891,17 @@ u32 InjectHealthAndSafety(const char* path, const char* destdrv) { if (CryptNcchNcsdBossFirmFile(path, path_cxi, GAME_NCCH, CRYPTO_DECRYPT, 0, 0, NULL, NULL) != 0) ret = 1; - // fix up the injected H&S NCCH header (copy H&S signature, title ID) - if ((ret == 0) && (LoadNcchHeaders(&ncch, NULL, NULL, path_cxi, 0) == 0)) { - UINT bw; + // fix up the injected H&S NCCH header / extheader (copy H&S signature, title ID to multiple locations) + if ((ret == 0) && (LoadNcchHeaders(&ncch, &exthdr, NULL, path_cxi, 0) == 0)) { ncch.programId = tid_hs; ncch.partitionId = tid_hs; + exthdr.jump_id = tid_hs; + exthdr.aci_title_id = tid_hs; + exthdr.aci_limit_title_id = tid_hs; memcpy(ncch.signature, sig, 0x100); - if ((fvx_qwrite(path_cxi, &ncch, 0, sizeof(NcchHeader), &bw) != FR_OK) || - (bw != sizeof(NcchHeader))) + sha_quick(ncch.hash_exthdr, &exthdr, 0x400, SHA256_MODE); + if ((fvx_qwrite(path_cxi, &ncch, 0, sizeof(NcchHeader), NULL) != FR_OK) || + (fvx_qwrite(path_cxi, &exthdr, NCCH_EXTHDR_OFFSET, sizeof(NcchExtHeader), NULL) != FR_OK)) ret = 1; } else ret = 1;