📄 patchmii_core.c
字号:
u32 i; u32 match_count = 0; u8 old_table[] = {0x00,0x00,0x00,0x01,0xFF,0xFF,0xFC,0x07,0xB5,0xF0}; u8 new_table[] = {0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0xB5,0xF0}; for (i=0; i<size-sizeof old_table; i++) { if (!memcmp(buf + i, old_table, sizeof old_table)) {// debug_printf("Found IOS deletion check @ 0x%x, patching.\n", i); memcpy(buf + i, new_table, sizeof new_table); buf += sizeof new_table; match_count++; continue; } } if (match_count > 1) { printf("Match count for %s was %d, expected 1; failing.\n", __FUNCTION__, match_count); exit(1); } return match_count;}/* This patch disables the MEM2 protection */int patch_mem2protect(u8 *buf, u32 size){ u32 i; u32 match_count = 0; u8 old_table[] = {0xB5,0x00,0x4B,0x09,0x22,0x01,0x80,0x1A,0x22,0xF0}; u8 new_table[] = {0xB5,0x00,0x4B,0x09,0x22,0x00,0x80,0x1A,0x22,0xF0}; for (i=0; i<size-sizeof old_table; i++) { if (!memcmp(buf + i, old_table, sizeof old_table)) {// debug_printf("Found MEM2 protection enable @ 0x%x, patching.\n", i); memcpy(buf + i, new_table, sizeof new_table); buf += sizeof new_table; match_count++; continue; } } if (match_count > 2) { debug_printf("Match count for %s was %d, expected 1 or 2; failing.\n", __FUNCTION__, match_count); exit(1); } return match_count;}void print_tmd_summary(const tmd *p_tmd) { const tmd_content *p_cr; p_cr = TMD_CONTENTS(p_tmd); u32 size=0; u16 i=0; for(i=0;i<p_tmd->num_contents;i++) { size += p_cr[i].size; } debug_printf("Title ID: %016llx\n",p_tmd->title_id); debug_printf("Number of parts: %d. Total size: %uK\n", p_tmd->num_contents, (u32) (size / 1024));}void zero_sig(signed_blob *sig) { u8 *sig_ptr = (u8 *)sig; memset(sig_ptr + 4, 0, SIGNATURE_SIZE(sig)-4);}void brute_tmd(tmd *p_tmd) { u16 fill; for(fill=0; fill<65535; fill++) { p_tmd->fill3=fill; sha1 hash; // debug_printf("SHA1(%p, %x, %p)\n", p_tmd, TMD_SIZE(p_tmd), hash); SHA1((u8 *)p_tmd, TMD_SIZE(p_tmd), hash);; if (hash[0]==0) { // debug_printf("setting fill3 to %04hx\n", fill); return; } } printf("Unable to fix tmd :(\n"); exit(4);}void brute_tik(tik *p_tik) { u16 fill; for(fill=0; fill<65535; fill++) { p_tik->padding=fill; sha1 hash; // debug_printf("SHA1(%p, %x, %p)\n", p_tmd, TMD_SIZE(p_tmd), hash); SHA1((u8 *)p_tik, sizeof(tik), hash); if (hash[0]==0) return; } printf("Unable to fix tik :(\n"); exit(5);} void forge_tmd(signed_blob *s_tmd) {// debug_printf("forging tmd sig"); zero_sig(s_tmd); brute_tmd(SIGNATURE_PAYLOAD(s_tmd));}void forge_tik(signed_blob *s_tik) {// debug_printf("forging tik sig"); zero_sig(s_tik); brute_tik(SIGNATURE_PAYLOAD(s_tik));}#define BLOCK 0x1000s32 install_ticket(const signed_blob *s_tik, const signed_blob *s_certs, u32 certs_len) { u32 ret;progress(10);// debug_printf("Installing ticket...\n"); ret = ES_AddTicket(s_tik,STD_SIGNED_TIK_SIZE,s_certs,certs_len, NULL, 0); if (ret < 0) { debug_printf("ES_AddTicket failed: %d\n",ret); return ret; } return 0;}s32 install(const signed_blob *s_tmd, const signed_blob *s_certs, u32 certs_len) { u32 ret, i; tmd *p_tmd = SIGNATURE_PAYLOAD(s_tmd);// debug_printf("Adding title...\n"); ret = ES_AddTitleStart(s_tmd, SIGNED_TMD_SIZE(s_tmd), s_certs, certs_len, NULL, 0);progress(40); if(ret < 0) { debug_printf("ES_AddTitleStart failed: %d\n",ret); ES_AddTitleCancel(); return ret; } for(i=0; i<p_tmd->num_contents; i++) {// debug_printf("Adding content ID %08x", i); ret = install_nus_object((tmd *)SIGNATURE_PAYLOAD(s_tmd), i); if (ret) return ret; } ret = ES_AddTitleFinish(); if(ret < 0) { printf("ES_AddTitleFinish failed: %d\n",ret); ES_AddTitleCancel(); return ret; }// printf("Installation complete!\n"); return 0;}void patchmii_network_init(void) { int retval;// printf("HackMii KeyRipper -- Initializing network."); fflush(stdout); printf("xyzzy v1.1, powered by PatchMii\nSending things to Earth..."); fflush(stdout); while (1) { retval = net_init (); if (retval < 0) { if (retval != -EAGAIN) { debug_printf ("net_init failed: %d\nI need a network to download IOS, sorry :(\n)", retval); exit(0); } } if (!retval) break; usleep(100000); printf("."); fflush(stdout); } printf("\n");}void patchmii_download(u32 titleid1, u32 titleid2) { u8 *temp_tmdbuf = NULL, *temp_tikbuf = NULL; u32 tmdsize; u8 update_tmd; int i, retval; if (ISFS_Initialize() || create_temp_dir()) { perror("Failed to create temp dir: "); exit(1); }// debug_printf("Downloading IOS%d metadata: ..", titleid2);// debug_printf("Sending things to Earth..."); retval = get_nus_object(titleid1, titleid2, "tmd.10", &temp_tmdbuf, &tmdsize); if (retval<0) { debug_printf("get_nus_object(tmd) returned %d, tmdsize = %u\n", retval, tmdsize); exit(1); } if (temp_tmdbuf == NULL) { debug_printf("Failed to allocate temp buffer for encrypted content, size was %u\n", tmdsize); exit(1); } memcpy(tmdbuf, temp_tmdbuf, MIN(tmdsize, sizeof(tmdbuf))); free(temp_tmdbuf); s_tmd = (signed_blob *)tmdbuf; if(!IS_VALID_SIGNATURE(s_tmd)) { debug_printf("Bad TMD signature!\n"); exit(1); } u32 ticketsize; retval = get_nus_object(titleid1, titleid2, "cetk", &temp_tikbuf, &ticketsize); if (retval < 0) debug_printf("get_nus_object(cetk) returned %d, ticketsize = %u\n", retval, ticketsize); memcpy(tikbuf, temp_tikbuf, MIN(ticketsize, sizeof(tikbuf))); s_tik = (signed_blob *)tikbuf; if(!IS_VALID_SIGNATURE(s_tik)) { debug_printf("Bad tik signature!\n"); exit(1); } free(temp_tikbuf); s_certs = (signed_blob *)haxx_certs; if(!IS_VALID_SIGNATURE(s_certs)) { debug_printf("Bad cert signature!\n"); exit(1); } u8 key[16]; get_title_key(s_tik, key); aes_set_key(key); const tmd *p_tmd; tmd_content *p_cr; p_tmd = (tmd*)SIGNATURE_PAYLOAD(s_tmd); p_cr = TMD_CONTENTS(p_tmd); // print_tmd_summary(p_tmd);// debug_printf("\b ..games..\b"); static char cidstr[32]; for (i=0;i<p_tmd->num_contents;i++) {// debug_printf("Downloading part %d/%d (%lluK): ", i+1, // p_tmd->num_contents, p_cr[i].size / 1024); sprintf(cidstr, "%08x", p_cr[i].cid); u8 *content_buf, *decrypted_buf; u32 content_size; retval = get_nus_object(titleid1, titleid2, cidstr, &content_buf, &content_size); if (retval < 0) { debug_printf("get_nus_object(%s) failed with error %d, content size = %u\n", cidstr, retval, content_size); exit(1); } if (content_buf == NULL) { debug_printf("error allocating content buffer, size was %u\n", content_size); exit(1); } if (content_size % 16) { debug_printf("ERROR: downloaded content[%hu] size %u is not a multiple of 16\n", i, content_size); free(content_buf); exit(1); } if (content_size < p_cr[i].size) { debug_printf("ERROR: only downloaded %u / %llu bytes\n", content_size, p_cr[i].size); free(content_buf); exit(1); } decrypted_buf = malloc(content_size); if (!decrypted_buf) { debug_printf("ERROR: failed to allocate decrypted_buf (%u bytes)\n", content_size); free(content_buf); exit(1); } decrypt_buffer(i, content_buf, decrypted_buf, content_size); sha1 hash; SHA1(decrypted_buf, p_cr[i].size, hash); if (!memcmp(p_cr[i].hash, hash, sizeof hash)) {// debug_printf("\b\b hash OK. ");// display_ios_tags(decrypted_buf, content_size); update_tmd = 0; if(patch_iosdelete(decrypted_buf, content_size)) update_tmd = 1; if(patch_mem2protect(decrypted_buf, content_size)) update_tmd = 1; if(update_tmd == 1) {// debug_printf("Updating TMD.\n"); SHA1(decrypted_buf, p_cr[i].size, hash); memcpy(p_cr[i].hash, hash, sizeof hash); tmd_dirty=1; } retval = (int) save_nus_object(p_cr[i].cid, decrypted_buf, content_size); if (retval < 0) { debug_printf("save_nus_object(%x) returned error %d\n", p_cr[i].cid, retval); exit(1); } } else { debug_printf("hash BAD\n"); exit(1); } free(decrypted_buf); free(content_buf); }// debug_printf("\b ..keys..\b"); }s32 find_empty_IOS_slot(void) { int i; for (i=255; i>64; i--) { if (get_title_version(1,i)==-106) break; } if (i>64) {// debug_printf("Found empty IOS slot (IOS%d)\n", i); temp_ios_slot = i; return i; } debug_printf("Couldn't find empty IOS slot :(\n"); return -1;}s32 install_temporary_ios(u32 base_ios) { if (find_empty_IOS_slot()==-1) return -1; patchmii_download(1, base_ios); change_ticket_title_id(s_tik, 1, temp_ios_slot); change_tmd_title_id(s_tmd, 1, temp_ios_slot); change_tmd_version(s_tmd, 31337); forge_tmd(s_tmd); forge_tik(s_tik);// debug_printf("Download complete. Installing:\n"); int retval = install_ticket(s_tik, s_certs, haxx_certs_size); if (retval) { debug_printf("install_ticket returned %d\n", retval); exit(1); } retval = install(s_tmd, s_certs, haxx_certs_size);// debug_printf("\b..hacks..\b"); if (retval) printf("install returned %d\n", retval); return retval;}s32 load_temporary_ios(void) { return IOS_ReloadIOS(temp_ios_slot);}s32 cleanup_temporary_ios(void) { debug_printf("Cleaning up temporary IOS version %d\n", temp_ios_slot); if (temp_ios_slot < 64) { // this should never happen printf("Not gonna do it, would't be prudent...\n"); while(1); } /* This code should work, but ends up getting an error -1017... s32 vers = get_title_version(1, temp_ios_slot); debug_printf("Detected version %d of IOS%d\n", vers, temp_ios_slot); if (vers != 31337) { debug_printf("Error: we didn't make this version of IOS\n"); return -1; } */ u64 title = (u64) 1 << 32 | (u64)temp_ios_slot; int retval = ES_DeleteTitle(title); if (retval < 0) debug_printf("ES_DeleteTitle(%016llx) returned %d\n", title, retval); return retval;}#ifdef STANDALONEint main(int argc, char **argv) { console_setup(); printf("PatchMii Core v" VERSION ", by bushing\n");// ******* WARNING *******// Obviously, if you're reading this, you're obviously capable of disabling the// following checks. If you put any of the following titles into an unusuable state, // your Wii will fail to boot://// 1-1 (BOOT2), 1-2 (System Menu), 1-30 (IOS30, currently specified by 1-2's TMD)// Corrupting other titles (for example, BC or the banners of installed channels)// may also cause difficulty booting. Please do not remove these safety checks// unless you have performed extensive testing and are willing to take on the risk// of bricking the systems of people to whom you give this code. -bushing if ((OUTPUT_TITLEID_H == 1) && (OUTPUT_TITLEID_L == 2)) { printf("Sorry, I won't modify the system menu; too dangerous. :(\n"); while(1); } if ((OUTPUT_TITLEID_H == 1) && (OUTPUT_TITLEID_L == 30)) { printf("Sorry, I won't modify IOS30; too dangerous. :(\n"); while(1); } printvers(); patchmii_network_init();// patchmii_download(INPUT_TITLEID_H, INPUT_TITLEID_L);// patchmii_install(); install_temporary_ios(11); cleanup_temporary_ios(); debug_printf("Done!\n"); exit(0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -