s32 Identify(const u8 *certs, u32 certs_size, const u8 *idtmd, u32 idtmd_size, const u8 *idticket, u32 idticket_size) { s32 ret; u32 keyid = 0; ret = ES_Identify((signed_blob*)certs, certs_size, (signed_blob*)idtmd, idtmd_size, (signed_blob*)idticket, idticket_size, &keyid); if (ret < 0){ switch(ret){ case ES_EINVAL: printf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret); break; case ES_EALIGN: printf("Error! ES_Identify (ret = %d;) Data not aligned!\n", ret); break; case ES_ENOTINIT: printf("Error! ES_Identify (ret = %d;) ES not initialized!\n", ret); break; case ES_ENOMEM: printf("Error! ES_Identify (ret = %d;) No memory!\n", ret); break; default: printf("Error! ES_Identify (ret = %d)\n", ret); break; } } else printf("OK!\n"); return ret; }
/* s32 ISFS_ReadFileToArray (char *filepath, u8 *filearray, u32 max_size, u32 *file_size) { s32 ret, fd; static fstats filestats ATTRIBUTE_ALIGN(32); ret = ISFS_Open(filepath, ISFS_OPEN_READ); if (ret <= 0) { printf("Error! ISFS_Open (ret = %d)\n", ret); return -1; } fd = ret; ret = ISFS_GetFileStats(fd, &filestats); if (ret < 0) { printf("Error! ISFS_GetFileStats (ret = %d)\n", ret); return -1; } *file_size = filestats.file_length; if (*file_size > max_size) { printf("File is too large! Size: %u", *file_size); return -1; } ret = ISFS_Read(fd, filearray, *file_size); if (ret < 0) { printf("Error! ISFS_Read (ret = %d)\n", ret); return -1; } ret = ISFS_Close(fd); if (ret < 0) { printf("Error! ISFS_Close (ret = %d)\n", ret); return -1; } return 0; } */ s32 Identify(const u8 *certs, u32 certs_size, const u8 *idtmd, u32 idtmd_size, const u8 *idticket, u32 idticket_size) { s32 ret; u32 keyid = 0; ret = ES_Identify((signed_blob*)certs, certs_size, (signed_blob*)idtmd, idtmd_size, (signed_blob*)idticket, idticket_size, &keyid); if (ret < 0) { printf("\n"); switch(ret){ case ES_EINVAL: printf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret); break; case ES_EALIGN: printf("Error! ES_Identify (ret = %d;) Data not aligned!\n", ret); break; case ES_ENOTINIT: printf("Error! ES_Identify (ret = %d;) ES not initialized!\n", ret); break; case ES_ENOMEM: printf("Error! ES_Identify (ret = %d;) No memory!\n", ret); break; default: printf("Error! ES_Identify (ret = %d)\n", ret); break; } if (!ISALIGNED(certs)) printf("\tCertificate data is not aligned!\n"); if (!ISALIGNED(idtmd)) printf("\tTMD data is not aligned!\n"); if (!ISALIGNED(idticket)) printf("\tTicket data is not aligned!\n"); } return ret; }
s32 identify(u64 titleid, u32 *ios){ char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(0x20); u8 *tmdBuffer = NULL; u32 tmdSize; signed_blob *tikBuffer = NULL; u32 tikSize; u8 *certBuffer = NULL; u32 certSize; int ret; printf("Reading TMD..."); fflush(stdout); sprintf(filepath, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(titleid), TITLE_LOWER(titleid)); ret = read_file(filepath, &tmdBuffer, &tmdSize); if (ret < 0) { printf("Reading TMD failed\n"); return ret; } printf("done\n"); *ios = (u32)(tmdBuffer[0x18b]); printf("Generating fake ticket..."); fflush(stdout); /* sprintf(filepath, "/ticket/%08x/%08x.tik", TITLE_UPPER(titleid), TITLE_LOWER(titleid)); ret = read_file(filepath, &tikBuffer, &tikSize); if (ret < 0) { printf("Reading ticket failed\n"); free(tmdBuffer); return ret; }*/ Identify_GenerateTik(&tikBuffer,&tikSize); printf("done\n"); printf("Reading certs..."); fflush(stdout); sprintf(filepath, "/sys/cert.sys"); ret = read_file(filepath, &certBuffer, &certSize); if (ret < 0) { printf("Reading certs failed\n"); free(tmdBuffer); free(tikBuffer); return ret; } printf("done\n"); printf("ES_Identify..."); fflush(stdout); ret = ES_Identify((signed_blob*)certBuffer, certSize, (signed_blob*)tmdBuffer, tmdSize, tikBuffer, tikSize, NULL); if (ret < 0) { switch(ret) { case ES_EINVAL: printf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret); break; case ES_EALIGN: printf("Error! ES_Identify (ret = %d;) Data not aligned!\n", ret); break; case ES_ENOTINIT: printf("Error! ES_Identify (ret = %d;) ES not initialized!\n", ret); break; case ES_ENOMEM: printf("Error! ES_Identify (ret = %d;) No memory!\n", ret); break; default: printf("Error! ES_Identify (ret = %d)\n", ret); break; } free(tmdBuffer); free(tikBuffer); free(certBuffer); return ret; } printf("done\n"); free(tmdBuffer); free(tikBuffer); free(certBuffer); return 0; }
return ERR_NONE; } void changeChannelName(u64 titleID) { printf("Identifying as 00000001-00000000 (SU)!... "); CheckESRetval(ES_Identify(SU_IDENTIFY)); // if(ES_SetUID(titleID)<0) // return; u32 tmd_size ATTRIBUTE_ALIGN(32); if(CheckESRetval(ES_GetStoredTMDSize(titleID, &tmd_size))!=0) return; signed_blob *TMD = (signed_blob *)memalign( 32, tmd_size ); memset(TMD, 0, tmd_size); if(CheckESRetval(ES_GetStoredTMD(titleID, TMD, tmd_size))!=0) { free(TMD); return; } u32 cnt ATTRIBUTE_ALIGN(32); if(CheckESRetval(ES_GetNumTicketViews(titleID, &cnt))!=0) { free(TMD); return; } if( cnt <= 0 ) { free(TMD); return; } tikview *views = (tikview *)memalign( 32, sizeof(tikview)*cnt ); if(CheckESRetval(ES_GetTicketViews(titleID, views, cnt))!=0) { free(views); free(TMD); return; } char *name=calloc((0x54/2),1); int z; for(z=0; z < 1; ++z) { tmd_content *TMDc = TMD_CONTENTS(((tmd*)(SIGNATURE_PAYLOAD(TMD)))); // OH GOD CREDIAR, WTF WAS THAT MESS!!! //printf("%d,",TMDc->index); s32 cfd = ES_OpenTitleContent( titleID, TMDc->index); free(views); if(CheckESRetval(cfd)!=0) { ; //printf("ES_OpenContent(%d) failed\n", cfd); //sleep(10); //exit(0); } else { u64 sz ATTRIBUTE_ALIGN(32) = 0x140; u8 *data = (u8*)memalign(32, sz); if( TMDc->size < sz ) sz = TMDc->size; if( data != NULL ) { if(ES_ReadContent(cfd, data, sz)<0) { free(data); return; } int y; int chan_name_offset=(language_setting*0x54); // Set to WiiMU's language for(y=0;y<(0x54/2);y++) name[y]=data[(0x9C+chan_name_offset)+(y*2)+1]; } if(CheckESRetval(ES_CloseContent(cfd))!=0) { ; //printf("ES_CloseContent failed\n"); //sleep(10); //exit(0); } free(data); } } int wiistring_size; reenter: wiistring_size=type_string_wiimote(name, 0x54/2); if(wiistring_size<=0) { printf("\n\nPlease enter a name!\n"); sleep(3); goto reenter; } name[wiistring_size+1]=0; /* Get Content */ char nameDirectory[80]; tmd_content *TMDc = TMD_CONTENTS(((tmd*)(SIGNATURE_PAYLOAD(TMD)))); sprintf(nameDirectory,"/title/%08x/%08x/content/%08x.app",TITLE_UPPER(titleID),TITLE_LOWER(titleID),TMDc->cid); s32 contentFd=ISFS_Open(nameDirectory,ISFS_OPEN_RW); CheckISFSRetval(contentFd); ClearScreen(); printf("\n\nOpened content!\n"); u8 *data=calloc(TMDc->size,1); int isUnaligned = ((int)data)%32 | TMDc->size%32; int alignedLen = (TMDc->size+31)&0xffffffe0; u8* alignedBuf; if(isUnaligned) alignedBuf = memalign(32, alignedLen); else alignedBuf = data; CheckISFSRetval(ISFS_Seek(contentFd,0,0)); CheckISFSRetval(ISFS_Read(contentFd, alignedBuf, alignedLen)); printf("Read content!\n"); int y; int chan_name_offset=(SYSCONF_GetArea()*0x54); // Edits the one for the Wii's system Menu char* nameOut=calloc(96,1); for(y=0;y<(0x54/2);y++) nameOut[(y*2)+1]=name[y]; printf("Wrote new name! %s\n", name); CheckISFSRetval(ISFS_Seek(contentFd,(0x9C+chan_name_offset),0)); printf("Seeked to location!\n"); if(nameOut==NULL) { printf("FAILED! (Name Out is NULL!)\n"); sleep(5); Finish(1); } if(((u32)nameOut%32)!=0) { isUnaligned = ((int)nameOut)%32 | 0x54%32; alignedLen = (0x54+31)&0xffffffe0; if(isUnaligned){ alignedBuf = memalign(32, alignedLen); memcpy(alignedBuf, nameOut, 0x54); } else alignedBuf = (u8*)nameOut; } CheckISFSRetval(ISFS_Write(contentFd, alignedBuf, 0x54)); printf("Wrote content name!\nReading new Header Chunk!\n"); CheckISFSRetval(ISFS_Seek(contentFd,0,0)); CheckISFSRetval(ISFS_Read(contentFd, alignedBuf, alignedLen)); printf("Read content!\n"); u8* header_chunk=calloc(0x640, 1); int i; for(i=0;i<0x630;i++) header_chunk[i]=alignedBuf[i]; for(i=0x630;i<0x640;i++) header_chunk[i]=0; u8* hash=calloc(0x10,1); md5(header_chunk, 0x640, hash); CheckISFSRetval(ISFS_Seek(contentFd,0x630,0)); printf("Seeked to location!\n"); if(hash==NULL) { printf("FAILED! (Hash is NULL!)\n"); sleep(5); Finish(1); } if(((u32)hash%32)!=0) { isUnaligned = ((int)hash)%32 | 0x10%32; alignedLen = (0x10+31)&0xffffffe0; if(isUnaligned){ alignedBuf = memalign(32, alignedLen); memcpy(alignedBuf, hash, 0x10); } else alignedBuf = hash;
s32 identify(u64 titleid, u32 *ios) { char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32); u8 *tmdBuffer = NULL; u32 tmdSize; signed_blob *tikBuffer = NULL; u32 tikSize; u8 *certBuffer = NULL; u32 certSize; int ret; debug("Reading TMD..."); fflush(stdout); sprintf(filepath, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(titleid), TITLE_LOWER(titleid)); ret = read_full_file_from_nand(filepath, &tmdBuffer, &tmdSize); if (ret < 0) { debug("ERR: (identify) Reading TMD failed\n"); return ret; } debug("done\n"); *ios = (u32)(tmdBuffer[0x18b]); debug("Generating fake ticket..."); fflush(stdout); Identify_GenerateTik(&tikBuffer,&tikSize); debug("done\n"); debug("Reading certs..."); fflush(stdout); sprintf(filepath, "/sys/cert.sys"); ret = read_full_file_from_nand(filepath, &certBuffer, &certSize); if (ret < 0) { debug("Reading certs failed, trying to use embedded one\n"); certBuffer = allocate_memory(cert_sys_size); certSize = cert_sys_size; if (certBuffer != NULL) memcpy (certBuffer, cert_sys, cert_sys_size); else { free(tmdBuffer); free(tikBuffer); return ret; } } debug("done\n"); debug("ES_Identify..."); fflush(stdout); ret = ES_Identify((signed_blob*)certBuffer, certSize, (signed_blob*)tmdBuffer, tmdSize, tikBuffer, tikSize, NULL); if (ret < 0) { switch(ret) { case ES_EINVAL: debug("ERR: (identify) ES_Identify (ret = %d;) Data invalid!\n", ret); break; case ES_EALIGN: debug("ERR: (identify) ES_Identify (ret = %d;) Data not aligned!\n", ret); break; case ES_ENOTINIT: debug("ERR: (identify) ES_Identify (ret = %d;) ES not initialized!\n", ret); break; case ES_ENOMEM: debug("ERR: (identify) ES_Identify (ret = %d;) No memory!\n", ret); break; default: debug("ERR: (identify) ES_Identify (ret = %d)\n", ret); break; } free(tmdBuffer); free(tikBuffer); free(certBuffer); sleep (5); return ret; } debug("done\n"); free(tmdBuffer); free(tikBuffer); free(certBuffer); return 0; }
static int identify(void){ // Identify as our own title void* dvdCert = NULL, * dvdTMD = NULL, * dvdTicket = NULL; unsigned int dvdCertSize, dvdTMDSize, dvdTicketSize, keyid; int ret; if(!customCert){ // If there's no certificate supplied #if 0 // Use the one from the DVD ret = getTitle(&dvdCert, &dvdCertSize, &dvdTMD, &dvdTMDSize, &dvdTicket, &dvdTicketSize); customCert = dvdCert; customCertSize = dvdCertSize; if(ret < 0) return ret; #else return identified = 0; #endif } ret = ES_Identify(customCert, customCertSize, customTMD, customTMDSize, customTicket, customTicketSize, &keyid); if(ret >= 0){ ES_GetTitleID(&titleID); ISFS_Initialize(); // If we haven't identified this title before // we'll need to set some things up char* path = memalign(32, 64);; ES_GetDataDir(titleID, path); strncat(path, "/banner.bin", 64); ret = ISFS_Open(path, 1); if(ret < 0){ // If the banner doesn't exist // Create our banner.bin ret = ISFS_CreateFile(path, 0, 3, 3, 1); if(ret < 0) return 0; ret = ISFS_Open(path, 2); if(ret < 0) return 0; ISFS_Write(ret, customBanner, customBannerSize); ISFS_Close(ret); // Create the N64SAVES directory ES_GetDataDir(titleID, path); strncat(path, "/N64SAVES", 64); ISFS_CreateDir(path, 0, 3, 3, 1); } else ISFS_Close(ret); free(path); return identified = 1; } #if 0 // If that still fails, try to identify from the discs certs if(!dvdCert || !dvdTMD || !dvdTicket) ret = getTitle(&dvdCert, &dvdCertSize, &dvdTMD, &dvdTMDSize, &dvdTicket, &dvdTicketSize); else ret = 0; if(ret >= 0){ ret = ES_Identify(dvdCert, dvdCertSize, dvdTMD, dvdTMDSize, dvdTicket, dvdTicketSize, &keyid); ES_GetTitleID(&titleID); ISFS_Initialize(); return identified = (ret >= 0); } #endif return identified = 0; }