diff --git a/injector/source/patcher.c b/injector/source/patcher.c index e1af719..97b9bc7 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -70,7 +70,7 @@ static int file_open(IFile *file, FS_ArchiveID id, const char *path, int flags){ return IFile_Open(file, archive, ppath, flags); } -static int patch_secureinfo(){ +static int load_secureinfo(){ IFile file; Result ret; u64 total; @@ -78,33 +78,18 @@ static int patch_secureinfo(){ if(secureinfo[0] == 0xFF) return 0; - ret = file_open(&file, ARCHIVE_SDMC, "/SecureInfo_A", FS_OPEN_READ); + ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ); if(R_SUCCEEDED(ret)){ ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo)); IFile_Close(&file); - if(R_SUCCEEDED(ret) && total == sizeof(secureinfo)){ - ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_WRITE | FS_OPEN_CREATE); - if(R_SUCCEEDED(ret)){ - ret = IFile_Write(&file, &total, secureinfo, sizeof(secureinfo), FS_WRITE_FLUSH); - IFile_Close(&file); - } - secureinfo[0] = 0xFF; // we repurpose this byte as status - } - } - else { // get file from NAND - ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_READ); - if(R_SUCCEEDED(ret)){ - ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo)); - IFile_Close(&file); - if(R_SUCCEEDED(ret) && total == sizeof(secureinfo)) - secureinfo[0] = 0xFF; - } + if(R_SUCCEEDED(ret) && total == sizeof(secureinfo)) + secureinfo[0] = 0xFF; } return ret; } -static int open_config(){ +static int load_config(){ IFile file; Result ret; u64 total; @@ -122,151 +107,165 @@ static int open_config(){ } u32 patch_code(u64 progid, u8 *code, u32 size){ - if( progid == 0x0004003000008F02LL || // USA Menu - progid == 0x0004003000008202LL || // JPN Menu - progid == 0x0004003000009802LL || // EUR Menu - progid == 0x000400300000A102LL || // CHN Menu - progid == 0x000400300000A902LL || // KOR Menu - progid == 0x000400300000B102LL // TWN Menu - ){ - static const u8 regionFreePattern[] = { - 0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3 - }; - static const u8 regionFreePatch[] = { - 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 - }; + switch(progid){ - patch_memory(code, size, - regionFreePattern, - sizeof(regionFreePattern), -16, - regionFreePatch, - sizeof(regionFreePatch), 1 - ); - } - else if(progid == 0x0004013000002C02LL){ // NIM - static const u8 blockAutoUpdatesPattern[] = { - 0x25, 0x79, 0x0B, 0x99 - }; - static const u8 blockAutoUpdatesPatch[] = { - 0xE3, 0xA0 - }; - static const u8 blockEShopUpdateCheckPattern[] = { - 0x30, 0xB5, 0xF1, 0xB0 - }; - static const u8 blockEShopUpdateCheckPatch[] = { - 0x00, 0x20, 0x08, 0x60, 0x70, 0x47 - }; - static const u8 countryRespPattern[] = { - 0x01, 0x20, 0x01, 0x90, 0x22, 0x46, 0x06, 0x9B - }; - static const char countryRespPatchModel[] = { - 0x06, 0x9A, 0x03, 0x20, 0x90, 0x47, 0x55, 0x21, 0x01, 0x70, 0x53, 0x21, 0x41, 0x70, 0x00, 0x21, - 0x81, 0x70, 0x60, 0x61, 0x00, 0x20 - }; - const char *country; - char countryRespPatch[sizeof(countryRespPatchModel)]; + case 0x0004003000008F02LL: // USA Menu + case 0x0004003000008202LL: // EUR Menu + case 0x0004003000009802LL: // JPN Menu + case 0x000400300000A102LL: // CHN Menu + case 0x000400300000A902LL: // KOR Menu + case 0x000400300000B102LL: // TWN Menu + { + static const u8 regionFreePattern[] = { + 0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3 + }; + static const u8 regionFreePatch[] = { + 0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 + }; - patch_memory(code, size, - blockAutoUpdatesPattern, - sizeof(blockAutoUpdatesPattern), 0, - blockAutoUpdatesPatch, - sizeof(blockAutoUpdatesPatch), 1 - ); - patch_memory(code, size, - blockEShopUpdateCheckPattern, - sizeof(blockEShopUpdateCheckPattern), 0, - blockEShopUpdateCheckPatch, - sizeof(blockEShopUpdateCheckPatch), 1 - ); - if(R_SUCCEEDED(patch_secureinfo())){ - switch(secureinfo[0x100]){ - case 1: country = "US"; break; - case 2: country = "GB"; break; // sorry rest-of-Europe, you have to change this - case 3: country = "AU"; break; - case 4: country = "CN"; break; - case 5: country = "KR"; break; - case 6: country = "TW"; break; - default: case 0: country = "JP"; break; + patch_memory(code, size, + regionFreePattern, + sizeof(regionFreePattern), -16, + regionFreePatch, + sizeof(regionFreePatch), 1 + ); + break; + } + + case 0x0004013000002C02LL: // NIM + { + static const u8 blockAutoUpdatesPattern[] = { + 0x25, 0x79, 0x0B, 0x99 + }; + static const u8 blockAutoUpdatesPatch[] = { + 0xE3, 0xA0 + }; + static const u8 blockEShopUpdateCheckPattern[] = { + 0x30, 0xB5, 0xF1, 0xB0 + }; + static const u8 blockEShopUpdateCheckPatch[] = { + 0x00, 0x20, 0x08, 0x60, 0x70, 0x47 + }; + static const u8 countryRespPattern[] = { + 0x01, 0x20, 0x01, 0x90, 0x22, 0x46, 0x06, 0x9B + }; + static const char countryRespPatchModel[] = { + 0x06, 0x9A, 0x03, 0x20, 0x90, 0x47, 0x55, 0x21, 0x01, 0x70, 0x53, 0x21, 0x41, 0x70, 0x00, 0x21, + 0x81, 0x70, 0x60, 0x61, 0x00, 0x20 + }; + const char *country; + char countryRespPatch[sizeof(countryRespPatchModel)]; + + patch_memory(code, size, + blockAutoUpdatesPattern, + sizeof(blockAutoUpdatesPattern), 0, + blockAutoUpdatesPatch, + sizeof(blockAutoUpdatesPatch), 1 + ); + patch_memory(code, size, + blockEShopUpdateCheckPattern, + sizeof(blockEShopUpdateCheckPattern), 0, + blockEShopUpdateCheckPatch, + sizeof(blockEShopUpdateCheckPatch), 1 + ); + if(R_SUCCEEDED(load_secureinfo())){ + switch(secureinfo[0x100]){ + case 1: country = "US"; break; + case 2: country = "GB"; break; // sorry rest-of-Europe, you have to change this + case 3: country = "AU"; break; + case 4: country = "CN"; break; + case 5: country = "KR"; break; + case 6: country = "TW"; break; + default: case 0: country = "JP"; break; + } + + // patch XML response Country + memcpy(countryRespPatch, + countryRespPatchModel, + sizeof(countryRespPatchModel) + ); + countryRespPatch[6] = country[0]; + countryRespPatch[10] = country[1]; + patch_memory(code, size, + countryRespPattern, + sizeof(countryRespPattern), 0, + countryRespPatch, + sizeof(countryRespPatch), 1 + ); } - - // patch XML response Country - memcpy(countryRespPatch, - countryRespPatchModel, - sizeof(countryRespPatchModel) - ); - countryRespPatch[6] = country[0]; - countryRespPatch[10] = country[1]; - patch_memory(code, size, - countryRespPattern, - sizeof(countryRespPattern), 0, - countryRespPatch, - sizeof(countryRespPatch), 1 - ); + break; } - } - else if( - progid == 0x0004001000021000LL || // USA MSET - progid == 0x0004001000020000LL || // JPN MSET - progid == 0x0004001000022000LL || // EUR MSET - progid == 0x0004001000026000LL || // CHN MSET - progid == 0x0004001000027000LL || // KOR MSET - progid == 0x0004001000028000LL // TWN MSET - ){ - if(R_SUCCEEDED(open_config()) && ((config >> 5) & 0x1)){ - static const u16 VerPattern[] = u"Ver."; - const u32 currentFirm = ((config >> 12) & 0x1); - const u32 currentNand = ((config >> 13) & 0x3); - patch_memory(code, size, - VerPattern, - sizeof(VerPattern) - sizeof(u16), 0, - currentNand ? ((currentNand == 1) ? ((currentFirm == 1) ? u" Emu" : u"Emu9") : u"Emu2") : - ((currentFirm == 1) ? u" Sys" : u"Sys9"), - sizeof(VerPattern) - sizeof(u16), 1 - ); + case 0x0004001000021000LL: // USA MSET + case 0x0004001000020000LL: // JPN MSET + case 0x0004001000022000LL: // EUR MSET + case 0x0004001000026000LL: // CHN MSET + case 0x0004001000027000LL: // KOR MSET + case 0x0004001000028000LL: // TWN MSET + { + if(R_SUCCEEDED(load_config()) && ((config >> 5) & 0x1)){ + static const u16 verPattern[] = u"Ver."; + const u32 currentFirm = ((config >> 12) & 0x1); + const u32 currentNand = ((config >> 13) & 0x3); + + patch_memory(code, size, + verPattern, + sizeof(verPattern) - sizeof(u16), 0, + currentNand ? ((currentNand == 1) ? ((currentFirm == 1) ? u" Emu" : u"Emu9") : u"Emu2") : + ((currentFirm == 1) ? u" Sys" : u"Sys9"), + sizeof(verPattern) - sizeof(u16), 1 + ); + } + break; } - } - else if (progid == 0x0004013000008002LL){ // NS - static const u8 stopCartUpdatesPattern[] = { - 0x0C, 0x18, 0xE1, 0xD8 - }; - static const u8 stopCartUpdatesPatch[] = { - 0x0B, 0x18, 0x21, 0xC8 - }; - patch_memory(code, size, - stopCartUpdatesPattern, - sizeof(stopCartUpdatesPattern), 0, - stopCartUpdatesPatch, - sizeof(stopCartUpdatesPatch), 2 - ); - } - else if(progid == 0x0004013000001702LL){ // CFG - static const u8 secureinfoSigCheckPattern[] = { - 0x06, 0x46, 0x10, 0x48, 0xFC - }; - static const u8 secureinfoSigCheckPatch[] = { - 0x00, 0x26 - }; - static const u16 secureinfoFilenamePattern[] = u"SecureInfo_"; - static const u16 secureinfoFilenamePatch[] = u"C"; + case 0x0004013000008002LL: // NS + { + static const u8 stopCartUpdatesPattern[] = { + 0x0C, 0x18, 0xE1, 0xD8 + }; + static const u8 stopCartUpdatesPatch[] = { + 0x0B, 0x18, 0x21, 0xC8 + }; - // disable SecureInfo signature check - patch_memory(code, size, - secureinfoSigCheckPattern, - sizeof(secureinfoSigCheckPattern), 0, - secureinfoSigCheckPatch, - sizeof(secureinfoSigCheckPatch), 1 - ); - if(R_SUCCEEDED(patch_secureinfo())){ - // use SecureInfo_C patch_memory(code, size, - secureinfoFilenamePattern, - sizeof(secureinfoFilenamePattern) - sizeof(u16), - sizeof(secureinfoFilenamePattern) - sizeof(u16), - secureinfoFilenamePatch, - sizeof(secureinfoFilenamePatch) - sizeof(u16), 2 + stopCartUpdatesPattern, + sizeof(stopCartUpdatesPattern), 0, + stopCartUpdatesPatch, + sizeof(stopCartUpdatesPatch), 2 ); + break; + } + + case 0x0004013000001702LL: // CFG + { + static const u8 secureinfoSigCheckPattern[] = { + 0x06, 0x46, 0x10, 0x48, 0xFC + }; + static const u8 secureinfoSigCheckPatch[] = { + 0x00, 0x26 + }; + static const u16 secureinfoFilenamePattern[] = u"SecureInfo_"; + static const u16 secureinfoFilenamePatch[] = u"C"; + + // disable SecureInfo signature check + patch_memory(code, size, + secureinfoSigCheckPattern, + sizeof(secureinfoSigCheckPattern), 0, + secureinfoSigCheckPatch, + sizeof(secureinfoSigCheckPatch), 1 + ); + if(R_SUCCEEDED(load_secureinfo())){ + // use SecureInfo_C + patch_memory(code, size, + secureinfoFilenamePattern, + sizeof(secureinfoFilenamePattern) - sizeof(u16), + sizeof(secureinfoFilenamePattern) - sizeof(u16), + secureinfoFilenamePatch, + sizeof(secureinfoFilenamePatch) - sizeof(u16), 2 + ); + } + break; } }