(Hopefully) fix unsuspecting crashes when retaining Priiloader (#7)

* "memalign is busted apparently"

* accidentally used ES_GetTMDView

* "static u32 cid" - hero of time
This commit is contained in:
thepikachugamer 2024-02-12 21:19:57 -05:00 committed by GitHub
parent b520bc7f88
commit 8c0269a8bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 188 additions and 199 deletions

View File

@ -1,9 +1,8 @@
#include <stdio.h> #include <stdio.h>
#include <malloc.h>
#include <string.h> #include <string.h>
#include "fileops.h" #include "fileops.h"
#include "malloc.h"
bool FSOPFileExists(const char* file) bool FSOPFileExists(const char* file)
{ {
@ -85,7 +84,7 @@ s32 FSOPReadOpenFile(FILE* fp, void* buffer, u32 offset, u32 length)
s32 FSOPReadOpenFileA(FILE* fp, void** buffer, u32 offset, u32 length) s32 FSOPReadOpenFileA(FILE* fp, void** buffer, u32 offset, u32 length)
{ {
*buffer = memalign(32, length); *buffer = memalign32(length);
if (!*buffer) if (!*buffer)
return -1; return -1;

11
source/malloc.h Normal file
View File

@ -0,0 +1,11 @@
#include <stdlib.h>
static inline void *memalign32(size_t size)
{
return aligned_alloc(0x20, (size + 0x1F) & ~0x1F);
}
static inline void *memalign64(size_t size)
{
return aligned_alloc(0x40, (size + 0x3F) & ~0x3F);
}

View File

@ -1,10 +1,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <ogcsys.h> #include <ogcsys.h>
#include <malloc.h>
#include <string.h> #include <string.h>
#include "nand.h" #include "nand.h"
#include "malloc.h"
#include "fileops.h" #include "fileops.h"
/* Buffer */ /* Buffer */
@ -118,7 +118,7 @@ u8* NANDReadFromFile(const char* path, u32 offset, u32 length, u32* size)
if (!length) if (!length)
length = IOS_Seek(fd, 0, SEEK_END); length = IOS_Seek(fd, 0, SEEK_END);
u8* data = (u8*)memalign(0x40, length); u8* data = memalign64(length);
if (!data) if (!data)
{ {
*size = 0; *size = 0;
@ -155,9 +155,10 @@ u8* NANDLoadFile(const char* path, u32* size)
s32 NANDWriteFileSafe(const char* path, u8* data, u32 size) s32 NANDWriteFileSafe(const char* path, u8* data, u32 size)
{ {
char tmpPath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(64);
NANDInitialize(); NANDInitialize();
char* tmpPath = (char*)memalign(0x40, ISFS_MAXPATH);
u32 i; u32 i;
for (i = strlen(path); i > 0; --i) for (i = strlen(path); i > 0; --i)
@ -175,43 +176,29 @@ s32 NANDWriteFileSafe(const char* path, u8* data, u32 size)
ret = ISFS_CreateFile(tmpPath, 0, 3, 3, 3); ret = ISFS_CreateFile(tmpPath, 0, 3, 3, 3);
if (ret < 0) if (ret < 0)
{
free(tmpPath);
return ret; return ret;
}
} }
else else if (ret < 0)
{ {
if (ret < 0) return ret;
{
free(tmpPath);
return ret;
}
} }
s32 fd = IOS_Open(tmpPath, 2); s32 fd = IOS_Open(tmpPath, 2);
if (fd < 0) if (fd < 0)
{
free(tmpPath);
return fd; return fd;
}
ret = IOS_Write(fd, data, size); ret = IOS_Write(fd, data, size);
IOS_Close(fd); IOS_Close(fd);
if (ret != size) if (ret != size)
{
free(tmpPath);
return ret - 3; return ret - 3;
}
if (strcmp(tmpPath, path)) if (strcmp(tmpPath, path))
ret = ISFS_Rename(tmpPath, path); ret = ISFS_Rename(tmpPath, path);
else else
ret = 0; ret = 0;
free(tmpPath);
return ret; return ret;
} }

View File

@ -1,14 +1,14 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h>
#include <ogcsys.h> #include <ogcsys.h>
#include "sys.h" #include "sys.h"
#include "malloc.h"
#include "mload.h" #include "mload.h"
#include "ehcmodule_elf.h" #include "ehcmodule_elf.h"
/* Constants */ /* Constants */
#define CERTS_LEN 0x280 #define CERTS_LEN 0x280
/* Variables */ /* Variables */
static const char certs_fs[] ATTRIBUTE_ALIGN(32) = "/sys/cert.sys"; static const char certs_fs[] ATTRIBUTE_ALIGN(32) = "/sys/cert.sys";
@ -31,73 +31,75 @@ void __Sys_PowerCallback(void)
bool isIOSstub(u8 ios_number) bool isIOSstub(u8 ios_number)
{ {
u32 tmd_size; u32 tmd_size = 0;
tmd_view *ios_tmd; tmd_view *ios_tmd;
if ((boot2version >= 5) && (ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224))
return true;
if((boot2version >= 5) && ( ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224)) return true; ES_GetTMDViewSize(0x0000000100000000ULL | ios_number, &tmd_size);
if (!tmd_size)
{
// getting size failed. invalid or fake tmd for sure!
// gprintf("failed to get tmd for ios %d\n",ios_number);
return true;
}
ios_tmd = memalign32(tmd_size);
if (!ios_tmd)
{
// gprintf("failed to mem align the TMD struct!\n");
return true;
}
memset(ios_tmd, 0, tmd_size);
ES_GetTMDView(0x0000000100000000ULL | ios_number, (u8 *)ios_tmd, tmd_size);
// gprintf("IOS %d is rev %d(0x%x) with tmd size of %u and %u contents\n",ios_number,ios_tmd->title_version,ios_tmd->title_version,tmd_size,ios_tmd->num_contents);
/*Stubs have a few things in common:
- title version : it is mostly 65280 , or even better : in hex the last 2 digits are 0.
example : IOS 60 rev 6400 = 0x1900 = 00 = stub
- exception for IOS21 which is active, the tmd size is 592 bytes (or 140 with the views)
- the stub ios' have 1 app of their own (type 0x1) and 2 shared apps (type 0x8001).
eventho the 00 check seems to work fine , we'll only use other knowledge as well cause some
people/applications install an ios with a stub rev >_> ...*/
u8 Version = ios_tmd->title_version;
ES_GetTMDViewSize(0x0000000100000000ULL | ios_number, &tmd_size); if ((boot2version >= 5) && (ios_number == 249 || ios_number == 250) && (Version < 18))
if (!tmd_size) return true;
{ if ((ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224) && (Version < 4))
//getting size failed. invalid or fake tmd for sure! return true;
//gprintf("failed to get tmd for ios %d\n",ios_number); // version now contains the last 2 bytes. as said above, if this is 00, its a stub
return true; if (Version == 0)
} {
ios_tmd = (tmd_view *)memalign( 32, (tmd_size+31)&(~31) ); if ((ios_tmd->num_contents == 3) && (ios_tmd->contents[0].type == 1 && ios_tmd->contents[1].type == 0x8001 && ios_tmd->contents[2].type == 0x8001))
if(!ios_tmd) {
{ // gprintf("IOS %d is a stub\n",ios_number);
//gprintf("failed to mem align the TMD struct!\n"); free(ios_tmd);
return true; return true;
} }
memset(ios_tmd , 0, tmd_size); else
ES_GetTMDView(0x0000000100000000ULL | ios_number, (u8*)ios_tmd , tmd_size); {
//gprintf("IOS %d is rev %d(0x%x) with tmd size of %u and %u contents\n",ios_number,ios_tmd->title_version,ios_tmd->title_version,tmd_size,ios_tmd->num_contents); // gprintf("IOS %d is active\n",ios_number);
/*Stubs have a few things in common: free(ios_tmd);
- title version : it is mostly 65280 , or even better : in hex the last 2 digits are 0. return false;
example : IOS 60 rev 6400 = 0x1900 = 00 = stub }
- exception for IOS21 which is active, the tmd size is 592 bytes (or 140 with the views) }
- the stub ios' have 1 app of their own (type 0x1) and 2 shared apps (type 0x8001). // gprintf("IOS %d is active\n",ios_number);
eventho the 00 check seems to work fine , we'll only use other knowledge as well cause some free(ios_tmd);
people/applications install an ios with a stub rev >_> ...*/ return false;
u8 Version = ios_tmd->title_version;
if((boot2version >= 5) && (ios_number == 249 || ios_number == 250) && (Version < 18)) return true;
if(( ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224) && (Version < 4)) return true;
//version now contains the last 2 bytes. as said above, if this is 00, its a stub
if ( Version == 0 )
{
if ( ( ios_tmd->num_contents == 3) && (ios_tmd->contents[0].type == 1 && ios_tmd->contents[1].type == 0x8001 && ios_tmd->contents[2].type == 0x8001) )
{
//gprintf("IOS %d is a stub\n",ios_number);
free(ios_tmd);
return true;
}
else
{
//gprintf("IOS %d is active\n",ios_number);
free(ios_tmd);
return false;
}
}
//gprintf("IOS %d is active\n",ios_number);
free(ios_tmd);
return false;
} }
bool loadIOS(int ios) bool loadIOS(int ios)
{ {
if(isIOSstub(ios)) return false; if (isIOSstub(ios))
return false;
mload_close(); mload_close();
if(IOS_ReloadIOS(ios)>=0) if (IOS_ReloadIOS(ios) >= 0)
{ {
if (IOS_GetVersion() != 249 && IOS_GetVersion() != 250) if (IOS_GetVersion() != 249 && IOS_GetVersion() != 250)
{ {
if (mload_init() >= 0) if (mload_init() >= 0)
{ {
data_elf my_data_elf; data_elf my_data_elf;
mload_elf((void *) ehcmodule_elf, &my_data_elf); mload_elf((void *)ehcmodule_elf, &my_data_elf);
mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, 0x47); mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, 0x47);
} }
} }
@ -125,17 +127,20 @@ void Sys_Reboot(void)
void Sys_Shutdown(void) void Sys_Shutdown(void)
{ {
/* Poweroff console */ /* Poweroff console */
if(CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE) { if (CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE)
{
s32 ret; s32 ret;
/* Set LED mode */ /* Set LED mode */
ret = CONF_GetIdleLedMode(); ret = CONF_GetIdleLedMode();
if(ret >= 0 && ret <= 2) if (ret >= 0 && ret <= 2)
STM_SetLedMode(ret); STM_SetLedMode(ret);
/* Shutdown to idle */ /* Shutdown to idle */
STM_ShutdownToIdle(); STM_ShutdownToIdle();
} else { }
else
{
/* Shutdown to standby */ /* Shutdown to standby */
STM_ShutdownToStandby(); STM_ShutdownToStandby();
} }
@ -144,21 +149,22 @@ void Sys_Shutdown(void)
void Sys_LoadMenu(void) void Sys_LoadMenu(void)
{ {
int HBC = 0; int HBC = 0;
char * sig = (char *)0x80001804; char *sig = (char *)0x80001804;
if( sig[0] == 'S' && if (sig[0] == 'S' &&
sig[1] == 'T' && sig[1] == 'T' &&
sig[2] == 'U' && sig[2] == 'U' &&
sig[3] == 'B' && sig[3] == 'B' &&
sig[4] == 'H' && sig[4] == 'H' &&
sig[5] == 'A' && sig[5] == 'A' &&
sig[6] == 'X' && sig[6] == 'X' &&
sig[7] == 'X') sig[7] == 'X')
{ {
HBC=1; // Exit to HBC HBC = 1; // Exit to HBC
} }
/* Homebrew Channel stub */ /* Homebrew Channel stub */
if (HBC == 1) { if (HBC == 1)
{
exit(0); exit(0);
} }
/* Return to the Wii system menu */ /* Return to the Wii system menu */
@ -183,9 +189,10 @@ s32 Sys_GetCerts(signed_blob **certs, u32 *len)
IOS_Close(fd); IOS_Close(fd);
/* Set values */ /* Set values */
if (ret > 0) { if (ret > 0)
{
*certs = certificates; *certs = certificates;
*len = sizeof(certificates); *len = sizeof(certificates);
} }
return ret; return ret;

View File

@ -2,12 +2,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <malloc.h>
#include <ogcsys.h> #include <ogcsys.h>
#include "sha1.h" #include "sha1.h"
#include "utils.h" #include "utils.h"
#include "malloc.h"
s32 Title_ZeroSignature(signed_blob *p_sig) s32 Title_ZeroSignature(signed_blob *p_sig)
{ {
@ -79,7 +78,7 @@ s32 Title_GetList(u64 **outbuf, u32 *outlen)
{ {
u64 *titles = NULL; u64 *titles = NULL;
u32 len, nb_titles; u32 nb_titles;
s32 ret; s32 ret;
/* Get number of titles */ /* Get number of titles */
@ -87,11 +86,9 @@ s32 Title_GetList(u64 **outbuf, u32 *outlen)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* Calculate buffer lenght */
len = round_up(sizeof(u64) * nb_titles, 32);
/* Allocate memory */ /* Allocate memory */
titles = memalign(32, len); titles = memalign32(nb_titles * sizeof(u64));
if (!titles) if (!titles)
return -1; return -1;
@ -126,7 +123,7 @@ s32 Title_GetTicketViews(u64 tid, tikview **outbuf, u32 *outlen)
return ret; return ret;
/* Allocate memory */ /* Allocate memory */
views = (tikview *)memalign(32, sizeof(tikview) * nb_views); views = memalign32(sizeof(tikview) * nb_views);
if (!views) if (!views)
return -1; return -1;
@ -161,7 +158,7 @@ s32 Title_GetTMD(u64 tid, signed_blob **outbuf, u32 *outlen)
return ret; return ret;
/* Allocate memory */ /* Allocate memory */
p_tmd = memalign(32, round_up(len, 32)); p_tmd = memalign32(len);
if (!p_tmd) if (!p_tmd)
return -1; return -1;
@ -290,7 +287,7 @@ s32 Title_GetIOSVersions(u8 **outbuf, u32 *outlen)
} }
/* Allocate memory */ /* Allocate memory */
buffer = (u8 *)memalign(32, cnt); buffer = memalign32(cnt);
if (!buffer) { if (!buffer) {
ret = -1; ret = -1;
goto out; goto out;

View File

@ -1,6 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <malloc.h>
#include <ogcsys.h> #include <ogcsys.h>
#include <ogc/pad.h> #include <ogc/pad.h>
#include <unistd.h> #include <unistd.h>
@ -16,6 +15,7 @@
#include "sha1.h" #include "sha1.h"
#include "menu.h" #include "menu.h"
#include "iospatch.h" #include "iospatch.h"
#include "malloc.h"
// Turn upper and lower into a full title ID // Turn upper and lower into a full title ID
#define TITLE_ID(x,y) (((u64)(x) << 32) | (y)) #define TITLE_ID(x,y) (((u64)(x) << 32) | (y))
@ -97,7 +97,7 @@ u64 get_title_ios(u64 title) {
// Check to see if title exists // Check to see if title exists
if (ES_GetDataDir(title, filepath) >= 0 ) { if (ES_GetDataDir(title, filepath) >= 0 ) {
u32 tmd_size; u32 tmd_size = 0;
static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
ret = ES_GetStoredTMDSize(title, &tmd_size); ret = ES_GetStoredTMDSize(title, &tmd_size);
@ -265,62 +265,86 @@ const char* GetSysMenuVersionString(u16 version)
return VersionLookupTable[version % 32][version / 32]; return VersionLookupTable[version % 32][version / 32];
}; };
static char* GetTitleExec(u64 tId, bool tweaked) static u32 GetSysMenuBootContent(void)
{ {
u32 size; s32 ret;
const u8 buffer[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); u32 cid = 0;
u32 size = 0;
signed_blob *s_tmd = NULL;
s32 ret = ES_GetStoredTMDSize(0x100000002LL, &size); ret = ES_GetStoredTMDSize(0x100000002LL, &size);
signed_blob* tmdRaw = (signed_blob*)buffer; if (!size)
ret = ES_GetStoredTMD(0x100000002LL, tmdRaw, size);
if (ret < 0)
{ {
printf("Error! ES_GetStoredTMDSize: Failed! (Error: %d)\n", ret); printf("Error! ES_GetStoredTMDSize failed (ret=%i)\n", ret);
return NULL; return 0;
} }
tmd* smTMD = SIGNATURE_PAYLOAD(tmdRaw); s_tmd = memalign32(size);
if (!s_tmd)
{
printf("Error! Memory allocation failed!\n");
return 0;
}
char* path = (char*)memalign(0x40, ISFS_MAXPATH); ret = ES_GetStoredTMD(0x100000002LL, (u8*)s_tmd, size);
if (!path) if (ret < 0)
return NULL; {
printf("Error! ES_GetStoredTMD failed (ret=%i)\n", ret);
free(s_tmd);
return 0;
}
if(tweaked) tmd *p_tmd = SIGNATURE_PAYLOAD(s_tmd);
sprintf(path, "/title/%08x/%08x/content/1%.7x.app", TITLE_UPPER(tId), TITLE_LOWER(tId), smTMD->contents[smTMD->boot_index].cid);
else
sprintf(path, "/title/%08x/%08x/content/%.8x.app", TITLE_UPPER(tId), TITLE_LOWER(tId), smTMD->contents[smTMD->boot_index].cid);
return path; for (int i = 0; i < p_tmd->num_contents; i++)
{
tmd_content* content = &p_tmd->contents[i];
if (content->index == p_tmd->boot_index)
{
cid = content->cid;
break;
}
}
free(s_tmd);
if (!cid) printf("Error! Cannot find system menu boot content!\n");
return cid;
}
bool GetSysMenuExecPath(char path[ISFS_MAXPATH], bool mainDOL)
{
u32 cid = GetSysMenuBootContent();
if (!cid) return false;
if (mainDOL) cid |= 0x10000000;
sprintf(path, "/title/00000001/00000002/content/%08x.app", cid);
return true;
} }
bool IsPriiloaderInstalled() bool IsPriiloaderInstalled()
{ {
char* path = GetTitleExec(0x100000002LL, true); char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
if (!path)
return false;
if (!GetSysMenuExecPath(path, true))
return false;
u32 size = 0; u32 size = 0;
NANDGetFileSize(path, &size); NANDGetFileSize(path, &size);
free(path);
if (size > 0) return (size > 0);
return true;
else
return false;
} }
static bool BackUpPriiloader() static bool BackUpPriiloader()
{ {
char* path = GetTitleExec(0x100000002LL, false); char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
if (!path)
if (!GetSysMenuExecPath(path, false))
return false; return false;
u32 size = 0; u32 size = 0;
s32 ret = NANDBackUpFile(path, "/tmp/priiload.app", &size); s32 ret = NANDBackUpFile(path, "/tmp/priiload.app", &size);
free(path);
if (ret < 0) if (ret < 0)
{ {
printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret); printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret);
@ -334,23 +358,19 @@ static bool BackUpPriiloader()
static bool MoveMenu(bool restore) static bool MoveMenu(bool restore)
{ {
char* srcPath = GetTitleExec(0x100000002LL, restore); ATTRIBUTE_ALIGN(0x20)
if (!srcPath) char srcPath[ISFS_MAXPATH], dstPath[ISFS_MAXPATH];
if (!GetSysMenuBootContent())
return false; return false;
char* dstPath = GetTitleExec(0x100000002LL, !restore); GetSysMenuExecPath(srcPath, restore);
if (!dstPath) GetSysMenuExecPath(dstPath, !restore);
{
free(srcPath);
return false;
}
u32 size = 0; u32 size = 0;
s32 ret = NANDBackUpFile(srcPath, dstPath, &size); s32 ret = NANDBackUpFile(srcPath, dstPath, &size);
if (ret < 0) if (ret < 0)
{ {
free(srcPath);
free(dstPath);
printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret); printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret);
return false; return false;
} }
@ -358,23 +378,19 @@ static bool MoveMenu(bool restore)
u32 checkSize = 0; u32 checkSize = 0;
ret = NANDGetFileSize(dstPath, &checkSize); ret = NANDGetFileSize(dstPath, &checkSize);
free(srcPath);
free(dstPath);
return (checkSize == size); return (checkSize == size);
} }
static bool RestorePriiloader() static bool RestorePriiloader()
{ {
char* dstPath = GetTitleExec(0x100000002LL, false); char dstPath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
if (!dstPath)
return false; if (!GetSysMenuExecPath(dstPath, false));
u32 size = 0; u32 size = 0;
s32 ret = NANDBackUpFile("/tmp/priiload.app", dstPath, &size); s32 ret = NANDBackUpFile("/tmp/priiload.app", dstPath, &size);
if (ret < 0) if (ret < 0)
{ {
free(dstPath);
printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret); printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret);
return false; return false;
} }
@ -382,8 +398,6 @@ static bool RestorePriiloader()
u32 checkSize = 0; u32 checkSize = 0;
ret = NANDGetFileSize(dstPath, &checkSize); ret = NANDGetFileSize(dstPath, &checkSize);
free(dstPath);
return (checkSize == size && checkSize == gPriiloaderSize); return (checkSize == size && checkSize == gPriiloaderSize);
} }
@ -453,56 +467,30 @@ static void CleanupPriiloaderLeftOvers(bool retain)
static bool CompareHashes(bool priiloader) static bool CompareHashes(bool priiloader)
{ {
char* dstPath = NULL; ATTRIBUTE_ALIGN(0x20)
char* srcPath = GetTitleExec(0x100000002LL, false); char srcPath[ISFS_MAXPATH], dstPath[ISFS_MAXPATH] = "/tmp/priiload.app";
if (!srcPath) if (!GetSysMenuExecPath(srcPath, false))
return false; return false;
if (priiloader) if (!priiloader)
{ GetSysMenuExecPath(dstPath, true);
dstPath = (char*)memalign(0x40, ISFS_MAXPATH);
if (!dstPath)
{
free(srcPath);
return false;
}
strcpy(dstPath, "/tmp/priiload.app");
}
else
{
dstPath = GetTitleExec(0x100000002LL, true);
if (!dstPath)
{
free(srcPath);
return false;
}
}
u32 sizeA = 0; u32 sizeA = 0;
u32 sizeB = 0; u32 sizeB = 0;
u8* dataA = NANDLoadFile(srcPath, &sizeA); u8* dataA = NANDLoadFile(srcPath, &sizeA);
if (!dataA) if (!dataA)
{
free(srcPath);
free(dstPath);
return false; return false;
}
u8* dataB = NANDLoadFile(dstPath, &sizeB); u8* dataB = NANDLoadFile(dstPath, &sizeB);
if (!dataA) if (!dataB)
{ {
free(srcPath);
free(dstPath);
free(dataA); free(dataA);
return false; return false;
} }
bool ret = !CompareHash(dataA, sizeA, dataB, sizeB); bool ret = (sizeA == sizeB) && !CompareHash(dataA, sizeA, dataB, sizeB);
free(srcPath);
free(dstPath);
free(dataA); free(dataA);
free(dataB); free(dataB);
@ -971,9 +959,9 @@ skipChecks:
{ {
if (restored) if (restored)
{ {
char* path = GetTitleExec(0x100000002LL, true); char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
GetSysMenuExecPath(path, true);
NANDDeleteFile(path); NANDDeleteFile(path);
free(path);
} }
} }
} }