SysCheck-ModMii-Edition/source/sysCheck.c
wiidev e27137da2e ModMii Edition changes
- Compile with the latest version of devkitPPC
- Reports can be saved to USB storage
- The console ID is masked when uploaded
- All of the assets have been optimised
- Added GitHub continuous integration
2023-03-09 18:42:29 +00:00

1197 lines
37 KiB
C

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <gccore.h>
#include <malloc.h>
#include <fat.h>
#include <unistd.h>
#include <ogc/conf.h>
#include <ogc/es.h>
#include <ogc/ios.h>
#include <ogc/pad.h>
#include <wiiuse/wpad.h>
#include <stdlib.h>
#include <stdarg.h>
#include <di/di.h>
#include <CheckRegion.h>
#include "runtimeiospatch.h"
#include "SysMenuInfo.h"
#include "fatMounter.h"
#include "gecko.h"
#include "gui.h"
#include "languages.h"
#include "mload.h"
#include "sha1.h"
#include "sys.h"
#include "title.h"
#include "tmdIdentification.h"
#include "tmd_dat.h"
#include "update.h"
#include "wiibasics.h"
// Filename
#define REPORT ":/SysCheck.csv"
#define HASHLOG ":/IOSsyscheck.log"
#define VERSION_1_1_0 65536
extern void __exception_setreload(int t);
static u64 current_time = 0;
// Main
int main(int argc, char **argv)
{
__exception_setreload(2);
arguments.AHB_At_Start = AHB_ACCESS;
memset(arguments.skipIOSlist, 0, sizeof(arguments.skipIOSlist));
arguments.skipIOScnt = 0;
arguments.debug = false;
arguments.USB = strlen(argv[0]) && (argv[0][0] == 'U' || argv[0][0] == 'u');
InitGecko();
gprintf(" \n \n==============================================================================\n");
if(argc>=1){
int i;
for(i=0; i<argc; i++){
if(CHECK_ARG("--debug=true")) {
arguments.debug = true;
gprintf("--debug=true\n");
logfile("--debug=true\r\n");
} else if(CHECK_ARG("--forceNoAHBPROT=true")) {
arguments.AHB_At_Start = false;
gprintf("--forceNoAHBPROT=true\n");
logfile("--forceNoAHBPROT=true\r\n");
IOS_ReloadIOS(IOS_GetVersion());
} else if(CHECK_ARG("--skipIOS=")) {
arguments.skipIOSlist[arguments.skipIOScnt] = atoi(CHECK_ARG_VAL("--skipIOS="));
gprintf("skipIOS[%i] = %i\r\n", arguments.skipIOScnt, arguments.skipIOSlist[arguments.skipIOScnt]);
logfile("skipIOS[%i] = %i\r\n", arguments.skipIOScnt, arguments.skipIOSlist[arguments.skipIOScnt]);
arguments.skipIOScnt++;
}
}
}
SysSettings_t SystemInfo = {0};
if(arguments.AHB_At_Start)
SystemInfo.deviceType = IS_WII_U;
else
SystemInfo.deviceType = CONSOLE_UNKNOWN;
memset(SystemInfo.miosInfo, 0, sizeof(SystemInfo.miosInfo));
if (AHB_ACCESS) IosPatch_RUNTIME(true, false, false, true);
SystemInfo.nandAccess = CheckNANDAccess();
// Get and display the current date and time
struct tm today;
time_t rawtime;
time(&rawtime);
today = *localtime(&rawtime);
initGUI();
initLanguages(today);
// Get the console region
printLoading(MSG_GetConsoleRegion);
UpdateTime();
SystemInfo.systemRegion = CONF_GetRegion();
CheckTime();
SystemInfo.shopcode = 0;
if (!CONF_GetShopCode(&SystemInfo.shopcode)) {
strcpy(SystemInfo.country, CONF_CountryCodes[SystemInfo.shopcode]);
} else {
strcpy(SystemInfo.country, TXT_Unknown);
}
// Get the system menu version
printLoading(MSG_GetSysMenuVer);
UpdateTime();
SystemInfo.sysMenuVer = GetSysMenuVersion();
CheckTime();
sysMenu_t systemmenu;
printLoading(MSG_GetHBCVer);
UpdateTime();
homebrew_t homebrew;
homebrew.hbcversion = 0;
homebrew.hbfversion = 0;
homebrew.hbc = HBC_NONE;
homebrew.hbf = HBF_NONE;
homebrew.hbcIOS = 0;
SystemInfo.dvdSupport = 0;
s32 ret = Title_GetVersionNObuf(TITLE_ID(0x00010001, HBC_TID_OPEN));
if (ret<0) {
ret = Title_GetVersionNObuf(TITLE_ID(0x00010001, HBC_TID_LULZ));
if (ret<0) {
ret = Title_GetVersionNObuf(TITLE_ID(0x00010001, HBC_TID_1_0_7));
if (ret<0) {
ret = Title_GetVersionNObuf(TITLE_ID(0x00010001, HBC_TID_JODI));
if (ret<0) {
homebrew.hbc = HBC_HAXX;
ret = Title_GetVersionNObuf(TITLE_ID(0x00010001, HBC_TID_HAXX));
if (ret<0) {
homebrew.hbc = HBC_NONE;
} else {
homebrew.hbc = HBC_HAXX;
homebrew.hbcversion = ret;
}
} else {
homebrew.hbc = HBC_JODI;
homebrew.hbcversion = ret;
}
} else {
homebrew.hbc = HBC_1_0_7;
homebrew.hbcversion = ret;
if (homebrew.hbcversion == 0)
homebrew.hbcversion = VERSION_1_1_0;
}
} else {
homebrew.hbc = HBC_LULZ;
homebrew.hbcversion = (ret != 257) + 1;
}
} else {
homebrew.hbc = HBC_OPEN;
homebrew.hbcversion = (ret == 258) ? 3 : ret; // OHBC or a fork
}
if (homebrew.hbc == HBC_OPEN) {
homebrew.hbcIOS = get_title_ios(TITLE_ID(0x00010001, HBC_TID_OPEN)); // OPEN
} else if (homebrew.hbc == HBC_LULZ) {
homebrew.hbcIOS = get_title_ios(TITLE_ID(0x00010001, HBC_TID_LULZ)); // LULZ
} else if (homebrew.hbc == HBC_1_0_7) {
homebrew.hbcIOS = get_title_ios(TITLE_ID(0x00010001, HBC_TID_1_0_7)); // ????
} else if (homebrew.hbc == HBC_JODI) {
homebrew.hbcIOS = get_title_ios(TITLE_ID(0x00010001, HBC_TID_JODI)); // JODI
} else if (homebrew.hbc == HBC_HAXX) {
homebrew.hbcIOS = get_title_ios(TITLE_ID(0x00010001, HBC_TID_HAXX)); // HAXX
}
ret = Title_GetVersionNObuf(TITLE_ID(0x00010001, 0x48424630)); //HBF0
if (ret<0) {
ret = Title_GetVersionNObuf(TITLE_ID(0x00010001, 0x54484246)); //THBF
if (ret<0) {
homebrew.hbf = HBF_NONE;
} else {
homebrew.hbf = HBF_HBF0;
homebrew.hbfversion = ret;
}
} else {
homebrew.hbf = HBF_THBF;
homebrew.hbfversion = ret;
}
if (AHB_ACCESS) {
DI_Init();
DI_DriveID id;
if(DI_Identify(&id) == 0) {
SystemInfo.dvdSupport = id.rel_date;
}
DI_Close();
}
SystemInfo.sysNinVersion = GetSysMenuNintendoVersion(SystemInfo.sysMenuVer);
SystemInfo.sysMenuRegion = GetSysMenuRegion(SystemInfo.sysMenuVer);
CheckTime();
// Get the running IOS version and revision
printLoading(MSG_GetRunningIOS);
UpdateTime();
SystemInfo.runningIOS = IOS_GetVersion();
SystemInfo.runningIOSRevision = IOS_GetRevision();
CheckTime();
// Get the console ID
printLoading(MSG_GetConsoleID);
UpdateTime();
SystemInfo.deviceID = GetDeviceID();
CheckTime();
// Get the boot2 version
printLoading(MSG_GetBoot2);
UpdateTime();
SystemInfo.boot2version = GetBoot2Version();
CheckTime();
// Get number of titles
printLoading(MSG_GetNrOfTitles);
UpdateTime();
u32 tempTitles;
if (ES_GetNumTitles(&tempTitles) < 0) {
printError(ERR_GetNrOfTitles);
sleep(5);
deinitGUI();
exit(1);
}
s32 nbTitles = tempTitles;
// Allocate the memory for titles
u64 *titles = memalign(32, nbTitles*sizeof(u64));
if (titles == NULL) {
sprintf(MSG_Buffer, ERR_AllocateMemory, titles);
printError(MSG_Buffer);
sleep(5);
deinitGUI();
exit(1);
}
CheckTime();
// Get list of titles
printLoading(MSG_GetTitleList);
UpdateTime();
if (ES_GetTitles(titles, nbTitles) < 0) {
printError(ERR_GetTitleList);
sleep(5);
deinitGUI();
exit(1);
}
int i;
int j;
SystemInfo.countIOS = 0; // Number of IOS
SystemInfo.countStubs = 0; // Number of IOS Stubs
SystemInfo.countBCMIOS = 0; //Number of BC and MIOS. Should be 2.
u32 titleID;
char HashLogBuffer[300][100] = {{0}};
int lines = 0;
// For each titles found
for (i = 0; i < nbTitles; i++)
{
// Skip non-system titles
if (titles[i] >> 32 != 1) {
titles[i] = 0;
continue;
}
titleID = titles[i] & 0xFFFFFFFF;
// Skip BC, MIOS and possible other non-IOS titles
if (titleID > 200 && titleID < 258) {
u32 tmdSize = 0;
if (ES_GetStoredTMDSize(0x0000000100000000ULL | titleID, &tmdSize) < 0) {
titles[i] = 0;
continue;
}
}
// Skip the running IOS, the System Menu, and out of range IOS
if ((titleID > 258 && titleID < 512) || (titleID == 0) || (titleID == 2)) {
titles[i] = 0;
continue;
}
SystemInfo.countIOS++;
}
// Not the most efficient way to remove argument-skipped IOS's, but it works.
int tempSkipIOScnt = arguments.skipIOScnt;
while (tempSkipIOScnt > 0) {
for (i = nbTitles; i--;) {
titleID = titles[i] & 0xFFFFFFFF;
if(arguments.skipIOSlist[tempSkipIOScnt - 1] > 0 && titleID == arguments.skipIOSlist[tempSkipIOScnt - 1]) {
logfile("Skipped IOS %i, titles[%i] = %i\r\n", arguments.skipIOSlist[tempSkipIOScnt - 1], i, titles[i]);
titles[i] = 0;
SystemInfo.countIOS--;
break;
}
}
tempSkipIOScnt--;
}
CheckTime();
// Sort IOS titles
printLoading(MSG_SortTitles);
UpdateTime();
u64 *newTitles = memalign(32, (SystemInfo.countIOS)*sizeof(u64));
u32 cnt = 0;
for (i = 0; i < nbTitles; i++) {
if (titles[i] > 0) {
newTitles[cnt] = titles[i];
cnt++;
}
}
sort(newTitles, SystemInfo.countIOS);
free(titles);
IOS_t ios[SystemInfo.countIOS];
// IOS List Initialization
for (i = SystemInfo.countIOS; i--;) {
ios[i].infoContent = 0;
ios[i].titleID = 0;
ios[i].mloadVersion = 0;
ios[i].baseIOS = -1;
strcpy(ios[i].info, "NULL");
ios[i].isStub = false;
ios[i].revision = 0;
ios[i].infoFakeSignature = false;
ios[i].infoESIdentify = false;
ios[i].infoFlashAccess = false;
ios[i].infoNANDAccess = false;
ios[i].infoBoot2Access = false;
ios[i].infoUSB2 = false;
ios[i].infoVersionPatch = false;
ios[i].infovIOS = false;
}
//MountSD();
NandStartup();
// Check Priiloader
SystemInfo.priiloader = checkSysLoader();
// Check MIOS
if (SystemInfo.nandAccess) get_miosinfo(SystemInfo.miosInfo);
// Check running IOS type so we don't have to reload it later
SystemInfo.runningIOSType = (SystemInfo.deviceType != CONSOLE_WII) && CheckIOSType(SystemInfo.runningIOS, SystemInfo.runningIOSRevision);
// For each titles found
for (i = SystemInfo.countIOS; i--;)
{
ios[i].titleID = newTitles[i] & 0xFFFFFFFF;
// Check if this title is an IOS stub
u32 tmdSize = 0;
tmd *iosTMD = NULL;
signed_blob *iosTMDBuffer = NULL;
// Get the stored TMD size for the title
if (ES_GetStoredTMDSize(0x0000000100000000ULL | ios[i].titleID, &tmdSize) < 0)
{
sprintf(MSG_Buffer, ERR_GetIosTMDSize, ios[i].titleID);
printError(MSG_Buffer);
sleep(5);
deinitGUI();
exit(1);
}
ios[i].infoBeerTicket = CheckBeerTicket(ios[i].titleID);
iosTMDBuffer = (signed_blob*)memalign(32, (tmdSize+31)&(~31));
memset(iosTMDBuffer, 0, tmdSize);
// Get the stored TMD for the title
logfile("Getting TMD for title %d\r\n", ios[i].titleID);
gprintf("Getting TMD for title %d\n", ios[i].titleID);
if (ES_GetStoredTMD(0x0000000100000000ULL | ios[i].titleID, iosTMDBuffer, tmdSize) < 0)
{
sprintf(MSG_Buffer, ERR_GetIosTMD, ios[i].titleID);
printError(MSG_Buffer);
sleep(5);
deinitGUI();
exit(1);
}
iosTMD = (tmd*)SIGNATURE_PAYLOAD(iosTMDBuffer);
// Get the title version
ios[i].titleSize = Title_GetSize_FromTMD(iosTMD);
ios[i].revision = iosTMD->title_version;
ios[i].isStub = false;
ios[i].infoContent = *(u8 *)((u32)iosTMDBuffer+0x1E7);
ios[i].num_contents = iosTMD->num_contents;
gprintf("ios%d rev%d iosTMD->num_contents = %d size=%d\n", ios[i].titleID, ios[i].revision, iosTMD->num_contents, ios[i].titleSize);
logfile("ios%d rev%d iosTMD->num_contents = %d size=%d\r\n", ios[i].titleID, ios[i].revision, iosTMD->num_contents, ios[i].titleSize);
// Check if this is an IOS stub (according to WiiBrew.org)
if (IsKnownStub(ios[i].titleID, ios[i].revision))
ios[i].isStub = true;
else
{
ios[i].isStub = (ios[i].titleID != TID_BC && ios[i].titleID != TID_MIOS && ios[i].titleID != TID_NAND && ios[i].titleID != TID_WFS && ios[i].titleSize < 0x100000);
if (ios[i].isStub) {
gprintf("is stub\n");
logfile("is stub\r\n");
usleep(100000); // A little delay so you can see what stubs were scanned
}
}
if ((!ios[i].isStub || ios[i].titleID == TID_CBOOT2) && (SystemInfo.nandAccess) && (!getInfoFromContent(&ios[i]))) {
// Get the TMD hash
iosTMD->title_id = ((u64)(1) << 32) | 249;
brute_tmd(iosTMD);
sha1 hash;
SHA1((u8 *)iosTMDBuffer, tmdSize, hash);
sprintf(HashLogBuffer[lines], "IOS%d base hash: \r\n%02x %02x %02x %02x, %02x %02x %02x %02x, %02x %02x %02x %02x, %02x %02x %02x %02x, %02x %02x %02x %02x\r\n", \
ios[i].titleID, hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], hash[8], hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15], hash[16], hash[17], hash[18], hash[19]);
lines++;
for (j = 0;j < base_number;j++)
{
// Check hashes
if (memcmp((void*)hash, (u32*)&iosHash[j].hashes, sizeof(sha1)) == 0)
{
if (ios[i].titleID != iosHash[j].base)
ios[i].baseIOS = iosHash[j].base;
strcpy(ios[i].info, iosHash[j].info);
gprintf("is %s\n", ios[i].info);
logfile("is %s\r\n", ios[i].info);
}
}
}
if (ios[i].titleID == TID_BC || ios[i].titleID == TID_MIOS) SystemInfo.countBCMIOS++;
if (ios[i].isStub && !(iosTMD->title_version == 31338) && !(iosTMD->title_version == 65281) && !(iosTMD->title_version == 65535)) SystemInfo.countStubs++;
free(iosTMDBuffer);
}
// Check if this title is an IOS stub
u32 tmdSize = 0;
signed_blob *iosTMDBuffer = NULL;
// Get the stored TMD size for the title
if (ES_GetStoredTMDSize(0x0000000100000000ULL | 2, &tmdSize) < 0)
{
sprintf(MSG_Buffer, ERR_GetIosTMDSize, 2);
printError(MSG_Buffer);
sleep(5);
deinitGUI();
exit(1);
}
iosTMDBuffer = (signed_blob*)memalign(32, (tmdSize+31)&(~31));
memset(iosTMDBuffer, 0, tmdSize);
// Get the stored TMD for the title
if (ES_GetStoredTMD(0x0000000100000000ULL | 2, iosTMDBuffer, tmdSize) < 0)
{
sprintf(MSG_Buffer, ERR_GetIosTMD, 2);
printError(MSG_Buffer);
sleep(5);
deinitGUI();
exit(1);
}
char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
u8 *buffer = 0;
u32 filesize = 0;
iosinfo_t *sysInfo;
// Try to identify the cIOS by the info put in by the installer/ModMii
sysMenuInfoContent = *(u8 *)((u32)iosTMDBuffer+0x1E7);
sprintf(filepath, "/title/00000001/00000002/content/%08x.app", sysMenuInfoContent);
gprintf(filepath);
gprintf("\n");
ret = read_file_from_nand(filepath, &buffer, &filesize);
sysInfo = (iosinfo_t *)(buffer);
if (ret >= 0 && sysInfo != NULL && sysInfo->magicword == 0x1ee7c105 && sysInfo->magicversion == 1)
{
systemmenu.realRevision = sysInfo->version;
systemmenu.hasInfo = true;
sprintf(systemmenu.info, "%s%s", sysInfo->name, sysInfo->versionstring);
if (buffer != NULL) free(buffer);
} else {
systemmenu.realRevision = 0;
systemmenu.hasInfo = false;
strcpy(systemmenu.info, "NONE");
}
NandShutdown();
//UnmountSD();
SystemInfo.countTitles = nbTitles;
nbTitles = SystemInfo.countIOS;
CheckTime();
// Get the certificates from the NAND
printLoading(MSG_GetCertificates);
UpdateTime();
if (!GetCertificates()) {
printError(ERR_GetCertificates);
sleep(5);
deinitGUI();
exit(1);
}
CheckTime();
//Select an IOS to test
WPAD_Init();
PAD_Init();
int selectedIOS = -1;
u32 wpressed;
time_t starttime = time(NULL);
printSelectIOS(MSG_SelectIOS, MSG_All);
bool completeReport = true;
while (difftime (time(NULL),starttime) < 15) {
wpressed = DetectInput(DI_BUTTONS_HELD);
usleep(80000);
if (wpressed & WPAD_BUTTON_RIGHT && selectedIOS < (nbTitles-1)){
selectedIOS++;
starttime = time(NULL);
titleID = newTitles[selectedIOS] & 0xFFFFFFFF;
switch (titleID)
{
case TID_BC:
sprintf(MSG_Buffer, "BC");
break;
case TID_MIOS:
sprintf(MSG_Buffer, "MIOS");
break;
default:
sprintf(MSG_Buffer, "IOS%d", titleID);
break;
}
printSelectIOS(MSG_SelectIOS, MSG_Buffer);
}
if (wpressed & WPAD_BUTTON_LEFT && selectedIOS > -1) {
selectedIOS--;
starttime = time(NULL);
if (selectedIOS > -1) {
titleID = newTitles[selectedIOS] & 0xFFFFFFFF;
switch (titleID)
{
case TID_BC:
sprintf(MSG_Buffer, "BC");
break;
case TID_MIOS:
sprintf(MSG_Buffer, "MIOS");
break;
default:
sprintf(MSG_Buffer, "IOS%d", titleID);
break;
}
printSelectIOS(MSG_SelectIOS, MSG_Buffer);
} else {
printSelectIOS(MSG_SelectIOS, MSG_All);
}
}
/*
if (wpressed & WPAD_BUTTON_PLUS) {
printLoading(MSG_Update);
ret = updateApp();
gprintf("updateApp returned %i\n", ret);
if (ret == 2) {
printSuccess(MSG_NoUpdate);
sleep(5);
starttime = time(NULL);
if (selectedIOS > -1)
printSelectIOS(MSG_SelectIOS, MSG_Buffer);
else
printSelectIOS(MSG_SelectIOS, MSG_All);
} else if (ret >= 0) {
printSuccess(MSG_UpdateSuccess);
sleep(5);
deinitGUI();
exit(0);
} else if (ret < 0) {
printError(MSG_UpdateFail);
sleep(5);
starttime = time(NULL);
if (selectedIOS > -1)
printSelectIOS(MSG_SelectIOS, MSG_Buffer);
else
printSelectIOS(MSG_SelectIOS, MSG_All);
}
}
*/
// Return to the loader
if (wpressed & WPAD_BUTTON_HOME) {
UnmountSD();
UnmountUSB();
deinitGUI();
exit(0);
}
// Return to System Menu
if (wpressed & WPAD_BUTTON_PLUS) {
UnmountSD();
UnmountUSB();
deinitGUI();
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
}
// Shutdown Wii
if (wpressed & WPAD_BUTTON_MINUS) {
UnmountSD();
UnmountUSB();
deinitGUI();
SYS_ResetSystem(SYS_POWEROFF, 0, 0);
}
if (wpressed & WPAD_BUTTON_A) {
break;
}
}
sleep(1); // Without this some controllers don't reconnect correctly (modern libogc issue?)
Wpad_Disconnect();
if (selectedIOS > -1) {
nbTitles = 1;
completeReport = false;
}
// Test vulnerabilities in IOS
for (i = 0; i < nbTitles; i++)
{
if (selectedIOS > -1) i = selectedIOS; //If specific IOS is selected
if (ios[i].titleID == TID_BC) sprintf(MSG_Buffer2, "BC");
else if (ios[i].titleID == TID_MIOS) sprintf(MSG_Buffer2, "MIOS");
else sprintf(MSG_Buffer2, "IOS%d", ios[i].titleID);
sprintf(MSG_Buffer, MSG_TestingIOS, MSG_Buffer2);
printLoadingBar(MSG_Buffer, (100.0/(nbTitles-1)*(i+1)));
if (ios[i].isStub ||
ios[i].titleID == TID_BC ||
ios[i].titleID == TID_MIOS ||
ios[i].titleID == TID_NAND ||
ios[i].titleID == TID_WFS)
{
ios[i].infoFakeSignature = false;
ios[i].infoESIdentify = false;
ios[i].infoFlashAccess = false;
ios[i].infoNANDAccess = false;
ios[i].infoBoot2Access = false;
ios[i].infoUSB2 = false;
if (ios[i].titleID == TID_NAND || ios[i].titleID == TID_WFS) ios[i].infovIOS = true;
}
else
{
// Reload IOS
gprintf("IOS_ReloadIOS(%d)\n", ios[i].titleID);
logfile("IOS_ReloadIOS(%d)\r\n", ios[i].titleID);
if (arguments.USB)
USB_Deinitialize();
if (SystemInfo.deviceType == CONSOLE_WII_U)
IosPatch_FULL(false, false, false, false, ios[i].titleID);
else
IOS_ReloadIOS(ios[i].titleID);
// Test IOS type
gprintf("// Test IOS type\n");
logfile("// Test IOS type\r\n");
if(SystemInfo.deviceType != CONSOLE_WII) ios[i].infovIOS = CheckIOSType(ios[i].titleID, ios[i].revision);
// Test fake signature
gprintf("// Test fake signature\n");
logfile("// Test fake signature\r\n");
ios[i].infoFakeSignature = CheckFakeSignature();
// Test ES Identify
gprintf("// Test ES Identify\n");
logfile("// Test ES Identify\r\n");
ios[i].infoESIdentify = CheckESIdentify();
// Test Flash Access
gprintf("// Test Flash Access\n");
logfile("// Test Flash Access\r\n");
ios[i].infoFlashAccess = CheckFlashAccess();
// Test NAND Access
gprintf("// Test NAND Access\n");
logfile("// Test NAND Access\r\n");
ios[i].infoNANDAccess = CheckNANDAccess();
// Test Boot2 Access
gprintf("// Test Boot2 Access\n");
logfile("// Test Boot2 Access\r\n");
ios[i].infoBoot2Access = CheckBoot2Access();
// Test USB 2.0
gprintf("// Test USB 2.0\n");
logfile("// Test USB 2.0\r\n");
ios[i].infoUSB2 = CheckUSB2(ios[i].titleID);
// Set sysMenuIOSVersion and sysMenuIOSType if currently running the System Menu IOS
if (ios[i].titleID == SystemInfo.sysMenuIOS) {
SystemInfo.sysMenuIOSVersion = ios[i].revision;
SystemInfo.sysMenuIOSType = ios[i].infovIOS;
}
// Check Priiloader
if (!SystemInfo.nandAccess && SystemInfo.priiloader == -2 && ios[i].infoNANDAccess) {
SystemInfo.priiloader = checkSysLoader();
}
// Check Base IOS
if (!SystemInfo.nandAccess && ios[i].infoNANDAccess) {
NandStartup();
int k = 0;
for (k = 0; k < nbTitles; k++) {
if ((ios[i].isStub || ios[i].titleID == TID_BC || ios[i].titleID == TID_MIOS) && ios[i].titleID != TID_CBOOT2) continue;
getInfoFromContent(&ios[k]);
}
NandShutdown();
}
if ((ios[i].titleID==222 || ios[i].titleID==224 || ios[i].titleID==223 || ios[i].titleID==202 || ios[i].titleID==225) && ios[i].baseIOS < 0) {
ret = mload_init();
gprintf("// mload_get_IOS_base()\n");
logfile("// mload_get_IOS_base()\r\n");
ios[i].baseIOS = mload_get_IOS_base();
gprintf("// mload_get_version()\n");
logfile("// mload_get_version()\r\n");
ios[i].mloadVersion = mload_get_version();
mload_close();
}
}
}
//--Generate Report--
UpdateTime();
printLoading(MSG_GenerateReport);
char ReportBuffer[200][100] = {{0}}; // The maximum display length is actually 73
if (SystemInfo.dvdSupport > 0)
formatDate(SystemInfo.dvdSupport, ReportBuffer);
else
sprintf(ReportBuffer[DVD], TXT_NoDVD);
// Display Title
sprintf(ReportBuffer[APP_TITLE], TXT_AppTitle, TXT_AppVersion);
sprintf(ReportBuffer[APP_IOS], TXT_AppIOS, SystemInfo.runningIOSType ? "v" : "", SystemInfo.runningIOS, SystemInfo.runningIOSRevision);
SystemInfo.validregion = SystemInfo.systemRegion >= CONF_REGION_JP && SystemInfo.systemRegion <= CONF_REGION_CN;
// Display the console region
if (SystemInfo.sysNinVersion != 0.0f) {
sprintf(ReportBuffer[TEXT_REGION], "%s: %s", TXT_Region, SystemInfo.validregion ? Regions[SystemInfo.systemRegion] : "");
if (SystemInfo.validregion)
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu, SystemInfo.sysNinVersion, SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
else
strcat(ReportBuffer[SYSMENU], TXT_Unknown);
} else if (systemmenu.hasInfo) {
SystemInfo.sysNinVersion = GetSysMenuNintendoVersion(systemmenu.realRevision);
SystemInfo.sysMenuRegion = GetSysMenuRegion(SystemInfo.sysMenuVer);
sprintf(ReportBuffer[TEXT_REGION], "%s: %s", TXT_Region, SystemInfo.validregion ? Regions[SystemInfo.systemRegion] : "");
if (SystemInfo.validregion)
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu3, SystemInfo.sysNinVersion, SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer, systemmenu.realRevision, systemmenu.info);
else
strcat(ReportBuffer[SYSMENU], TXT_Unknown);
} else {
signed_blob *TMD = NULL;
tmd *t = NULL;
u32 TMD_size = 0;
ret = GetTMD((((u64)(1) << 32) | (0x0000000100000002LL)), &TMD, &TMD_size);
t = (tmd*)SIGNATURE_PAYLOAD(TMD);
t->title_id = ((u64)(1) << 32) | 249;
brute_tmd(t);
sha1 hash;
SHA1((u8 *)TMD, TMD_size, hash);
free(TMD);
u32 hashtest[5] = {0xc6404e23, 0x39eff390, 0x1d17c28f, 0xc3970680, 0xf44524e7};
if (memcmp((void *)hash, (u32 *)&hashtest, sizeof(sha1)) == 0)
{
SystemInfo.sysNinVersion = 4.1f;
sprintf(ReportBuffer[TEXT_REGION], "%s: PAL", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu, SystemInfo.sysNinVersion, "E", SystemInfo.sysMenuVer);
} else {
SystemInfo.sysMenuIOS = get_title_ios(TITLE_ID(0x00000001, 0x00000002));
switch (SystemInfo.systemRegion)
{
case CONF_REGION_US:
sprintf(ReportBuffer[TEXT_REGION], "%s: NTSC-U", TXT_Region);
break;
case CONF_REGION_EU:
sprintf(ReportBuffer[TEXT_REGION], "%s: PAL", TXT_Region);
break;
case CONF_REGION_JP:
sprintf(ReportBuffer[TEXT_REGION], "%s: NTSC-J", TXT_Region);
break;
case CONF_REGION_KR:
sprintf(ReportBuffer[TEXT_REGION], "%s: KOR", TXT_Region);
break;
default:
sprintf(ReportBuffer[TEXT_REGION], "%s: ", TXT_Region);
strcat(ReportBuffer[TEXT_REGION], TXT_Unknown);
}
switch (SystemInfo.sysMenuIOS)
{
case 9:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "1.0", SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
break;
case 11:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "2.0/2.1", SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
break;
case 20:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "2.2", SystemInfo.sysMenuRegion);
break;
case 30:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "3.0/3.1/3.2/3.3", SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
break;
case 40:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "3.3", SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
break;
case 50:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "3.4", SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
break;
case 60:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "4.0/4.1", SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
break;
case 70:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "4.2", SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
break;
case 80:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "4.3", SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
break;
default:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "0.0", SystemInfo.sysMenuRegion, SystemInfo.sysMenuVer);
break;
}
}
}
switch (CONF_GetSerialCode(NULL)) {
case CONF_CODE_JPN:
case CONF_CODE_VJPNI:
case CONF_CODE_VJPNO:
// JAP
if (SystemInfo.systemRegion != CONF_REGION_JP) {
strcat(ReportBuffer[TEXT_REGION], TXT_OriginalRegion);
strcat(ReportBuffer[TEXT_REGION], "JAP)");
}
break;
case CONF_CODE_USA:
case CONF_CODE_USAK:
case CONF_CODE_VUSAI:
case CONF_CODE_VUSAO:
// USA
if (SystemInfo.systemRegion != CONF_REGION_US) {
strcat(ReportBuffer[TEXT_REGION], TXT_OriginalRegion);
strcat(ReportBuffer[TEXT_REGION], "USA)");
}
break;
case CONF_CODE_EURH:
case CONF_CODE_EURHK:
case CONF_CODE_EURM:
case CONF_CODE_EURMK:
case CONF_CODE_EURF:
case CONF_CODE_EURFK:
case CONF_CODE_VEURHI:
case CONF_CODE_VEURHO:
case CONF_CODE_VEURMI:
case CONF_CODE_VEURMO:
case CONF_CODE_VEURFI:
case CONF_CODE_VEURFO:
// EU
if (SystemInfo.systemRegion != CONF_REGION_EU) {
strcat(ReportBuffer[TEXT_REGION], TXT_OriginalRegion);
strcat(ReportBuffer[TEXT_REGION], "PAL)");
}
break;
case CONF_CODE_KOR:
// KOR
if (SystemInfo.systemRegion != CONF_REGION_KR) {
strcat(ReportBuffer[TEXT_REGION], TXT_OriginalRegion);
strcat(ReportBuffer[TEXT_REGION], "KOR)");
}
break;
case CONF_CODE_AUS:
case CONF_CODE_AUSK:
case CONF_CODE_VAUSI:
case CONF_CODE_VAUSO:
// AUS
strcat(ReportBuffer[TEXT_REGION], TXT_OriginalRegion);
strcat(ReportBuffer[TEXT_REGION], "AUS)");
break;
default:
break;
}
if (SystemInfo.priiloader == 1)
sprintf(ReportBuffer[PRIILOADER], TXT_Priiloader);
else if (SystemInfo.priiloader == 2)
sprintf(ReportBuffer[PRIILOADER], TXT_PreFiix);
if (homebrew.hbc == HBC_NONE || homebrew.hbcversion == 0)
sprintf(ReportBuffer[HBC], TXT_NO_HBC);
else if (homebrew.hbcIOS == 0)
sprintf(ReportBuffer[HBC], TXT_HBC_STUB);
else if (homebrew.hbc == HBC_OPEN)
sprintf(ReportBuffer[HBC], TXT_HBC_112, homebrew.hbcversion, homebrew.hbcIOS);
else if (homebrew.hbc == HBC_LULZ)
sprintf(ReportBuffer[HBC], TXT_HBC_112, homebrew.hbcversion, homebrew.hbcIOS);
else if (homebrew.hbcversion == VERSION_1_1_0)
sprintf(ReportBuffer[HBC], TXT_HBC_NEW, homebrew.hbcIOS);
else if (homebrew.hbcversion > 0)
sprintf(ReportBuffer[HBC], TXT_HBC, homebrew.hbcversion, homebrew.hbcIOS);
if (homebrew.hbf > HBF_NONE)
sprintf(ReportBuffer[HBF], TXT_HBF, homebrew.hbfversion);
// If console type is unknown (because no AHB access), try to determine it by the IOS80 version. Less reliable
if ((SystemInfo.deviceType == CONSOLE_UNKNOWN) && (SystemInfo.sysMenuIOSType == IOS_WII_U) && (SystemInfo.sysMenuIOS == 80) && (SystemInfo.sysMenuIOSVersion == 7200))
SystemInfo.deviceType = CONSOLE_WII_U;
const char *device_types[] = {"Wii", "vWii", TXT_Unknown};
sprintf(ReportBuffer[HOLLYWOOD], TXT_Hollywood, HOLLYWOOD_VERSION);
sprintf(ReportBuffer[CONSOLE_ID], TXT_ConsoleID, SystemInfo.deviceID);
sprintf(ReportBuffer[CONSOLE_TYPE], TXT_ConsoleType, device_types[SystemInfo.deviceType]);
sprintf(ReportBuffer[COUNTRY], TXT_ShopCountry, (strlen(SystemInfo.country)) ? SystemInfo.country : TXT_Unknown, SystemInfo.shopcode);
sprintf(ReportBuffer[BOOT2_VERSION], TXT_vBoot2, SystemInfo.boot2version);
sprintf(ReportBuffer[NR_OF_TITLES], TXT_NrOfTitles, SystemInfo.countTitles);
sprintf(ReportBuffer[NR_OF_IOS], TXT_NrOfIOS, (SystemInfo.countIOS - SystemInfo.countBCMIOS), SystemInfo.countStubs);
// Display IOS vulnerabilities
int lineOffset = 0;
int skippedOffset = 0;
int lastIOS = 0;
for (i = 0; i < nbTitles; i++)
{
lineOffset = i + LAST;
if (arguments.skipIOScnt > 0) {
for(j = 0; j < arguments.skipIOScnt; j++) {
if (arguments.skipIOSlist[j] > lastIOS && arguments.skipIOSlist[j] < ios[i].titleID) {
snprintf(ReportBuffer[skippedOffset + lineOffset], MAX_ELEMENTS(ReportBuffer[0]), "%sIOS%d: %s", (SystemInfo.deviceType == CONSOLE_WII_U) ? "v" : "", arguments.skipIOSlist[j], TXT_IOSSkipped);
skippedOffset++;
break;
}
}
}
if (selectedIOS > -1) i = selectedIOS; //If specific IOS is selected
if (ios[i].titleID == TID_BC) {
sprintf(ReportBuffer[skippedOffset + lineOffset], "BC v%d", ios[i].revision);
} else if (ios[i].titleID == TID_MIOS) {
sprintf(ReportBuffer[skippedOffset + lineOffset], "MIOS v%d%s", ios[i].revision, SystemInfo.miosInfo);
} else if (ios[i].baseIOS == 75 && (ios[i].titleID==222 || ios[i].titleID==224 || ios[i].titleID==223 || ios[i].titleID==202 || ios[i].titleID==225)) {
sprintf(ReportBuffer[skippedOffset + lineOffset], "%sIOS%d[38+37] (rev %d, Info: %s):", ios[i].infovIOS ? "v" : "", ios[i].titleID, ios[i].revision, ios[i].info);
} else if (ios[i].baseIOS == 98 && (ios[i].titleID==222 || ios[i].titleID==224 || ios[i].titleID==223 || ios[i].titleID==202 || ios[i].titleID==225)) {
sprintf(ReportBuffer[skippedOffset + lineOffset], "%sIOS%d[38+60] (rev %d, Info: %s):", ios[i].infovIOS ? "v" : "", ios[i].titleID, ios[i].revision, ios[i].info);
} else {
if(ios[i].mloadVersion > 0 && ios[i].baseIOS > 0) {
int v, s;
v = ios[i].mloadVersion;
s = v & 0x0F;
v = v >> 4;
if (v == 0 && s == 1) {
v = 4;
s = 0;
}
sprintf(ReportBuffer[skippedOffset + lineOffset], "%sIOS%d[%d] (rev %d, Info: hermes-v%d.%d):", ios[i].infovIOS ? "v" : "", ios[i].titleID, ios[i].baseIOS, ios[i].revision, v, s);
} else if(ios[i].baseIOS > 0) {
snprintf(ReportBuffer[skippedOffset + lineOffset], MAX_ELEMENTS(ReportBuffer[0]), "%sIOS%d[%d] (rev %d, Info: %s):", ios[i].infovIOS ? "v" : "", ios[i].titleID, ios[i].baseIOS, ios[i].revision, ios[i].info);
} else if (strcmp(ios[i].info, "NULL") != 0 && !ios[i].isStub) {
snprintf(ReportBuffer[skippedOffset + lineOffset], MAX_ELEMENTS(ReportBuffer[0]), "%sIOS%d (rev %d, Info: %s):", ios[i].infovIOS ? "v" : "", ios[i].titleID, ios[i].revision, ios[i].info);
} else if (ios[i].titleID == 249 && ios[i].revision > 11 && ios[i].revision < 18) {
sprintf(ReportBuffer[skippedOffset + lineOffset], "%sIOS%d[38] (rev %d):", ios[i].infovIOS ? "v" : "", ios[i].titleID, ios[i].revision);
} else {
snprintf(ReportBuffer[skippedOffset + lineOffset], MAX_ELEMENTS(ReportBuffer[0]), "%sIOS%d (rev %d):", ios[i].infovIOS ? "v" : "", ios[i].titleID, ios[i].revision);
}
}
// Check BootMii As IOS (BootMii As IOS is installed on IOS254 rev 31338)
if (ios[i].titleID == TID_BOOTMII && (ios[i].revision == 31338 || ios[i].revision == 65281))
strcat (ReportBuffer[skippedOffset + lineOffset]," BootMii");
else if (ios[i].titleID == TID_NANDEMU && ios[i].revision == 65535)
strcat (ReportBuffer[skippedOffset + lineOffset]," NANDEmu");
else
{
if (ios[i].isStub && strcmp(ios[i].info, "NULL") == 0) {
gprintf("1. titleID: %d %s\n", ios[i].titleID, ios[i].info);
strcat (ReportBuffer[skippedOffset + lineOffset], TXT_Stub);
} else if (ios[i].isStub && strcmp(ios[i].info, "NULL") != 0) {
gprintf("2. titleID: %d %s\n", ios[i].titleID, ios[i].info);
strcat (ReportBuffer[skippedOffset + lineOffset], ios[i].info);
} else if(ios[i].titleID != TID_BC && ios[i].titleID != TID_MIOS) {
if(ios[i].infoFakeSignature) strcat(ReportBuffer[skippedOffset + lineOffset], TXT_Trucha);
if(ios[i].infoESIdentify) strcat(ReportBuffer[skippedOffset + lineOffset], TXT_ES);
if(ios[i].infoFlashAccess) strcat(ReportBuffer[skippedOffset + lineOffset], TXT_Flash);
if(ios[i].infoNANDAccess) strcat(ReportBuffer[skippedOffset + lineOffset], TXT_NAND);
if(ios[i].infoVersionPatch) strcat(ReportBuffer[skippedOffset + lineOffset], TXT_VersionP);
if(ios[i].infoBoot2Access) strcat(ReportBuffer[skippedOffset + lineOffset], TXT_Boot2);
if(ios[i].infoUSB2) strcat(ReportBuffer[skippedOffset + lineOffset], TXT_USB);
if(ios[i].infoBeerTicket) strcat(ReportBuffer[skippedOffset + lineOffset], TXT_BeerTicket);
if(!ios[i].infoFakeSignature && !ios[i].infoESIdentify && !ios[i].infoFlashAccess && !ios[i].infoNANDAccess && !ios[i].infoUSB2 && !ios[i].infoVersionPatch && !ios[i].infoBeerTicket) strcat(ReportBuffer[skippedOffset + lineOffset], TXT_NoPatch);
ReportBuffer[skippedOffset + lineOffset][strlen(ReportBuffer[skippedOffset + lineOffset])-1]='\0';
}
}
lastIOS = ios[i].titleID;
}
int NumLines = lineOffset + skippedOffset + 1;
sprintf(ReportBuffer[NumLines], TXT_ReportDate);
CheckTime();
// Mount the SD Card
UpdateTime();
if (arguments.USB)
{
printLoading(MSG_MountUSB);
USB_Deinitialize();
if (SystemInfo.runningIOS != IOS_GetVersion())
{
IosPatch_AHBPROT(false);
IOS_ReloadIOS(SystemInfo.runningIOS);
}
usleep(100000);
MountUSB();
} else {
printLoading(MSG_MountSD);
MountSD();
}
CheckTime();
// Initialise the FAT file system
UpdateTime();
printLoading(MSG_InitFAT);
if (!arguments.USB && !fatInitDefault())
{
sprintf(MSG_Buffer, ERR_InitFAT);
printError(MSG_Buffer);
sleep(2);
printEndError(MSG_ReportError);
} else {
// Create the report
CheckTime();
char dest[100];
sprintf(dest, "%s%s", arguments.USB ? "usb" : "sd", REPORT);
FILE *file = fopen(dest, "w");
if(!file)
{
printError(ERR_OpenFile);
sleep(2);
printEndError(MSG_ReportError);
} else {
for (i = 0; i <= NumLines; i++) {
fprintf(file, ReportBuffer[i]);
fprintf(file, "\r\n");
fflush(file);
}
// Close the report
fclose(file);
printEndSuccess(MSG_ReportSuccess);
CheckTime();
}
// Create hash log
sprintf(dest, "%s%s", arguments.USB ? "usb" : "sd", HASHLOG);
file = fopen(dest, "w");
if(!file)
{
printError(ERR_OpenFile);
sleep(2);
printEndError(MSG_ReportError);
} else {
for (i = 0; i <= lines; i++) {
fprintf(file, HashLogBuffer[i]);
fprintf(file, "\r\n");
fflush(file);
}
// Close the report
fclose(file);
UpdateTime();
printEndSuccess(MSG_ReportSuccess);
CheckTime();
}
}
int LineNr = 0;
WPAD_Init();
bool reportIsDisplayed = false;
while (1) {
wpressed = DetectInput(DI_BUTTONS_HELD);
// Return to the loader
if (wpressed & WPAD_BUTTON_HOME) {
UnmountSD();
UnmountUSB();
deinitGUI();
exit(0);
}
// Return to System Menu
if (wpressed & WPAD_BUTTON_PLUS) {
UnmountSD();
UnmountUSB();
deinitGUI();
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
}
// Shutdown Wii
if (wpressed & WPAD_BUTTON_MINUS) {
UnmountSD();
UnmountUSB();
deinitGUI();
SYS_ResetSystem(SYS_POWEROFF, 0, 0);
}
// Display Report
if (wpressed & WPAD_BUTTON_A) {
if (reportIsDisplayed && completeReport) {
transmitSyscheck(ReportBuffer, &NumLines);
FILE *file = fopen(REPORT, "a");
if(file)
{
fprintf(file, ReportBuffer[NumLines]);
fprintf(file, "\r\n");
// Close the report
fclose(file);
}
completeReport = false;
printReport(ReportBuffer, LineNr, completeReport);
} else {
printReport(ReportBuffer, LineNr, completeReport);
usleep(500000); // A little pause to decrease the chance of accidental upload
reportIsDisplayed = true;
}
}
if (NumLines > 14) { // Just a safety measure in case the report is less than 14 lines for some reason
if (wpressed & WPAD_BUTTON_UP) {
if (LineNr > 0) LineNr--;
printReport(ReportBuffer, LineNr, completeReport);
usleep(50000);
}
if (wpressed & WPAD_BUTTON_DOWN) {
if (LineNr < NumLines-14) LineNr++;
printReport(ReportBuffer, LineNr, completeReport);
usleep(50000);
}
if (wpressed & WPAD_BUTTON_LEFT) {
if (LineNr > 0) LineNr = LineNr - 15;
if (LineNr < 0) LineNr = 0;
printReport(ReportBuffer, LineNr, completeReport);
usleep(100000);
}
if (wpressed & WPAD_BUTTON_RIGHT) {
if (LineNr < NumLines-14) LineNr = LineNr + 15;
if (LineNr + 14 > NumLines) LineNr = NumLines-14;
printReport(ReportBuffer, LineNr, completeReport);
usleep(100000);
}
}
}
}