From: root Date: Sat, 14 May 2016 23:11:28 +0000 (-0400) Subject: So, we now are capable of signature patches. X-Git-Tag: stable-1~78 X-Git-Url: https://chaos.moe/g/?a=commitdiff_plain;h=82e21d2082a7172564224578ef1c95cea66b2e85;p=corbenik%2Fcorbenik.git So, we now are capable of signature patches. --- diff --git a/asm/backdoor.s b/asm/backdoor.s new file mode 100644 index 0000000..bcd09e1 --- /dev/null +++ b/asm/backdoor.s @@ -0,0 +1,14 @@ +// This is svcBackdoor's code from earlier FIRMs +.arm.little +.create "backdoor.bin", 0 + bic r1, sp, #0xff + orr r1, r1, #0xf00 + add r1, r1, #0x28 + ldr r2, [r1] + stmdb r2!, {sp, lr} + mov sp, r2 + blx r0 + pop {r0, r1} + mov sp, r0 + bx r1 +.close diff --git a/asm/sigpatches.s b/asm/sigpatches.s new file mode 100644 index 0000000..dd1220e --- /dev/null +++ b/asm/sigpatches.s @@ -0,0 +1,12 @@ +.arm.little + +.create "sig1.to", 0 +.thumb +mov r0, #0 +.close + +.create "sig2.to", 0 +.thumb +mov r0, #0 +bx lr +.close diff --git a/source/config.c b/source/config.c index d4e8eaa..e6b9a00 100644 --- a/source/config.c +++ b/source/config.c @@ -2,6 +2,8 @@ FILE* conf_handle; +struct config_file config; + void regenerate_config() { f_mkdir(PATH_CFW); f_mkdir(PATH_FIRMWARES); @@ -17,6 +19,7 @@ void regenerate_config() { memcpy(&(config.magic), CONFIG_MAGIC, 4); config.config_ver = config_version; + if(!(conf_handle = fopen(PATH_CONFIG, "w"))) abort("Failed to open config for write?\n"); @@ -63,3 +66,14 @@ void load_config() { fprintf(BOTTOM_SCREEN, "Config file loaded.\n"); } +void save_config() { + fprintf(stderr, "Saving config.\n"); + + f_unlink(PATH_CONFIG); + + if(!(conf_handle = fopen(PATH_CONFIG, "w"))) + abort("Failed to open config for write?\n"); + + fwrite(&config, 1, sizeof(config), conf_handle); + fclose(conf_handle); +} diff --git a/source/config.h b/source/config.h index 5b4d250..6325543 100644 --- a/source/config.h +++ b/source/config.h @@ -15,7 +15,7 @@ struct config_file { uint64_t patch_ids[256]; // What patches are enabled by UUID. 256 is an arbitrary limit - contact me if you hit it. }__attribute__((packed)); -_UNUSED static struct config_file config; +extern struct config_file config; #define OPTION_SIGPATCH 0 // Use builtin signature patch. #define OPTION_LOADER 1 // Use builtin loader module replacer. @@ -38,6 +38,7 @@ _UNUSED static struct config_file config; #define ARROW_COLOR 14 // Color of Arrow. void load_config(); +void save_config(); /* [CORBENIK] diff --git a/source/firm/firm.c b/source/firm/firm.c index 27e6000..29187ec 100644 --- a/source/firm/firm.c +++ b/source/firm/firm.c @@ -8,17 +8,19 @@ firm_h *firm_loc = (firm_h *)FCRAM_FIRM_LOC; static uint32_t firm_size = FCRAM_SPACING; firm_section_h firm_proc9; +exefs_h *firm_p9_exefs; firm_h *twl_firm_loc = (firm_h *)FCRAM_TWL_FIRM_LOC; static uint32_t twl_firm_size = FCRAM_SPACING * 2; firm_section_h twl_firm_proc9; +exefs_h *twl_firm_p9_exefs; firm_h *agb_firm_loc = (firm_h *)FCRAM_AGB_FIRM_LOC; static uint32_t agb_firm_size = FCRAM_SPACING; firm_section_h agb_firm_proc9; +exefs_h *agb_firm_p9_exefs; static int update_96_keys = 0; -static int save_firm = 0; static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8; @@ -77,13 +79,12 @@ int decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key) { return 0; } -int decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title) { +int decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title, uint8_t version) { uint8_t slot = 0x15; fprintf(BOTTOM_SCREEN, "Decrypting ARM9 FIRM binary\n"); -// if (firm_title == NATIVE_FIRM_TITLEID && version > 0x0F) { - if (firm_title == NATIVE_FIRM_TITLEID) { + if (firm_title == NATIVE_FIRM_TITLEID && version > 0x0F) { uint8_t decrypted_keyx[AES_BLOCK_SIZE]; slot0x11key96_init(); @@ -162,9 +163,12 @@ int load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint fprintf(BOTTOM_SCREEN, "FIRM not encrypted\n"); } + struct firm_signature* fsig = get_firm_info(dest); + + fprintf(BOTTOM_SCREEN, "FIRM version: %s\n", fsig->version_string); + // The N3DS firm has an additional encryption layer for ARM9 - // Only run if n3ds. - { + if (fsig->console == console_n3ds) { // Look for the arm9 section for (firm_section_h *section = dest->section; section < dest->section + 4; section++) { @@ -179,7 +183,7 @@ int load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint if (arm9bin_iscrypt) { // Decrypt the arm9bin. - if (decrypt_arm9bin((arm9bin_h *)((uintptr_t)dest + section->offset), firm_title)) { + if (decrypt_arm9bin((arm9bin_h *)((uintptr_t)dest + section->offset), firm_title, fsig->version)) { fprintf(BOTTOM_SCREEN, "Couldn't decrypt ARM9 FIRM binary.\n" "Check if you have the needed key at:\n" " " PATH_SLOT0X11KEY96 "\n"); @@ -189,9 +193,9 @@ int load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint firmware_changed = 1; // Decryption of arm9bin performed. } else { fprintf(BOTTOM_SCREEN, "ARM9 FIRM binary not encrypted\n"); -// if (firm_type == NATIVE_FIRM && firm_current->version > 0x0F) { + if (firm_title == NATIVE_FIRM_TITLEID && fsig->version > 0x0F) { slot0x11key96_init(); // This has to be loaded regardless, otherwise boot will fail. -// } + } } // We assume there's only one section to decrypt. @@ -206,7 +210,7 @@ int load_firm(firm_h *dest, char *path, char *path_firmkey, uint32_t *size, uint write_file(dest, path, *size); } - //if (firm_current->console == console_n3ds) + if (fsig->console == console_n3ds) { fprintf(BOTTOM_SCREEN, "Fixing arm9 entrypoint\n"); @@ -257,13 +261,6 @@ void boot_firm() { fprintf(BOTTOM_SCREEN, "Updated keyX keyslots\n"); } - struct memory_header *memory = (void *)(memory_loc + 1); - while ((uintptr_t)memory < (uintptr_t)memory_loc + *memory_loc) { - memcpy((void *)memory->location, memory + 1, memory->size); - memory = (void *)((uintptr_t)(memory + 1) + memory->size); - } - fprintf(BOTTOM_SCREEN, "Copied memory\n"); - for (firm_section_h *section = firm_loc->section; section < firm_loc->section + 4 && section->address != 0; section++) { memcpy((void *)section->address, (void *)firm_loc + section->offset, section->size); @@ -279,7 +276,7 @@ void boot_firm() { ((void (*)())firm_loc->a9Entry)(); } -int find_proc9(firm_h* firm, firm_section_h* process9) { +int find_proc9(firm_h* firm, firm_section_h* process9, exefs_h** p9exefs) { for (firm_section_h *section = firm->section; section < firm->section + 4; section++) { if (section->address == 0) break; @@ -292,10 +289,10 @@ int find_proc9(firm_h* firm, firm_section_h* process9) { if (ncch->magic == NCCH_MAGIC) { // Found Process9 ncch_ex_h *p9exheader = (ncch_ex_h *)(ncch + 1); - exefs_h *p9exefs = (exefs_h *)(p9exheader + 1); + *p9exefs = (exefs_h *)(p9exheader + 1); process9->address = p9exheader->sci.textCodeSet.address; - process9->size = p9exefs->fileHeaders[0].size; - process9->offset = (void*)(p9exefs + 1) - (void*)firm; + process9->size = (*p9exefs)->fileHeaders[0].size; + process9->offset = (void*)((*p9exefs) + 1) - (void*)firm; fprintf(BOTTOM_SCREEN, "Found Process9 for FIRM.\n"); return 0; } @@ -314,19 +311,19 @@ int load_firms() { fprintf(BOTTOM_SCREEN, "Loading NATIVE_FIRM\n"); if (load_firm(firm_loc, PATH_NATIVE_F, PATH_NATIVE_FIRMKEY, &firm_size, NATIVE_FIRM_TITLEID) != 0) return 1; - find_proc9(firm_loc, &firm_proc9); + find_proc9(firm_loc, &firm_proc9, &firm_p9_exefs); fprintf(BOTTOM_SCREEN, "Loading TWL_FIRM\n"); if(load_firm(twl_firm_loc, PATH_TWL_F, PATH_TWL_FIRMKEY, &twl_firm_size, TWL_FIRM_TITLEID)) fprintf(BOTTOM_SCREEN, "TWL_FIRM failed to load.\n"); else - find_proc9(twl_firm_loc, &twl_firm_proc9); + find_proc9(twl_firm_loc, &twl_firm_proc9, &twl_firm_p9_exefs); fprintf(BOTTOM_SCREEN, "Loading AGB_FIRM\n"); if(load_firm(agb_firm_loc, PATH_AGB_F, PATH_AGB_FIRMKEY, &agb_firm_size, AGB_FIRM_TITLEID)) fprintf(BOTTOM_SCREEN, "AGB_FIRM failed to load.\n"); else - find_proc9(agb_firm_loc, &agb_firm_proc9); + find_proc9(agb_firm_loc, &agb_firm_proc9, &agb_firm_p9_exefs); return 0; } @@ -336,41 +333,5 @@ void boot_cfw() { if (patch_firm_all() != 0) return; - // Only save the firm if that option is required (or it's needed for autoboot), - // and either the patches have been modified, or the file doesn't exist. - if ((save_firm || config.options[OPTION_AUTOBOOT]) && - f_stat(PATH_NATIVE_P, NULL) != 0) { - fprintf(BOTTOM_SCREEN, "Saving patched NATIVE_FIRM\n"); - if (write_file(firm_loc, PATH_NATIVE_P, firm_size) != firm_size) { - fprintf(BOTTOM_SCREEN, "%pFailed to save patched FIRM.\nWriting SD failed.\nThis is fatal.\n", COLOR(RED, BLACK)); - return; - } - } - - if ((save_firm || config.options[OPTION_AUTOBOOT]) && - f_stat(PATH_MEMBIN, NULL) != 0) { - fprintf(BOTTOM_SCREEN, "Saving patched memory\n"); - if (write_file(memory_loc, PATH_MEMBIN, *memory_loc) != *memory_loc) { - fprintf(BOTTOM_SCREEN, "%pFailed to save the patched FIRM\nWriting SD failed.\n", COLOR(RED, BLACK)); - return; - } - } - - if (f_stat(PATH_TWL_P, NULL) != 0) { - fprintf(BOTTOM_SCREEN, "Saving patched TWL_FIRM\n"); - if (write_file(twl_firm_loc, PATH_TWL_P, twl_firm_size) != twl_firm_size) { - fprintf(BOTTOM_SCREEN, "%pFailed to save the patched FIRM\nWriting SD failed.\n", COLOR(RED, BLACK)); - return; - } - } - - if (f_stat(PATH_AGB_P, NULL) != 0) { - fprintf(BOTTOM_SCREEN, "Saving patched AGB_FIRM\n"); - if (write_file(agb_firm_loc, PATH_AGB_P, agb_firm_size) != agb_firm_size) { - fprintf(BOTTOM_SCREEN, "%pFailed to save the patched FIRM\nWriting SD failed.\n", COLOR(RED, BLACK)); - return; - } - } - boot_firm(); } diff --git a/source/firm/firm.h b/source/firm/firm.h index 20eb89b..73f6e57 100644 --- a/source/firm/firm.h +++ b/source/firm/firm.h @@ -3,14 +3,32 @@ #include #include "headers.h" +enum consoles { + console_o3ds, + console_n3ds +}; + +struct firm_signature { + uint8_t sig[0x10]; + unsigned int version; + char version_string[16]; + enum consoles console; +}; + extern firm_h *firm_loc; extern struct firm_signature *current_firm; +extern firm_section_h firm_proc9; +extern exefs_h *firm_p9_exefs; extern firm_h *twl_firm_loc; extern struct firm_signature *current_twl_firm; +extern firm_section_h twl_firm_proc9; +extern exefs_h *twl_firm_p9_exefs; extern firm_h *agb_firm_loc; extern struct firm_signature *current_agb_firm; +extern firm_section_h agb_firm_proc9; +extern exefs_h *agb_firm_p9_exefs; struct firm_signature *get_firm_info(firm_h *firm); void slot0x11key96_init(); diff --git a/source/firm/version.c b/source/firm/version.c new file mode 100644 index 0000000..dfd9180 --- /dev/null +++ b/source/firm/version.c @@ -0,0 +1,105 @@ +#include "firm.h" +#include "../common.h" + +// We use the firm's section 0's hash to identify the version +struct firm_signature firm_signatures[] = { + { + .sig = {0xEE, 0xE2, 0x81, 0x2E, 0xB9, 0x10, 0x0D, 0x03, 0xFE, 0xA2, 0x3F, 0x44, 0xB5, 0x1C, 0xB3, 0x5E}, + .version = 0x1F, + .version_string = "4.1.0", + .console = console_o3ds + }, { + .sig = {0x8C, 0x29, 0xDA, 0x7B, 0xB5, 0x5F, 0xFE, 0x44, 0x1F, 0x66, 0x79, 0x70, 0x8E, 0xE4, 0x42, 0xE3}, + .version = 0x2A, + .version_string = "6.1.0", + .console = console_o3ds + }, { + .sig = {0x1D, 0x96, 0x80, 0xD9, 0x0A, 0xA9, 0xDB, 0xE8, 0x29, 0x77, 0xCB, 0x7D, 0x90, 0x55, 0xB7, 0xF9}, + .version = 0x30, + .version_string = "7.2.0", + .console = console_o3ds + }, { + .sig = {0x3B, 0x61, 0x2E, 0xBA, 0x42, 0xAE, 0x24, 0x46, 0xAD, 0x60, 0x2F, 0x7B, 0x52, 0x16, 0x82, 0x91}, + .version = 0x37, + .version_string = "8.0.0", + .console = console_o3ds + }, { + .sig = {0x3F, 0xBF, 0x14, 0x06, 0x33, 0x77, 0x82, 0xDE, 0xB2, 0x68, 0x83, 0x01, 0x6B, 0x1A, 0x71, 0x69}, + .version = 0x38, + .version_string = "9.0.0", + .console = console_o3ds + }, { + .sig = {0x5C, 0x6A, 0x51, 0xF3, 0x79, 0x4D, 0x21, 0x91, 0x0B, 0xBB, 0xFD, 0x17, 0x7B, 0x72, 0x6B, 0x59}, + .version = 0x49, + .version_string = "9.6.0", + .console = console_o3ds + }, { + .sig = {0xF5, 0x7E, 0xC3, 0x86, 0x1F, 0x8D, 0x8E, 0xFB, 0x44, 0x61, 0xF3, 0x16, 0x51, 0x0A, 0x57, 0x7D}, + .version = 0x50, + .version_string = "10.4.0", + .console = console_o3ds + }, { + .sig = {0xE9, 0xAD, 0x74, 0x9D, 0x46, 0x9C, 0x9C, 0xF4, 0x96, 0x9E, 0x1A, 0x7A, 0xDF, 0x40, 0x2A, 0x82}, + .version = 0x52, + .version_string = "11.0.0", + .console = console_o3ds + }, { + .sig = {0x31, 0xCC, 0x46, 0xCD, 0x61, 0x7A, 0xE7, 0x13, 0x7F, 0xE5, 0xFC, 0x20, 0x46, 0x91, 0x6A, 0xBB}, + .version = 0x04, + .version_string = "9.0.0", + .console = console_n3ds + }, { + .sig = {0x40, 0x35, 0x6C, 0x9A, 0x24, 0x36, 0x93, 0x7B, 0x76, 0xFE, 0x5D, 0xB1, 0x4D, 0x05, 0x06, 0x52}, + .version = 0x0F, + .version_string = "9.5.0", + .console = console_n3ds + }, { + .sig = {0x07, 0xFE, 0x9A, 0x62, 0x3F, 0xDE, 0x54, 0xC1, 0x9B, 0x06, 0x91, 0xD8, 0x4F, 0x44, 0x9C, 0x21}, + .version = 0x1B, + .version_string = "10.2.0", + .console = console_n3ds + }, { + .sig = {0x1A, 0x56, 0x5C, 0xFF, 0xC9, 0xCC, 0x62, 0xBB, 0x2B, 0xC2, 0x23, 0xB6, 0x4F, 0x48, 0xD1, 0xCC}, + .version = 0x1F, + .version_string = "10.4.0", + .console = console_n3ds + }, { + .sig = {0x52, 0x30, 0x0F, 0x55, 0xA2, 0x64, 0x4E, 0xFF, 0x96, 0x90, 0xF0, 0xE5, 0x6E, 0xC8, 0x2E, 0xB3}, + .version = 0x21, + .version_string = "11.0.0", + .console = console_n3ds + }, + { + .sig = {0xE8, 0xB8, 0x82, 0xF5, 0x8C, 0xC4, 0x1B, 0x24, 0x05, 0x60, 0x6D, 0xB8, 0x74, 0xF5, 0xE5, 0xDD}, + .version = 0x16, + .version_string = "6.2.0_TWL", + .console = console_o3ds + }, { + .sig = {0x0F, 0x05, 0xC5, 0xF3, 0x60, 0x83, 0x8B, 0x9D, 0xC8, 0x44, 0x3F, 0xB3, 0x06, 0x4D, 0x30, 0xC7}, + .version = 0x00, + .version_string = "9.0.0_TWL", + .console = console_n3ds + }, + { + .sig = {0x65, 0xB7, 0x55, 0x78, 0x97, 0xE6, 0x5C, 0xD6, 0x11, 0x74, 0x95, 0xDD, 0x61, 0xE8, 0x08, 0x40}, + .version = 0x0B, + .version_string = "6.0.0_AGB", + .console = console_o3ds + }, { + .sig = {0xAF, 0x81, 0xA1, 0xAB, 0xBA, 0xAC, 0xAC, 0xA7, 0x30, 0xE8, 0xD8, 0x74, 0x7C, 0x47, 0x1C, 0x5D}, + .version = 0x00, + .version_string = "9.0.0_AGB", + .console = console_n3ds + }, + {.version = 0xFF} // Terminate list +}; + +struct firm_signature *get_firm_info(firm_h *firm) { + for (struct firm_signature *signature = firm_signatures; signature->version != 0xFF; signature++) { + if (memcmp(signature->sig, firm->section[0].hash, 0x10) == 0) { + return signature; + } + } + + return NULL; +} diff --git a/source/main.c b/source/main.c index bf2ab72..e0ea618 100644 --- a/source/main.c +++ b/source/main.c @@ -1,7 +1,8 @@ #include "common.h" #include "firm/firm.h" -void init_system() {} +void init_system() { +} int menu_handler(); @@ -23,6 +24,10 @@ int main() { in_menu = menu_handler(); } - init_system(); + fprintf(BOTTOM_SCREEN, "Booting CFW\n"); + + save_config(); // Save config file. + + boot_cfw(); // Under ideal conditions, we never get here. } diff --git a/source/menu.c b/source/menu.c index 1c153a6..a44090b 100644 --- a/source/menu.c +++ b/source/menu.c @@ -10,11 +10,28 @@ #define MENU_HELP 5 #define MENU_RESET 6 #define MENU_POWER 7 +#define MENU_DUMPBOOT 8 static int cursor_y = 0; static int which_menu = 1; static int need_redraw = 1; +int menu_dumpboot() { + // No, we can't dump the whole bootrom. + // I'm still curious what's in the readable half. + + FILE *output9; + if(!(output9 = fopen("/bootrom9_low.bin", "w"))) + abort("Failed to open file for write?\n"); + + fwrite((uint8_t*)0xffff0000, 1, 0x8000, output9); + fclose(output9); + + fprintf(stderr, "Dumped 0x8000 bytes at 0xffff0000\n"); + + return MENU_MAIN; +} + uint32_t wait_key() { uint32_t get = 0; while(get == 0) { @@ -179,9 +196,10 @@ int menu_main() { "Help/Readme", "Reset", "Power off", + "Dump partial arm9 bootrom", "Boot firmware" }; - int menu_max = 6; + int menu_max = 8; header(); @@ -219,6 +237,8 @@ int menu_main() { case BUTTON_A: need_redraw = 1; cursor_y = 0; + if (ret == 9) + return MENU_BOOTME; // Boot meh, damnit! return ret; } @@ -249,6 +269,9 @@ int menu_handler() { case MENU_HELP: to_menu = menu_help(); break; + case MENU_DUMPBOOT: + to_menu = menu_dumpboot(); + break; case MENU_BOOTME: return 0; case MENU_RESET: diff --git a/source/patch_format.h b/source/patch_format.h index 38879af..d5957cd 100644 --- a/source/patch_format.h +++ b/source/patch_format.h @@ -70,6 +70,9 @@ struct system_patch { uint8_t patch_data[]; // The data for the patch. This is a sort of interpreted code...see below. } __attribute__((packed)); +struct patch_opcode { +} __attribute__((packed)); + /* [PATCH] version=1 diff --git a/source/patcher.c b/source/patcher.c index 422fd36..344f859 100644 --- a/source/patcher.c +++ b/source/patcher.c @@ -1,16 +1,102 @@ #include #include "std/unused.h" #include "std/memory.h" +#include "firm/firm.h" #include "config.h" +#include "common.h" -#define SIGNATURE_CHECK {0x00, 0x20} -#define SIGNATURE_CHECK_FIX {0x70, 0x60, 0x70, 0x47} +uint32_t wait_key(); + +// A portion of this file is inherited from Luma3DS. +/* +u16 *getFirmWrite(u8 *pos, u32 size) { + //Look for FIRM writing code + u8 *const off = memsearch(pos, "exe:", size, 4); + const u8 pattern[] = {0x00, 0x28, 0x01, 0xDA}; + + return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4); +} + +u16 *getFirmWriteSafe(u8 *pos, u32 size) { + //Look for FIRM writing code + const u8 pattern[] = {0x04, 0x1E, 0x1D, 0xDB}; + + return (u16 *)memsearch(pos, pattern, size, 4); +} + +u32 getLoader(u8 *pos, u32 *loaderSize) { + u8 *off = pos; + u32 size; + + while(1) + { + size = *(u32 *)(off + 0x104) * 0x200; + if(*(u32 *)(off + 0x200) == 0x64616F6C) break; + off += size; + } + + *loaderSize = size; + + return (u32)(off - pos); +} + + +// patch_location = (void *)((uintptr_t)firm + section->offset + (version->offset - section->address)); + +u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) +{ + u8 *off = memsearch(pos, "ess9", size, 4); + + *process9Size = *(u32 *)(off - 0x60) * 0x200; + *process9MemAddr = *(u32 *)(off + 0xC); + + //Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size) + return off - 0x204 + (*(u32 *)(off - 0x64) * 0x200) + 0x200; +} +*/ + +int patch_signatures() { + //Look for signature checks + + uint8_t pat1[] = {0xC0, 0x1C, 0x76, 0xE7}; + uint8_t pat2[] = {0xB5, 0x22, 0x4D, 0x0C}; + + uint8_t *firm_mem = (uint8_t*)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset; + uint32_t size = firm_p9_exefs->fileHeaders[0].size; + + uint8_t *off = memfind(firm_mem, size, pat1, 4); + uint8_t *off2 = memfind(firm_mem, size, pat2, 4) - 1; + + if (off == NULL) { + fprintf(stderr, "Signature patch failed on P0.\n"); + return 1; // Failed to find sigpatch. Ugh. + } + + if (off2 == NULL) { + fprintf(stderr, "Signature patch failed on P1.\n"); + return 2; // Failed to find sigpatch. Ugh. + } + + fprintf(stderr, "Signatures[0]: 0x%x\n", (uint32_t)off); + fprintf(stderr, "Signatures[1]: 0x%x\n", (uint32_t)off2); + + uint8_t sigpatch[] = {0x00, 0x20, 0x70, 0x47}; + + memcpy(off, sigpatch, 2); + memcpy(off2, sigpatch, 4); + fprintf(stderr, "Signature patch succeded.\n"); + + return 0; +} int patch_firm_all() { // Use builtin signature patcher? + + fprintf(stderr, "Signature patch: %s\n", ((config.options[OPTION_SIGPATCH]) ? "yes" : "no" )); if (config.options[OPTION_SIGPATCH]) { - // Yes. - // memfind( + if(patch_signatures()) { + abort("Fatal. Sigpatch has failed."); + } } // Replace loader? @@ -23,8 +109,11 @@ int patch_firm_all() { // Use ARM9 hook thread? if (config.options[OPTION_ARM9THREAD]) { // Yes. + // FIXME - NYI } + wait_key(); + return 0; } diff --git a/source/std/draw.c b/source/std/draw.c index bb10b62..a87b767 100644 --- a/source/std/draw.c +++ b/source/std/draw.c @@ -263,6 +263,17 @@ void put_uint64(void* channel, uint64_t n, int length) { puts(channel, out); } +void put_hexdump(void* channel, unsigned int num) { + uint8_t* num_8 = (uint8_t*)# + for(int i=3; i>=0; i--) { + uint8_t high = (num_8[i] >> 4) & 0xf; + uint8_t low = num_8[i] & 0xf; + + putc(channel, ("0123456789abcdef")[high]); + putc(channel, ("0123456789abcdef")[low]); + } +} + void put_uint(void* channel, unsigned int n, int length) { put_uint64(channel, n, length); } @@ -386,6 +397,9 @@ check_format: case 'l': ++type_size; goto check_format; + case 'x': + put_hexdump(channel, va_arg( ap, unsigned int )); + break; default: if (*ref >= '0' && *ref <= '9') { length = *ref - '0';