SysCheck-ModMii-Edition/source/sysCheck.c
2013-10-12 18:38:34 +00:00

1288 lines
35 KiB
C

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <gccore.h>
#include <malloc.h>
#include <fat.h>
#include <unistd.h>
#include <wiilight.h>
#include <ogc/conf.h>
#include <wiiuse/wpad.h>
#include <stdlib.h>
#include <stdarg.h>
#include <di/di.h>
#include <CheckRegion.h>
#include "tmd_dat.h"
#include "sys.h"
#include "video.h"
#include "fatMounter.h"
#include "languages.h"
#include "gui.h"
#include "mload.h"
#include "title.h"
#include "sha1.h"
#include "wiibasics.h"
#include "tmdIdentification.h"
#include "gecko.h"
#include "update.h"
// Filename
#define REPORT "sd:/sysCheck.csv"
#define HASHLOG "sd:/IOSsyscheck.log"
#define VERSION_1_1_0 65536
#define FLASH_SIZE (512 * 1024 * 1024)
#define SECTOR_SIZE (0x4000)
extern bool geckoinit;
extern u8 sysMenueInfoContent;
bool debug;
char miosInfo[128] = {0};
extern void __exception_setreload(int t);
int get_title_ios(u64 title) {
s32 ret, fd;
static char filepath[256] ATTRIBUTE_ALIGN(32);
// Check to see if title exists
if (ES_GetDataDir(title, filepath) >= 0 ) {
u32 tmd_size;
static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
ret = ES_GetStoredTMDSize(title, &tmd_size);
if (ret < 0) {
// If we fail to use the ES function, try reading manually
// This is a workaround added since some IOS (like 21) don't like our
// call to ES_GetStoredTMDSize
//printf("Error! ES_GetStoredTMDSize: %d\n", ret);
sprintf(filepath, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title));
ret = ISFS_Open(filepath, ISFS_OPEN_READ);
if (ret <= 0)
{
printf("Error! ISFS_Open (ret = %d)\n", ret);
return 0;
}
fd = ret;
ret = ISFS_Seek(fd, 0x184, 0);
if (ret < 0)
{
printf("Error! ISFS_Seek (ret = %d)\n", ret);
return 0;
}
ret = ISFS_Read(fd,tmd_buf,8);
if (ret < 0)
{
printf("Error! ISFS_Read (ret = %d)\n", ret);
return 0;
}
ret = ISFS_Close(fd);
if (ret < 0)
{
printf("Error! ISFS_Close (ret = %d)\n", ret);
return 0;
}
return be64(tmd_buf);
} else {
// Normal versions of IOS won't have a problem, so we do things the "right" way.
// Some of this code adapted from bushing's title_lister.c
signed_blob *s_tmd = (signed_blob *)tmd_buf;
ret = ES_GetStoredTMD(title, s_tmd, tmd_size);
if (ret < 0){
printf("Error! ES_GetStoredTMD: %d\n", ret);
return -1;
}
tmd *t = SIGNATURE_PAYLOAD(s_tmd);
return t->sys_version;
}
}
return 0;
}
bool getInfoFromContent(IOS *ios) {
bool retValue = false;
iosinfo_t *iosinfo = NULL;
char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20);
u8 *buffer = 0;
u32 filesize = 0;
s32 ret = 0;
// Try to identify the cIOS by the info put in by the installer/ModMii
sprintf(filepath, "/title/%08x/%08x/content/%08x.app", 0x00000001, ios->titleID, ios->infoContent);
ret = read_file_from_nand(filepath, &buffer, &filesize);
iosinfo = (iosinfo_t *)(buffer);
if (ret >= 0 && ios->titleID == 252 && ios->num_contents == 1) {
const char *checkStr = "bootcb2";
int i;
for (i = 0; i < filesize - strlen(checkStr); i++)
{
if (!strncmp((char*)buffer + i, checkStr, strlen(checkStr)))
{
sprintf(ios->info, " cBoot252");
gprintf("is cBoot252\n");
logfile("is cBoot252\r\n");
retValue = true;
ios->isStub = true;
break;
}
}
if (buffer != 0)
{
free(buffer);
}
} else if (ret >= 0 && iosinfo != NULL && iosinfo->magicword == 0x1ee7c105 && iosinfo->magicversion == 1) {
if (ios->titleID != iosinfo->baseios)
ios->baseIOS = iosinfo->baseios;
if (strcmp(iosinfo->name, "nintendo") == 0)
sprintf(ios->info, "rev %u", iosinfo->version);
else
sprintf(ios->info, "%s-v%u%s", iosinfo->name, iosinfo->version, iosinfo->versionstring);
gprintf("is %s\n", ios->info);
logfile("is %s\r\n", ios->info);
retValue = true;
if (buffer != 0)
{
free(buffer);
}
}
return retValue;
}
void formatDate(u32 date, char ReportBuffer[200][100]) {
char temp[9] = {0};
char day[3] = {0};
char month[3] = {0};
char year[5] = {0};
sprintf(temp, "%08x", date);
sprintf(year, "%c%c%c%c", temp[0], temp[1], temp[2], temp[3]);
sprintf(month, "%c%c", temp[4], temp[5]);
sprintf(day, "%c%c", temp[6], temp[7]);
gprintf("MONTH: %s\n", month);
gprintf("DAY: %s\n", day);
gprintf("YEAR: %s\n", year);
logfile("MONTH: %s\r\n", month);
logfile("DAY: %s\r\n", day);
logfile("YEAR: %s\r\n", year);
char result[10] = {0};
switch (CONF_GetLanguage()) {
case CONF_LANG_GERMAN:
case CONF_LANG_ITALIAN:
case CONF_LANG_SPANISH:
sprintf(result, "%s.%s.%s", day, month, year);
break;
default:
sprintf(result, "%s.%s.%s", month, day, year); // You don't say "I was born 1990 January 1" The year comes last
break;
}
gprintf("String: %s\n", result);
logfile("String: %s\r\n", result);
if (strlen(result) > 1)
sprintf(ReportBuffer[DVD], TXT_DVD, result);
else
sprintf(ReportBuffer[DVD], TXT_NoDVD);
}
void sort(u64 *titles, u32 cnt) {
int i, j;
for (i = 0; i < cnt -1; ++i) {
for (j = 0; j < cnt - i - 1; ++j) {
if (titles[j] > titles[j + 1]) {
u64 tmp = titles[j];
titles[j] = titles[j + 1];
titles[j + 1] = tmp;
}
}
}
}
// Main
int main(int argc, char **argv)
{
__exception_setreload(2);
bool forceNoAHBPROT = false;
geckoinit = InitGecko();
if(argc>=1){
int i;
for(i=0; i<argc; i++){
if(strncmp("--debug=true", argv[i], 12)==0){
debug = true;
gprintf("--debug=true\n");
} else if(strncmp("--forceNoAHBPROT=true", argv[i], 21)==0){
forceNoAHBPROT = true;
gprintf("--forceNoAHBPROT=true\n");
}
}
}
if (HAVE_AHBPROT && !forceNoAHBPROT)
IOSPATCH_Apply();
bool 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);
usleep(250000);
int regionSelection = CONF_GetRegion();
u8 shopcode = 0;
char country[COUNTRY_SIZE] = "Unknown";
if (!CONF_GetShopCode(&shopcode)) strncpy(country, CONF_CountryCodes[shopcode], COUNTRY_SIZE);
// Get the system menu version
printLoading(MSG_GetSysMenuVer);
usleep(250000);
u32 sysVersion = GetSysMenuVersion();
sysMenu systemmenu;
printLoading(MSG_GetHBCVer);
usleep(250000);
u32 hbcversion = 0;
u32 hbfversion = 0;
s32 hbc = 0;
s32 hbf = 0;
u32 hbcIOS = 0;
u32 dvdSupport = 0;
s32 ret;
ret = Title_GetVersionNObuf(0x000100014C554C5All);
if (ret<0) {
ret = Title_GetVersionNObuf(0x00010001AF1BF516ll);
if (ret<0) {
ret = Title_GetVersionNObuf(0x000100014A4F4449ll);
if (ret<0) {
hbc = 1;
ret = Title_GetVersionNObuf(0x0001000148415858ll);
if (ret<0) {
hbc = 0;
} else {
hbc = 1;
hbcversion = ret;
}
} else {
hbc = 2;
hbcversion = ret;
}
} else {
hbc = 3;
hbcversion = ret;
if (hbcversion == 0)
hbcversion = VERSION_1_1_0;
}
} else {
hbc = 4;
hbcversion = ret;
if (hbcversion == 257)
hbcversion = 1;
else
hbcversion = 2;
}
if (hbc == 4) {
hbcIOS = get_title_ios(TITLE_ID(0x10001, 0x4C554C5A));
} else if (hbc == 3) {
hbcIOS = get_title_ios(TITLE_ID(0x10001, 0xAF1BF516));
} else if (hbc == 2) {
hbcIOS = get_title_ios(TITLE_ID(0x10001, 0x4A4F4449));
} else if (hbc == 1) {
hbcIOS = get_title_ios(TITLE_ID(0x10001, 0x48415858));
}
ret = Title_GetVersionNObuf(0x0001000148424630LL); //HBF0
if (ret<0) {
ret = Title_GetVersionNObuf(0x0001000154484246LL); //THBF
if (ret<0) {
hbf = 0;
} else {
hbf = 1;
hbfversion = ret;
}
} else {
hbf = 2;
hbfversion = ret;
}
if (HAVE_AHBPROT && !forceNoAHBPROT) {
DI_Init();
DI_DriveID id;
if(DI_Identify(&id) == 0) {
dvdSupport = id.rel_date;
}
DI_Close();
}
float sysNinVersion = GetSysMenuNintendoVersion(sysVersion);
// Get the running IOS version and revision
u32 runningIOS = IOS_GetVersion();
u32 runningIOSRevision = IOS_GetRevision();
printLoading(MSG_GetRunningIOS);
usleep(250000);
// Get the console ID
printLoading(MSG_GetConsoleID);
usleep(250000);
u32 deviceID = GetDeviceID();
// Get the boot2 version
printLoading(MSG_GetBoot2);
usleep(250000);
u32 boot2version = GetBoot2Version();
// Get number of titles
printLoading(MSG_GetNrOfTitles);
usleep(250000);
u32 tempTitles;
if (ES_GetNumTitles(&tempTitles) < 0) {
printError(ERR_GetNrOfTitles);
sleep(5);
return false;
}
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);
return false;
}
// Get list of titles
printLoading(MSG_GetTitleList);
usleep(250000);
if (ES_GetTitles(titles, nbTitles) < 0) {
printError(ERR_GetTitleList);
sleep(5);
return false;
}
int i;
int j;
int countIOS = 0; // Number of IOS
int countStubs = 0; // Number of IOS Stubs
int 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;
}
u32 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;
}
}
if (titleID > 258 && titleID < 512) {
titles[i] = 0;
continue;
}
// Skip the running IOS
if (titleID == 0) {
titles[i] = 0;
continue;
}
// Skip the System Menu
if (titleID == 2) {
titles[i] = 0;
continue;
}
countIOS++;
}
// Sort IOS titles
printLoading(MSG_SortTitles);
usleep(250000);
u64 *newTitles = memalign(32, countIOS*sizeof(u64));
u32 cnt = 0;
for (i = 0; i < nbTitles; i++) {
if (titles[i] > 0) {
newTitles[cnt] = titles[i];
cnt++;
}
}
sort(newTitles, countIOS);
free(titles);
IOS ios[countIOS];
// ios Liste initialisieren
//for (i = 0; i < countIOS; i++) {
for (i = countIOS; i--;) { // Should be slightly faster
ios[i].infoContent = 0;
ios[i].titleID = 0;
ios[i].mloadVersion = 0;
ios[i].baseIOS = -1;
sprintf(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;
}
MountSD();
NandStartup();
// Check Priiloader
int priiloader = checkSysLoader();
// Check MIOS
if (nandAccess) get_miosinfo(miosInfo);
// For each titles found
//for (i = 0; i < countIOS; i++)
for (i = countIOS; i--;) // Should be slightly faster
{
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);
return false;
}
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);
return false;
}
iosTMD = (tmd*)SIGNATURE_PAYLOAD(iosTMDBuffer);
// Get the title version
u32 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, titleSize);
logfile("ios%d rev%d iosTMD->num_contents = %d size=%d\r\n", ios[i].titleID, ios[i].revision, iosTMD->num_contents, 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
{
if (ios[i].titleID != 256 && ios[i].titleID != 257 && ios[i].titleID != 512 && ios[i].titleID != 513 && titleSize < 0x100000)
ios[i].isStub = true;
else
ios[i].isStub = false;
if (ios[i].isStub) {
gprintf("is stub\n");
logfile("is stub\r\n");
}
}
if (!ios[i].isStub || ios[i].titleID == 252) {
if (nandAccess)
if (!getInfoFromContent(&ios[i])) {
// Hash des TMDs abrufen
iosTMD->title_id = ((u64)(1) << 32) | 249;
brute_tmd(iosTMD);
sha1 hash;
SHA1((u8 *)iosTMDBuffer, tmdSize, hash);
sprintf(HashLogBuffer[lines], "IOS%d get_ios_base: \n%x %x %x %x, %x %x %x %x, %x %x %x %x, %x %x %x %x, %x %x %x %x\n", ios[i].titleID, (char)hash[0], (char)hash[1], (char)hash[2], (char)hash[3], (char)hash[4], (char)hash[5], (char)hash[6], (char)hash[7], (char)hash[8], (char)hash[9], (char)hash[10], (char)hash[11], (char)hash[12], (char)hash[13], (char)hash[14], (char)hash[15], (char)hash[16], (char)hash[17], (char)hash[18], (char)hash[19]);
lines++;
for (j = 0;j < base_number;j++)
{
// Hashes berprfen
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);
}
}
}
}
free(iosTMDBuffer);
if (ios[i].titleID == 256 || ios[i].titleID == 257) countBCMIOS++;
if (ios[i].isStub && !(iosTMD->title_version == 31338) && !(iosTMD->title_version == 65281) && !(iosTMD->title_version == 65535)) countStubs++;
}
// 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);
return false;
}
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);
return false;
}
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
sysMenueInfoContent = *(u8 *)((u32)iosTMDBuffer+0x1E7);
sprintf(filepath, "/title/%08x/%08x/content/%08x.app", 0x00000001, 2, sysMenueInfoContent);
gprintf("/title/%08x/%08x/content/%08x.app\n", 0x00000001, 2, sysMenueInfoContent);
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;
//strcpy(systemmenu.info, sysInfo->name);
sprintf(systemmenu.info, "%s%s", sysInfo->name, sysInfo->versionstring);
if (buffer != 0)
{
free(buffer);
}
} else {
systemmenu.realRevision = 0;
systemmenu.hasInfo = false;
strcpy(systemmenu.info, "NICHTS");
}
NandShutdown();
UnmountSD();
u32 countTitles = nbTitles;
nbTitles = countIOS;
// Get the certificates from the NAND
printLoading(MSG_GetCertificates);
usleep(250000);
if (!GetCertificates()) {
printError(ERR_GetCertificates);
sleep(5);
return false;
}
//Select an IOS to test
WPAD_Init();
int selectedIOS = -1;
u16 wpressed;
time_t starttime;
starttime = time(NULL);
printSelectIOS(MSG_SelectIOS, MSG_All);
bool completeReport = true;
while (difftime (time(NULL),starttime) < 15) {
//while(1) {
WPAD_ScanPads();
wpressed = WPAD_ButtonsHeld(0);
usleep(50000);
if (wpressed & WPAD_BUTTON_RIGHT && selectedIOS < (nbTitles-1)){
selectedIOS++;
starttime = time(NULL);
u32 titleID = newTitles[selectedIOS] & 0xFFFFFFFF;
switch (titleID)
{
case 256:
sprintf(MSG_Buffer, "BC");
break;
case 257:
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) {
u32 titleID = newTitles[selectedIOS] & 0xFFFFFFFF;
switch (titleID)
{
case 256:
sprintf(MSG_Buffer, "BC");
break;
case 257:
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();
if (ret == 2) {
printSuccess(MSG_NoUpdate);
sleep(5);
starttime = time(NULL);
} else if (ret >= 0) {
printSuccess(MSG_UpdateSuccess);
sleep(10);
if (*(u32*)0x80001800) exit(0);
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
} else if (ret < 0) {
printError(MSG_UpdateFail);
sleep(5);
starttime = time(NULL);
}
}
if (wpressed & WPAD_BUTTON_A) {
break;
}
}
WPAD_Shutdown();
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 == 256) sprintf(MSG_Buffer2, "BC");
else if (ios[i].titleID == 257) 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 == 256 || ios[i].titleID == 257)
{
ios[i].infoFakeSignature = false;
ios[i].infoESIdentify = false;
ios[i].infoFlashAccess = false;
ios[i].infoNANDAccess = false;
ios[i].infoBoot2Access = false;
ios[i].infoUSB2 = false;
}
else
{
// Reload IOS
gprintf("// IOS_ReloadIOS(%d)\n", ios[i].titleID);
logfile("// IOS_ReloadIOS(%d)\r\n", ios[i].titleID);
IOS_ReloadIOS(ios[i].titleID);
// 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));
if (ios[i].infoFakeSignature) {
//ios[i].infoVersionPatch = (CheckVersionPatch());
}
// Check Priiloader
if (!nandAccess && priiloader == -2 && ios[i].infoNANDAccess) {
priiloader = checkSysLoader();
}
// Check Base IOS
if (!nandAccess && ios[i].infoNANDAccess) {
NandStartup();
int k = 0;
for (k = 0; k < nbTitles; k++) {
if ((ios[i].isStub || ios[i].titleID == 256 || ios[i].titleID == 257) && ios[i].titleID != 252) 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();
}
}
}
// Reload the running IOS
IOS_ReloadIOS(runningIOS);
sprintf(MSG_Buffer, MSG_ReloadIOS, runningIOS, runningIOSRevision);
printLoading(MSG_Buffer);
usleep(250000);
//--Generate Report--
printLoading(MSG_GenerateReport);
usleep(250000);
char ReportBuffer[200][100] = {{0}} ;
if (dvdSupport > 0)
formatDate(dvdSupport, ReportBuffer);
else
sprintf(ReportBuffer[DVD], TXT_NoDVD);
// Display Title
sprintf(ReportBuffer[APP_TITLE], TXT_AppTitle, TXT_AppVersion);
sprintf(ReportBuffer[APP_IOS], TXT_AppIOS, runningIOS, IOS_GetRevision());
// Display the console region
if (!sysNinVersion == 0.0f) {
switch (regionSelection)
{
case CONF_REGION_US:
sprintf(ReportBuffer[TEXT_REGION], "%s: NTSC-U", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu, sysNinVersion, "U", sysVersion);
break;
case CONF_REGION_EU:
sprintf(ReportBuffer[TEXT_REGION], "%s: PAL", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu, sysNinVersion, "E", sysVersion);
break;
case CONF_REGION_JP:
sprintf(ReportBuffer[TEXT_REGION], "%s: NTSC-J", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu, sysNinVersion, "J", sysVersion);
break;
case CONF_REGION_KR:
sprintf(ReportBuffer[TEXT_REGION], "%s: KOR", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu, sysNinVersion, "K", sysVersion);
break;
default:
sprintf(ReportBuffer[TEXT_REGION], "%s: ", TXT_Region);
strcat(ReportBuffer[SYSMENU], TXT_Unknown);
}
} else if (systemmenu.hasInfo) {
u32 realSysVersion = systemmenu.realRevision;
sysNinVersion = GetSysMenuNintendoVersion(realSysVersion);
switch (regionSelection)
{
case CONF_REGION_US:
sprintf(ReportBuffer[TEXT_REGION], "%s: NTSC-U", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu3, sysNinVersion, "U", sysVersion, realSysVersion, systemmenu.info);
break;
case CONF_REGION_EU:
sprintf(ReportBuffer[TEXT_REGION], "%s: PAL", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu3, sysNinVersion, "E", sysVersion, realSysVersion, systemmenu.info);
break;
case CONF_REGION_JP:
sprintf(ReportBuffer[TEXT_REGION], "%s: NTSC-J", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu3, sysNinVersion, "J", sysVersion, realSysVersion, systemmenu.info);
break;
case CONF_REGION_KR:
sprintf(ReportBuffer[TEXT_REGION], "%s: KOR", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu3, sysNinVersion, "K", sysVersion, realSysVersion, systemmenu.info);
break;
default:
sprintf(ReportBuffer[TEXT_REGION], "%s: ", TXT_Region);
strcat(ReportBuffer[TEXT_REGION], 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)
{
sysNinVersion = 4.1f;
sprintf(ReportBuffer[TEXT_REGION], "%s: PAL", TXT_Region);
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu, sysNinVersion, "E", sysVersion);
} else {
s32 sysIOS = get_title_ios(TITLE_ID(0x00000001, 0x00000002));
char Region[100];
switch (regionSelection)
{
case CONF_REGION_US:
sprintf(ReportBuffer[TEXT_REGION], "%s: NTSC-U", TXT_Region);
sprintf(Region, "U");
break;
case CONF_REGION_EU:
sprintf(ReportBuffer[TEXT_REGION], "%s: PAL", TXT_Region);
sprintf(Region, "E");
break;
case CONF_REGION_JP:
sprintf(ReportBuffer[TEXT_REGION], "%s: NTSC-J", TXT_Region);
sprintf(Region, "J");
break;
case CONF_REGION_KR:
sprintf(ReportBuffer[TEXT_REGION], "%s: KOR", TXT_Region);
sprintf(Region, "K");
break;
default:
sprintf(ReportBuffer[TEXT_REGION], "%s: ", TXT_Region);
strcat(ReportBuffer[TEXT_REGION], TXT_Unknown);
}
switch (sysIOS)
{
case 9:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "1.0", Region, sysVersion);
break;
case 11:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "2.0/2.1", Region, sysVersion);
break;
case 20:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "2.2", Region);
break;
case 30:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "3.0/3.1/3.2/3.3", Region, sysVersion);
break;
case 40:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "3.3", Region, sysVersion);
break;
case 50:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "3.4", Region, sysVersion);
break;
case 60:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "4.0/4.1", Region, sysVersion);
break;
case 70:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "4.2", Region, sysVersion);
break;
case 80:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "4.3", Region, sysVersion);
break;
default:
sprintf(ReportBuffer[SYSMENU], TXT_SysMenu2, "0.0", Region, sysVersion);
}
}
}
switch (CONF_GetSerialCode(NULL)) {
case CONF_CODE_JPN:
case CONF_CODE_VJPNI:
case CONF_CODE_VJPNO:
// JAP
if (regionSelection != 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 (regionSelection != 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 (regionSelection != CONF_REGION_EU) {
strcat(ReportBuffer[TEXT_REGION], TXT_OriginalRegion);
strcat(ReportBuffer[TEXT_REGION], "PAL)");
}
break;
case CONF_CODE_KOR:
// KOR
if (regionSelection != 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 (priiloader == 1)
sprintf(ReportBuffer[PRIILOADER], TXT_Priiloader);
else if (priiloader == 2)
sprintf(ReportBuffer[PRIILOADER], TXT_PreFiix);
if (hbc == 0 || hbcversion == 0)
sprintf(ReportBuffer[HBC], "Homebrew Channel is not installed");
else if (hbcIOS == 0)
sprintf(ReportBuffer[HBC], TXT_HBC_STUB);
else if (hbc == 4)
sprintf(ReportBuffer[HBC], TXT_HBC_112, hbcversion, hbcIOS);
else if (hbcversion == VERSION_1_1_0)
sprintf(ReportBuffer[HBC], TXT_HBC_NEW, hbcIOS);
else if (hbcversion > 0)
sprintf(ReportBuffer[HBC], TXT_HBC, hbcversion, hbcIOS);
if (hbf > 0)
sprintf(ReportBuffer[HBF], TXT_HBF, hbfversion);
sprintf(ReportBuffer[HOLLYWOOD], TXT_Hollywood, *HOLLYWOOD_VERSION);
sprintf(ReportBuffer[CONSOLE_ID], TXT_ConsoleID, deviceID);
sprintf(ReportBuffer[BOOT2_VERSION], TXT_vBoot2, boot2version);
sprintf(ReportBuffer[COUNTRY], "Shop Channel Country: %s (%u)", (strlen(country)) ? country : "Unknown", shopcode);
sprintf(ReportBuffer[NR_OF_TITLES], TXT_NrOfTitles, countTitles);
sprintf(ReportBuffer[NR_OF_IOS], TXT_NrOfIOS, (countIOS - countBCMIOS), countStubs);
// Display IOS vulnerabilities
int lineOffset = 0;
for (i = 0; i < nbTitles; i++)
{
lineOffset = i;
if (selectedIOS > -1) i = selectedIOS; //If specific IOS is selected
if (ios[i].titleID == 256) {
sprintf(ReportBuffer[LAST+lineOffset], "BC v%d", ios[i].revision);
} else if (ios[i].titleID == 257) {
sprintf(ReportBuffer[LAST+lineOffset], "MIOS v%d%s", ios[i].revision, miosInfo);
} else if ((ios[i].titleID==222 || ios[i].titleID==224 || ios[i].titleID==223 || ios[i].titleID==202 || ios[i].titleID==225) && ios[i].baseIOS == 75) {
sprintf(ReportBuffer[LAST+lineOffset], "IOS%d[38+37] (rev %d, Info: %s):", 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[LAST+lineOffset], "IOS%d[%d] (rev %d, Info: hermes-v%d.%d):", ios[i].titleID, ios[i].baseIOS, ios[i].revision, v, s);
} else if(ios[i].baseIOS > 0) {
sprintf(ReportBuffer[LAST+lineOffset], "IOS%d[%d] (rev %d, Info: %s):", ios[i].titleID, ios[i].baseIOS, ios[i].revision, ios[i].info);
} else if (strcmp(ios[i].info, "NULL") != 0 && !ios[i].isStub) {
sprintf(ReportBuffer[LAST+lineOffset], "IOS%d (rev %d, Info: %s):", 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[LAST+lineOffset], "IOS%d[38] (rev %d):", ios[i].titleID, ios[i].revision);
} else {
sprintf(ReportBuffer[LAST+lineOffset], "IOS%d (rev %d):", ios[i].titleID, ios[i].revision);
}
}
// Check BootMii As IOS (BootMii As IOS is installed on IOS254 rev 31338)
if (ios[i].titleID == 254 && (ios[i].revision == 31338 || ios[i].revision == 65281))
strcat (ReportBuffer[LAST+lineOffset]," BootMii");
else if (ios[i].titleID == 253 && ios[i].revision == 65535)
strcat (ReportBuffer[LAST+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[LAST+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[LAST+lineOffset], ios[i].info);
} else if(ios[i].titleID == 256 || ios[i].titleID == 257) {
//Do nothing
} else {
if(ios[i].infoFakeSignature) strcat(ReportBuffer[LAST+lineOffset], TXT_Trucha);
if(ios[i].infoESIdentify) strcat(ReportBuffer[LAST+lineOffset], TXT_ES);
if(ios[i].infoFlashAccess) strcat(ReportBuffer[LAST+lineOffset], TXT_Flash);
if(ios[i].infoNANDAccess) strcat(ReportBuffer[LAST+lineOffset], TXT_NAND);
if(ios[i].infoVersionPatch) strcat(ReportBuffer[LAST+lineOffset], TXT_VersionP);
if(ios[i].infoBoot2Access) strcat(ReportBuffer[LAST+lineOffset], TXT_Boot2);
if(ios[i].infoUSB2) strcat(ReportBuffer[LAST+lineOffset], TXT_USB);
if(!ios[i].infoFakeSignature && !ios[i].infoESIdentify && !ios[i].infoFlashAccess && !ios[i].infoNANDAccess && !ios[i].infoUSB2 && !ios[i].infoVersionPatch) strcat(ReportBuffer[LAST+lineOffset], TXT_NoPatch);
ReportBuffer[LAST+lineOffset][strlen(ReportBuffer[LAST+lineOffset])-1]='\0';
}
}
}
sprintf(ReportBuffer[17+lineOffset], TXT_ReportDate);
int NumLines = 17+lineOffset;
// Mount the SD Card
printLoading(MSG_MountSD);
usleep(250000);
MountSD();
// Initialise the FAT file system
printLoading(MSG_InitFAT);
usleep(250000);
if (!fatInitDefault())
{
sprintf(MSG_Buffer, ERR_InitFAT);
printError(MSG_Buffer);
sleep(2);
printEndError(MSG_ReportError);
} else {
// Create the report
FILE *file = fopen(REPORT, "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");
}
// Close the report
fclose(file);
printEndSuccess(MSG_ReportSuccess);
}
// Create hash log
file = fopen(HASHLOG, "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");
}
// Close the report
fclose(file);
printEndSuccess(MSG_ReportSuccess);
}
}
int LineNr = 0;
WPAD_Init();
bool reportIsDisplayed = false;
while (1) {
WPAD_ScanPads();
wpressed = WPAD_ButtonsHeld(0);
// Return to the loader
if (wpressed & WPAD_BUTTON_HOME) {
// Unmount the SD Card
UnmountSD();
if(*LOADER_STUB) return true;
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
}
// Return to System Menu
if (wpressed & WPAD_BUTTON_PLUS) {
// Unmount the SD Card
UnmountSD();
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
}
// Shutdown Wii
if (wpressed & WPAD_BUTTON_MINUS) {
// Unmount the SD Card
UnmountSD();
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);
reportIsDisplayed = true;
}
}
if (wpressed & WPAD_BUTTON_UP) {
if (LineNr > 0) LineNr--;
printReport(ReportBuffer, LineNr, completeReport);
}
if (wpressed & WPAD_BUTTON_DOWN) {
if (LineNr < NumLines-14) LineNr++;
printReport(ReportBuffer, LineNr, completeReport);
}
if (wpressed & WPAD_BUTTON_LEFT) {
if (LineNr > 0) LineNr = LineNr - 15;
if (LineNr < 0) LineNr = 0;
printReport(ReportBuffer, LineNr, completeReport);
}
if (wpressed & WPAD_BUTTON_RIGHT) {
if (LineNr < NumLines-14) LineNr = LineNr + 15;
if (LineNr > NumLines) LineNr = NumLines;
printReport(ReportBuffer, LineNr, completeReport);
}
}
}