Further clean-up of the patcher code
This commit is contained in:
parent
ac9bdc7665
commit
c80ac985fe
@ -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);
|
return IFile_Open(file, archive, ppath, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int patch_secureinfo(){
|
static int load_secureinfo(){
|
||||||
IFile file;
|
IFile file;
|
||||||
Result ret;
|
Result ret;
|
||||||
u64 total;
|
u64 total;
|
||||||
@ -78,33 +78,18 @@ static int patch_secureinfo(){
|
|||||||
if(secureinfo[0] == 0xFF)
|
if(secureinfo[0] == 0xFF)
|
||||||
return 0;
|
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)){
|
if(R_SUCCEEDED(ret)){
|
||||||
ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo));
|
ret = IFile_Read(&file, &total, secureinfo, sizeof(secureinfo));
|
||||||
IFile_Close(&file);
|
IFile_Close(&file);
|
||||||
if(R_SUCCEEDED(ret) && total == sizeof(secureinfo)){
|
if(R_SUCCEEDED(ret) && total == sizeof(secureinfo))
|
||||||
ret = file_open(&file, ARCHIVE_NAND_RW, "/sys/SecureInfo_C", FS_OPEN_WRITE | FS_OPEN_CREATE);
|
secureinfo[0] = 0xFF;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_config(){
|
static int load_config(){
|
||||||
IFile file;
|
IFile file;
|
||||||
Result ret;
|
Result ret;
|
||||||
u64 total;
|
u64 total;
|
||||||
@ -122,151 +107,165 @@ static int open_config(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 patch_code(u64 progid, u8 *code, u32 size){
|
u32 patch_code(u64 progid, u8 *code, u32 size){
|
||||||
if( progid == 0x0004003000008F02LL || // USA Menu
|
switch(progid){
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
patch_memory(code, size,
|
case 0x0004003000008F02LL: // USA Menu
|
||||||
regionFreePattern,
|
case 0x0004003000008202LL: // EUR Menu
|
||||||
sizeof(regionFreePattern), -16,
|
case 0x0004003000009802LL: // JPN Menu
|
||||||
regionFreePatch,
|
case 0x000400300000A102LL: // CHN Menu
|
||||||
sizeof(regionFreePatch), 1
|
case 0x000400300000A902LL: // KOR Menu
|
||||||
);
|
case 0x000400300000B102LL: // TWN Menu
|
||||||
}
|
{
|
||||||
else if(progid == 0x0004013000002C02LL){ // NIM
|
static const u8 regionFreePattern[] = {
|
||||||
static const u8 blockAutoUpdatesPattern[] = {
|
0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3
|
||||||
0x25, 0x79, 0x0B, 0x99
|
};
|
||||||
};
|
static const u8 regionFreePatch[] = {
|
||||||
static const u8 blockAutoUpdatesPatch[] = {
|
0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1
|
||||||
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,
|
patch_memory(code, size,
|
||||||
blockAutoUpdatesPattern,
|
regionFreePattern,
|
||||||
sizeof(blockAutoUpdatesPattern), 0,
|
sizeof(regionFreePattern), -16,
|
||||||
blockAutoUpdatesPatch,
|
regionFreePatch,
|
||||||
sizeof(blockAutoUpdatesPatch), 1
|
sizeof(regionFreePatch), 1
|
||||||
);
|
);
|
||||||
patch_memory(code, size,
|
break;
|
||||||
blockEShopUpdateCheckPattern,
|
}
|
||||||
sizeof(blockEShopUpdateCheckPattern), 0,
|
|
||||||
blockEShopUpdateCheckPatch,
|
case 0x0004013000002C02LL: // NIM
|
||||||
sizeof(blockEShopUpdateCheckPatch), 1
|
{
|
||||||
);
|
static const u8 blockAutoUpdatesPattern[] = {
|
||||||
if(R_SUCCEEDED(patch_secureinfo())){
|
0x25, 0x79, 0x0B, 0x99
|
||||||
switch(secureinfo[0x100]){
|
};
|
||||||
case 1: country = "US"; break;
|
static const u8 blockAutoUpdatesPatch[] = {
|
||||||
case 2: country = "GB"; break; // sorry rest-of-Europe, you have to change this
|
0xE3, 0xA0
|
||||||
case 3: country = "AU"; break;
|
};
|
||||||
case 4: country = "CN"; break;
|
static const u8 blockEShopUpdateCheckPattern[] = {
|
||||||
case 5: country = "KR"; break;
|
0x30, 0xB5, 0xF1, 0xB0
|
||||||
case 6: country = "TW"; break;
|
};
|
||||||
default: case 0: country = "JP"; break;
|
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
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,
|
case 0x0004001000021000LL: // USA MSET
|
||||||
VerPattern,
|
case 0x0004001000020000LL: // JPN MSET
|
||||||
sizeof(VerPattern) - sizeof(u16), 0,
|
case 0x0004001000022000LL: // EUR MSET
|
||||||
currentNand ? ((currentNand == 1) ? ((currentFirm == 1) ? u" Emu" : u"Emu9") : u"Emu2") :
|
case 0x0004001000026000LL: // CHN MSET
|
||||||
((currentFirm == 1) ? u" Sys" : u"Sys9"),
|
case 0x0004001000027000LL: // KOR MSET
|
||||||
sizeof(VerPattern) - sizeof(u16), 1
|
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,
|
case 0x0004013000008002LL: // NS
|
||||||
stopCartUpdatesPattern,
|
{
|
||||||
sizeof(stopCartUpdatesPattern), 0,
|
static const u8 stopCartUpdatesPattern[] = {
|
||||||
stopCartUpdatesPatch,
|
0x0C, 0x18, 0xE1, 0xD8
|
||||||
sizeof(stopCartUpdatesPatch), 2
|
};
|
||||||
);
|
static const u8 stopCartUpdatesPatch[] = {
|
||||||
}
|
0x0B, 0x18, 0x21, 0xC8
|
||||||
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";
|
|
||||||
|
|
||||||
// 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,
|
patch_memory(code, size,
|
||||||
secureinfoFilenamePattern,
|
stopCartUpdatesPattern,
|
||||||
sizeof(secureinfoFilenamePattern) - sizeof(u16),
|
sizeof(stopCartUpdatesPattern), 0,
|
||||||
sizeof(secureinfoFilenamePattern) - sizeof(u16),
|
stopCartUpdatesPatch,
|
||||||
secureinfoFilenamePatch,
|
sizeof(stopCartUpdatesPatch), 2
|
||||||
sizeof(secureinfoFilenamePatch) - sizeof(u16), 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user