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

View File

@ -1,14 +1,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <ogcsys.h>
#include "sys.h"
#include "malloc.h"
#include "mload.h"
#include "ehcmodule_elf.h"
/* Constants */
#define CERTS_LEN 0x280
#define CERTS_LEN 0x280
/* Variables */
static const char certs_fs[] ATTRIBUTE_ALIGN(32) = "/sys/cert.sys";
@ -29,75 +29,77 @@ void __Sys_PowerCallback(void)
Sys_Shutdown();
}
bool isIOSstub(u8 ios_number)
{
u32 tmd_size;
tmd_view *ios_tmd;
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 = (tmd_view *)memalign( 32, (tmd_size+31)&(~31) );
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;
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 isIOSstub(u8 ios_number)
{
u32 tmd_size = 0;
tmd_view *ios_tmd;
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;
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)
{
if(isIOSstub(ios)) return false;
if (isIOSstub(ios))
return false;
mload_close();
if(IOS_ReloadIOS(ios)>=0)
if (IOS_ReloadIOS(ios) >= 0)
{
if (IOS_GetVersion() != 249 && IOS_GetVersion() != 250)
{
if (mload_init() >= 0)
{
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);
}
}
@ -125,17 +127,20 @@ void Sys_Reboot(void)
void Sys_Shutdown(void)
{
/* Poweroff console */
if(CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE) {
if (CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE)
{
s32 ret;
/* Set LED mode */
ret = CONF_GetIdleLedMode();
if(ret >= 0 && ret <= 2)
if (ret >= 0 && ret <= 2)
STM_SetLedMode(ret);
/* Shutdown to idle */
STM_ShutdownToIdle();
} else {
}
else
{
/* Shutdown to standby */
STM_ShutdownToStandby();
}
@ -144,21 +149,22 @@ void Sys_Shutdown(void)
void Sys_LoadMenu(void)
{
int HBC = 0;
char * sig = (char *)0x80001804;
if( sig[0] == 'S' &&
sig[1] == 'T' &&
sig[2] == 'U' &&
sig[3] == 'B' &&
sig[4] == 'H' &&
sig[5] == 'A' &&
sig[6] == 'X' &&
sig[7] == 'X')
char *sig = (char *)0x80001804;
if (sig[0] == 'S' &&
sig[1] == 'T' &&
sig[2] == 'U' &&
sig[3] == 'B' &&
sig[4] == 'H' &&
sig[5] == 'A' &&
sig[6] == 'X' &&
sig[7] == 'X')
{
HBC=1; // Exit to HBC
HBC = 1; // Exit to HBC
}
/* Homebrew Channel stub */
if (HBC == 1) {
if (HBC == 1)
{
exit(0);
}
/* Return to the Wii system menu */
@ -183,9 +189,10 @@ s32 Sys_GetCerts(signed_blob **certs, u32 *len)
IOS_Close(fd);
/* Set values */
if (ret > 0) {
if (ret > 0)
{
*certs = certificates;
*len = sizeof(certificates);
*len = sizeof(certificates);
}
return ret;

View File

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

View File

@ -1,6 +1,5 @@
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <ogc/pad.h>
#include <unistd.h>
@ -16,6 +15,7 @@
#include "sha1.h"
#include "menu.h"
#include "iospatch.h"
#include "malloc.h"
// Turn upper and lower into a full title ID
#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
if (ES_GetDataDir(title, filepath) >= 0 ) {
u32 tmd_size;
u32 tmd_size = 0;
static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
ret = ES_GetStoredTMDSize(title, &tmd_size);
@ -265,62 +265,86 @@ const char* GetSysMenuVersionString(u16 version)
return VersionLookupTable[version % 32][version / 32];
};
static char* GetTitleExec(u64 tId, bool tweaked)
static u32 GetSysMenuBootContent(void)
{
u32 size;
const u8 buffer[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
s32 ret;
u32 cid = 0;
u32 size = 0;
signed_blob *s_tmd = NULL;
s32 ret = ES_GetStoredTMDSize(0x100000002LL, &size);
signed_blob* tmdRaw = (signed_blob*)buffer;
ret = ES_GetStoredTMD(0x100000002LL, tmdRaw, size);
if (ret < 0)
ret = ES_GetStoredTMDSize(0x100000002LL, &size);
if (!size)
{
printf("Error! ES_GetStoredTMDSize: Failed! (Error: %d)\n", ret);
return NULL;
printf("Error! ES_GetStoredTMDSize failed (ret=%i)\n", ret);
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);
if (!path)
return NULL;
ret = ES_GetStoredTMD(0x100000002LL, (u8*)s_tmd, size);
if (ret < 0)
{
printf("Error! ES_GetStoredTMD failed (ret=%i)\n", ret);
free(s_tmd);
return 0;
}
if(tweaked)
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);
tmd *p_tmd = SIGNATURE_PAYLOAD(s_tmd);
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()
{
char* path = GetTitleExec(0x100000002LL, true);
if (!path)
char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
if (!GetSysMenuExecPath(path, true))
return false;
u32 size = 0;
NANDGetFileSize(path, &size);
free(path);
if (size > 0)
return true;
else
return false;
return (size > 0);
}
static bool BackUpPriiloader()
{
char* path = GetTitleExec(0x100000002LL, false);
if (!path)
char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
if (!GetSysMenuExecPath(path, false))
return false;
u32 size = 0;
s32 ret = NANDBackUpFile(path, "/tmp/priiload.app", &size);
free(path);
if (ret < 0)
{
printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret);
@ -334,23 +358,19 @@ static bool BackUpPriiloader()
static bool MoveMenu(bool restore)
{
char* srcPath = GetTitleExec(0x100000002LL, restore);
if (!srcPath)
ATTRIBUTE_ALIGN(0x20)
char srcPath[ISFS_MAXPATH], dstPath[ISFS_MAXPATH];
if (!GetSysMenuBootContent())
return false;
char* dstPath = GetTitleExec(0x100000002LL, !restore);
if (!dstPath)
{
free(srcPath);
return false;
}
GetSysMenuExecPath(srcPath, restore);
GetSysMenuExecPath(dstPath, !restore);
u32 size = 0;
s32 ret = NANDBackUpFile(srcPath, dstPath, &size);
if (ret < 0)
{
free(srcPath);
free(dstPath);
printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret);
return false;
}
@ -358,23 +378,19 @@ static bool MoveMenu(bool restore)
u32 checkSize = 0;
ret = NANDGetFileSize(dstPath, &checkSize);
free(srcPath);
free(dstPath);
return (checkSize == size);
}
static bool RestorePriiloader()
{
char* dstPath = GetTitleExec(0x100000002LL, false);
if (!dstPath)
return false;
char dstPath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
if (!GetSysMenuExecPath(dstPath, false));
u32 size = 0;
s32 ret = NANDBackUpFile("/tmp/priiload.app", dstPath, &size);
if (ret < 0)
{
free(dstPath);
printf("Error! NANDBackUpFile: Failed! (Error: %d)\n", ret);
return false;
}
@ -382,8 +398,6 @@ static bool RestorePriiloader()
u32 checkSize = 0;
ret = NANDGetFileSize(dstPath, &checkSize);
free(dstPath);
return (checkSize == size && checkSize == gPriiloaderSize);
}
@ -453,56 +467,30 @@ static void CleanupPriiloaderLeftOvers(bool retain)
static bool CompareHashes(bool priiloader)
{
char* dstPath = NULL;
char* srcPath = GetTitleExec(0x100000002LL, false);
ATTRIBUTE_ALIGN(0x20)
char srcPath[ISFS_MAXPATH], dstPath[ISFS_MAXPATH] = "/tmp/priiload.app";
if (!srcPath)
if (!GetSysMenuExecPath(srcPath, false))
return false;
if (priiloader)
{
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;
}
}
if (!priiloader)
GetSysMenuExecPath(dstPath, true);
u32 sizeA = 0;
u32 sizeB = 0;
u8* dataA = NANDLoadFile(srcPath, &sizeA);
if (!dataA)
{
free(srcPath);
free(dstPath);
return false;
}
u8* dataB = NANDLoadFile(dstPath, &sizeB);
if (!dataA)
if (!dataB)
{
free(srcPath);
free(dstPath);
free(dataA);
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(dataB);
@ -971,9 +959,9 @@ skipChecks:
{
if (restored)
{
char* path = GetTitleExec(0x100000002LL, true);
char path[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
GetSysMenuExecPath(path, true);
NANDDeleteFile(path);
free(path);
}
}
}