Created
April 12, 2015 17:22
-
-
Save patois/2dc6bf727a07b8bcdcd7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "firm.h" | |
int get_section_by_address (void *address) { | |
int i; | |
struct firm_section_header volatile *sh; | |
for (i=0; i < FIRM_MAX_SECTION_COUNT; i++) { | |
sh = &firm->section_headers[i]; | |
if ((sh->address <= address) && (address < (sh->address + sh->size))) { | |
return i; | |
} | |
} | |
return -1; | |
} | |
/* this could/should be added a few more checks */ | |
int is_valid_firm (void) { | |
return (firm->magic == FIRM_MAGIC); | |
} | |
void dump_section_header (int index) { | |
struct firm_section_header volatile *sh; | |
sh = &firm->section_headers[index]; | |
Debug("Section %02d/%02d (ARM%s):", index, FIRM_MAX_SECTION_COUNT, sh->type ? "11" : "9"); | |
Debug("%08X - %08X", sh->address, sh->address + sh->size); | |
Debug(""); | |
return; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "common.h" | |
int get_section_by_address (void *address); | |
int is_valid_firm (void); | |
void dump_section_header (int index); | |
#define PA_FIRM_IMAGE 0x24000000 | |
#define FIRM_MAGIC 0x4D524946 | |
#define FIRM_MAX_SECTION_COUNT 0x4 | |
typedef struct firm_section_header { | |
u32 offset; | |
void *address; | |
u32 size; | |
u32 type; | |
u8 hash[0x20]; | |
} _firm_section_header; | |
typedef struct firm_header { | |
u32 magic; | |
u32 reserved1; | |
void *arm11_ep; | |
void *arm9_ep; | |
u8 reserved2[0x30]; | |
struct firm_section_header section_headers[4]; | |
u8 rsa_sig[0x100]; | |
} _firm_header; | |
static struct firm_header volatile *const firm = (struct firm_header *)PA_FIRM_IMAGE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "draw.h" | |
#include "hid.h" | |
u32 InputWait() { | |
u32 pad_state_old = HID_STATE; | |
while (true) { | |
u32 pad_state = HID_STATE; | |
if (pad_state ^ pad_state_old) | |
return ~pad_state; | |
} | |
} | |
u32 wait_key (char *msg) { | |
if (msg) { | |
Debug(""); | |
Debug("%s", msg); | |
} | |
return InputWait(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "common.h" | |
u32 InputWait(); | |
u32 wait_key (char *msg); | |
#define HID_STATE (*(volatile u32*)0x10146000) | |
#define BUTTON_A (1 << 0) | |
#define BUTTON_B (1 << 1) | |
#define BUTTON_SELECT (1 << 2) | |
#define BUTTON_START (1 << 3) | |
#define BUTTON_RIGHT (1 << 4) | |
#define BUTTON_LEFT (1 << 5) | |
#define BUTTON_UP (1 << 6) | |
#define BUTTON_DOWN (1 << 7) | |
#define BUTTON_R1 (1 << 8) | |
#define BUTTON_L1 (1 << 9) | |
#define BUTTON_X (1 << 10) | |
#define BUTTON_Y (1 << 11) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include "draw.h" | |
#include "hid.h" | |
#include "firm.h" | |
void ClearTop (void) { | |
ClearScreen(TOP_SCREEN0, RGB(255, 255, 255)); | |
ClearScreen(TOP_SCREEN1, RGB(255, 255, 255)); | |
current_y = 0; | |
return; | |
} | |
int patch (void *address, u8 *sig, u32 size) { | |
int result = 0; | |
if (address && sig && size) { | |
memcpy(address, sig, size); | |
result = 1; | |
} | |
return result; | |
} | |
void *find_signature (void *start_addr, void *end_addr, u8 *sig, u32 size) { | |
u8 *p = start_addr; | |
void *max_addr = 0; | |
if (sig && | |
(u32)start_addr < (u32)end_addr && | |
(u32)end_addr > size) { | |
max_addr = end_addr - size; | |
while (p < (u8 *)max_addr) { | |
if ((*p == *sig) && (memcmp(p, sig, size) == 0)) { | |
return p; | |
} | |
p++; | |
} | |
} | |
return 0; | |
} | |
void fatal(void) { | |
Debug("Signature not found! Please Turn off your 3DS"); | |
while (1) | |
; | |
} | |
int main (void) { | |
ClearTop(); | |
Debug(""); | |
int sect; | |
u8 *sig_addr = 0; | |
u32 key; | |
u8 sig[32] = { | |
0x20,0xA0,0xDA,0xE5, 0x07,0xE0,0x09,0xE2, | |
0x1B,0x0E,0x1A,0xE1, 0x31,0xA0,0xDD,0xE5, | |
0xEA,0xFF,0xFF,0x0A, 0x00,0x00,0x5A,0xE3, | |
0x0D,0x00,0x00,0x0A, 0x00,0xE0,0xA0,0xE3}; | |
u8 sig_patch[32] = { | |
0x20,0xA0,0xDA,0xE5, 0x07,0xE0,0x09,0xE2, | |
0x1B,0x0E,0x1A,0xE1, 0x31,0xA0,0xDD,0xE5, | |
0x00,0xF0,0x20,0xE3, 0x00,0x00,0x5A,0xE3, | |
0x00,0xF0,0x20,0xE3, 0x00,0xE0,0xA0,0xE3}; | |
Debug("Simple memory patcher example"); | |
Debug("============================="); | |
Debug(""); | |
Debug("Finds a byte signature in memory and"); | |
Debug("replaces it with a new signature"); | |
Debug(""); | |
if (is_valid_firm()) { | |
sect = get_section_by_address(firm->arm11_ep); | |
if (sect != -1) { | |
Debug("ARM11 entry point found in:"); | |
dump_section_header(sect); | |
if (wait_key("Press START to find signature in memory") & BUTTON_START) { | |
sig_addr = firm->section_headers[sect].address; | |
while ((sig_addr = find_signature(sig_addr, | |
firm->section_headers[sect].address + | |
firm->section_headers[sect].size, | |
(u8 *)&sig, | |
sizeof(sig))) != 0) { | |
ClearTop(); | |
Debug("Signature found at %08X", sig_addr); | |
Debug("X : Confirm patch (at your own risk)"); | |
Debug("B : Skip/Cancel"); | |
while (1) { | |
key = wait_key(""); | |
if (key & BUTTON_X) { | |
patch(sig_addr, (u8 *)&sig_patch, sizeof(sig_patch)); | |
Debug("Signature patched"); | |
break; | |
} else if (key & BUTTON_B) { | |
break; | |
} | |
} | |
sig_addr++; | |
} | |
} else { | |
Debug("Aborted"); | |
} | |
} else { /* ARM11 entry point outside of section headers */ | |
fatal(); | |
} | |
} else { /* invalid FIRM header */ | |
fatal(); | |
} | |
wait_key("Press any key to launch firm."); | |
// return control to FIRM ARM9 code (performs firmlaunch) | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment