Emunand self patching; found solution for some hard coded stuff/FS more flexible; got rid of screenShot; implemented PoC RAM dumper using txt file; changed location of arm9 thread; fixed ver string; tons of organization and cleaning up for easier to read and modify code.

This commit is contained in:
Reisyukaku 2016-01-23 03:53:45 -05:00
parent 2465cb0fa9
commit 62d8d582c1
14 changed files with 127 additions and 91 deletions

@ -64,9 +64,9 @@ $(dir_out)/3ds/$(name):
@mv $(dir_out)/$(name).3dsx $@
@mv $(dir_out)/$(name).smdh $@
$(dir_out)/rei/: $(dir_data)/firmware.bin $(dir_data)/splash.bin
$(dir_out)/rei/: $(dir_data)/firmware.bin $(dir_data)/splash.bin $(dir_data)/RAM.txt
@mkdir -p "$(dir_out)/rei"
@cp -av $(dir_data)/*bin $@
@cp -av $(dir_data)/* $@
$(dir_out)/rei/thread/arm9.bin: $(dir_thread)
@$(MAKE) $(FLAGS) -C $(dir_thread)

1
data/RAM.txt Normal file

@ -0,0 +1 @@
536870912

@ -1,6 +1,6 @@
.nds
sdmmc equ 0x080F0AB0
sdmmc equ 0x434D4453 ;dummy
.create "emunand.bin", 0x0801A5C0
.org 0x0801A5C0

@ -5,12 +5,13 @@
*/
#include "emunand.h"
#include "memory.h"
#include "fatfs/ff.h"
#include "fatfs/sdmmc/sdmmc.h"
static u8 *temp = (u8*)0x24300000;
void getEmunand(u32 *off, u32 *head){
void getEmunandSect(u32 *off, u32 *head){
u32 nandSize = getMMCDevice(0)->total_size;
if (sdmmc_sdcard_readsectors(nandSize, 1, temp) == 0) {
if (*(u32*)(temp + 0x100) == NCSD_MAGIC) {
@ -18,4 +19,30 @@ void getEmunand(u32 *off, u32 *head){
*head = nandSize;
}
}
}
void getSDMMC(void *offset, u32 *off, u32 size){
//Look for struct code
unsigned char pattern[] = {0x01, 0x21, 0x20, 0x18, 0x20, 0x30};
*off = memsearch(offset, pattern, size, 6);
//Get DCD values
unsigned char buf[4];
int p;
u32 addr = 0;
u32 additive = 0;
memcpy((void*)buf, (void*)(*off+0x0A), 4);
for (p = 0; p < 4; p++) addr |= ((u32) buf[p]) << (8 * p);
memcpy((void*)buf, (void*)(*off+0x0E), 4);
for (p = 0; p < 4; p++) additive |= ((u32) buf[p]) << (8 * p);
//Return result
*off = addr + additive;
}
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
//Look for read/write code
unsigned char pattern[] = {0x04, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x1E, 0x00, 0xC8, 0x05};
*writeOff = memsearch(pos, pattern, size, 10);
*readOff = *writeOff - 0x40; //TODO: Maybe make memsearch work properly for this.
}

@ -11,6 +11,8 @@
#define NCSD_MAGIC (0x4453434E)
void getEmunand(u32 *off, u32 *head);
void getEmunandSect(u32 *off, u32 *head);
void getSDMMC(void *offset, u32 *off, u32 size);
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
#endif

@ -13,13 +13,19 @@
const firmHeader *firmLocation = (firmHeader *)0x24000000;
firmSectionHeader *section;
u32 emuOffset = 0;
u32 emuHeader = 0;
u32 emuOffset = 0,
emuHeader = 0,
emuRead = 0,
emuWrite = 0,
sdmmcOffset = 0,
firmSize = 0;
//Load firm into FCRAM
void loadFirm(void){
//Read FIRM from SD card and write to FCRAM
fileRead((u8*)firmLocation, "/rei/firmware.bin", 0);
const char firmPath[] = "/rei/firmware.bin";
firmSize = fileSize(firmPath);
fileRead((u8*)firmLocation, firmPath, firmSize);
section = firmLocation->section;
arm9loader((u8*)firmLocation + section[2].offset);
}
@ -29,31 +35,35 @@ void loadEmu(void){
//Read emunand code from SD
u32 code = emuCode();
fileRead(code, "/rei/emunand/emunand.bin", 0);
u32 *pos_offset = memsearch(code, "NAND", 0x218, 4);
u32 *pos_header = memsearch(code, "NCSD", 0x218, 4);
getEmunand(&emuOffset, &emuHeader);
if (pos_offset && pos_header) {
*pos_offset = emuOffset;
*pos_header = emuHeader;
}
const char path[] = "/rei/emunand/emunand.bin";
u32 size = fileSize(path);
fileRead(code, path, size);
//Find and patch emunand related offsets
u32 *pos_sdmmc = memsearch(code, "SDMC", size, 4);
u32 *pos_offset = memsearch(code, "NAND", size, 4);
u32 *pos_header = memsearch(code, "NCSD", size, 4);
getSDMMC(firmLocation, &sdmmcOffset, firmSize);
getEmunandSect(&emuOffset, &emuHeader);
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
*pos_sdmmc = sdmmcOffset;
*pos_offset = emuOffset;
*pos_header = emuHeader;
//Add emunand hooks
memcpy((u8*)emuHook(1), nandRedir, sizeof(nandRedir));
memcpy((u8*)emuHook(2), nandRedir, sizeof(nandRedir));
memcpy((u8*)emuRead, nandRedir, sizeof(nandRedir));
memcpy((u8*)emuWrite, nandRedir, sizeof(nandRedir));
memcpy((u8*)mpuCode(), mpu, sizeof(mpu));
}
//Patches
void patchFirm(){
//Part1: Set MPU for payload area
memcpy((u8*)mpuCode(), mpu, sizeof(mpu));
//Part2: Disable signature checks
//Disable signature checks
memcpy((u8*)sigPatch(1), sigPat1, sizeof(sigPat1));
memcpy((u8*)sigPatch(2), sigPat2, sizeof(sigPat2));
//Part3: Create arm9 thread
//Create arm9 thread
fileRead((u8*)threadCode(), "/rei/thread/arm9.bin", 0);
memcpy((u8*)threadHook(1), th1, sizeof(th1));
memcpy((u8*)threadHook(2), th2, sizeof(th2));

@ -69,4 +69,18 @@ int fileWrite(const u8 *buffer, const char *path, u32 size){
if (fr == FR_OK && br == size) return 0;
}
return fr;
}
int fileSize(const char* path){
FRESULT fr;
FIL fp;
int size = 0;
fr = f_open(&fp, path, FA_READ);
if (fr != FR_OK)goto error;
size = f_size(&fp);
error:
f_close(&fp);
return size;
}

@ -12,5 +12,6 @@ int unmountSD();
int fileReadOffset(u8 *dest, const char *path, u32 size, u32 offset);
int fileRead(u8 *dest, const char *path, u32 size);
int fileWrite(const u8 *buffer, const char *path, u32 size);
int fileSize(const char* path);
#endif

@ -19,14 +19,13 @@
**************************************************/
/*
* Emunand
* MPU
*/
u8 mpu[0x2C] = { //MPU shit
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00,
0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08,
0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x08
};
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0xC0, 0xA5, 0x01, 0x08}; //Branch to emunand function
/*
@ -38,8 +37,8 @@ u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
/*
* Arm9 thread
*/
u8 th1[4] = {0x2C, 0xF0, 0x9F, 0xE5}; //ldr pc, =0x0801A7E0
u8 th2[4] = {0xE0, 0xA7, 0x01, 0x08}; //0x0801A7E0
u8 th1[4] = {0x2C, 0xF0, 0x9F, 0xE5}; //ldr pc, =0x08006070
u8 th2[4] = {0x70, 0x60, 0x00, 0x08}; //0x08006070
@ -54,7 +53,7 @@ u32 emuCode(void){
//Where thread code is stored in firm
u32 threadCode(void){
return KERNEL9 + (0x0801A7E0 - K9_ADDR);
return KERNEL9 + (0x08006070 - K9_ADDR);
}
//Area of MPU setting code
@ -69,13 +68,6 @@ u32 threadHook(u8 val){
PROC9 + (0x080851CC - P9_ADDR);
}
//Offsets to redirect to Emunand code
u32 emuHook(u8 val){ //latest only
return val == 1 ?
PROC9 + (0x08077B40 - P9_ADDR):
PROC9 + (0x08077B80 - P9_ADDR);
}
//Offsets to redirect to thread code
u32 sigPatch(u8 val){
return val == 1 ?

@ -6,7 +6,7 @@ ENTRY(_start)
SECTIONS
{
. = 0x0801A7E0;
. = 0x08006070;
start_addr = .;
.text.start : { *(.text.start) }
.text : { *(.text) *(.text*) }

@ -13,8 +13,8 @@ _start:
ldr r1, =thread @ thread_addr
mov r2, #0x0 @ arg
ldr r3, =0x08000c00 @ StackTop
ldr r4, =0x1
ldr r4, =0xFFFFFFFE
svc 0x8
pop {r0-r12 , lr}
ldr r0, =0x80E3408
ldr r0, =0x080E3408
ldr pc, =0x0808519C

@ -31,6 +31,24 @@ int memcmp(void* buf1, void* buf2, int size){
return equal;
}
int atoi(const char* nptr){
int result = 0,
position = 1;
const char* p = nptr;
while(*p) ++p;
for(--p; p >= nptr; p--){
if(*p < 0x30 || *p > 0x39) break;
else{
result += (position) * (*p - 0x30);
position *= 10;
}
}
result = ((nptr[0] == '-')? -result : result);
return result;
}
unsigned isPressed(unsigned bitfield){
return ((~*(unsigned *)0x10146000) & 0xFFF) == (bitfield & 0xFFF) ? 1 : 0;
}

@ -20,6 +20,7 @@ void* memset(void * ptr, int value, unsigned int num);
int strcomp(char* s1, char*s2, unsigned int size);
void strcopy(char* dest, char* source, unsigned int size);
int memcmp(void* buf1, void* buf2, int size);
int atoi(const char* nptr);
unsigned isPressed(unsigned bitfield);
#endif

@ -10,78 +10,48 @@
#include "lib.h"
#include "FS.h"
//ram stuff
#define VRAM (unsigned char*)0x18000000
#define FCRAM (unsigned char*)0x20000000
#define FCRAM_EXT (unsigned char*)0x28000000
#define ARM9_MEM (unsigned char*)0x8000000
#define AXIWRAM (unsigned char*)0x1FF80000
#define TOP_FRAME 0
#define BOT_FRAME 1
//file stuff
#define READ 0
#define WRITE 1
unsigned char handle[32];
unsigned char bmpHead[] = {
0x42, 0x4D, 0x36, 0x65, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF0, 0x00,
0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x65, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void fileReadWrite(void *buf, void *path, int size, char rw){
unsigned int br = 0;
memset(&handle, 0, 32);
fopen9(&handle, path, 6);
if(rw == 0) fread9(&handle, &br, buf, size);
else fwrite9(&handle, &br, buf, size);
fclose9(&handle);
}
void memdump(void* filename, void* buf, unsigned int size){
unsigned int br = 0;
memset(&handle, 0, 32);
fopen9(&handle, filename, 6);
fwrite9(&handle, &br, buf, size);
fclose9(&handle);
fileReadWrite(buf, filename, size, WRITE);
memset(VRAM+0x1E6000, 0xFF, 0x46500);
}
void transpose (void * dst, const void * src, unsigned dim1, unsigned dim2, unsigned item_length) {
char * ptr_write;
const char * ptr_read;
unsigned x, y, z;
for (x = 0; x < dim1; x ++) for (y = 0; y < dim2; y ++) {
ptr_write = ((char *) dst) + item_length * (y * dim1 + x);
ptr_read = ((const char *) src) + item_length * (x * dim2 + y);
for (z = 0; z < item_length; z ++) *(ptr_write ++) = *(ptr_read ++);
}
}
void screenShot(int frame){
unsigned int br;
short width = frame == 0 ? 400 : 320;
short height = 240;
int frameOff = frame == 0 ? 0x1E6000 : 0x48F000; //<- Defaults
int length = frame == 0 ? 0x46500 : 0x38400;
memset(&handle, 0, 32);
fopen9(&handle, frame == 0 ? L"sdmc:/screen_top.bmp" : L"sdmc:/screen_bot.bmp", 6);
transpose(FCRAM+0xF80000, VRAM+frameOff, width, height, 3);
bmpHead[18] = frame == 0 ? 0x90 : 0x40;
fwrite9(&handle, &br, bmpHead, 0x36);
fwrite9(&handle, &br, FCRAM+0xF80000, length);
fclose9(&handle);
memset(VRAM+frameOff, 0xFF, 0x46500);
}
void patches(void){
//Change version string
for(int i = 0; i < 0x600000; i+=4){
if(strcomp((void*)0x27B00000 - i, (void*)L"Ver.", 4)){
if(strcomp((void*)0x27B00000 - i + 0x28, (void*)"T_ver_00", 4)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
if(strcomp((void*)0x27B00000 - i + 0x0A, (void*)L"%d.%d.%d-%d", 11)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
}
}
}
void thread(void){
while(1){
if(isPressed(BUTTON_SELECT | BUTTON_X)){
screenShot(TOP_FRAME);
screenShot(BOT_FRAME);
}
if(isPressed(BUTTON_START | BUTTON_X)){
memdump(L"sdmc:/FCRAM.bin", (void*)0x27500000, 0x600000);
if(isPressed(BUTTON_START | BUTTON_X)){
unsigned char buf[0x10] = {0};
int loc = 0;
fileReadWrite(buf, L"sdmc:/rei/RAM.txt", 0x20, READ);
loc = atoi(buf);
memdump(L"sdmc:/RAMdmp.bin", (void*)loc, 0x500000);
}
patches();
}