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

View File

@ -64,9 +64,9 @@ $(dir_out)/3ds/$(name):
@mv $(dir_out)/$(name).3dsx $@ @mv $(dir_out)/$(name).3dsx $@
@mv $(dir_out)/$(name).smdh $@ @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" @mkdir -p "$(dir_out)/rei"
@cp -av $(dir_data)/*bin $@ @cp -av $(dir_data)/* $@
$(dir_out)/rei/thread/arm9.bin: $(dir_thread) $(dir_out)/rei/thread/arm9.bin: $(dir_thread)
@$(MAKE) $(FLAGS) -C $(dir_thread) @$(MAKE) $(FLAGS) -C $(dir_thread)

1
data/RAM.txt Normal file
View File

@ -0,0 +1 @@
536870912

View File

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

View File

@ -5,12 +5,13 @@
*/ */
#include "emunand.h" #include "emunand.h"
#include "memory.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
#include "fatfs/sdmmc/sdmmc.h" #include "fatfs/sdmmc/sdmmc.h"
static u8 *temp = (u8*)0x24300000; static u8 *temp = (u8*)0x24300000;
void getEmunand(u32 *off, u32 *head){ void getEmunandSect(u32 *off, u32 *head){
u32 nandSize = getMMCDevice(0)->total_size; u32 nandSize = getMMCDevice(0)->total_size;
if (sdmmc_sdcard_readsectors(nandSize, 1, temp) == 0) { if (sdmmc_sdcard_readsectors(nandSize, 1, temp) == 0) {
if (*(u32*)(temp + 0x100) == NCSD_MAGIC) { if (*(u32*)(temp + 0x100) == NCSD_MAGIC) {
@ -19,3 +20,29 @@ void getEmunand(u32 *off, u32 *head){
} }
} }
} }
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.
}

View File

@ -11,6 +11,8 @@
#define NCSD_MAGIC (0x4453434E) #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 #endif

View File

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

View File

@ -70,3 +70,17 @@ int fileWrite(const u8 *buffer, const char *path, u32 size){
} }
return fr; 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;
}

View File

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

View File

@ -19,14 +19,13 @@
**************************************************/ **************************************************/
/* /*
* Emunand * MPU
*/ */
u8 mpu[0x2C] = { //MPU shit u8 mpu[0x2C] = { //MPU shit
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00, 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, 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 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 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 * Arm9 thread
*/ */
u8 th1[4] = {0x2C, 0xF0, 0x9F, 0xE5}; //ldr pc, =0x0801A7E0 u8 th1[4] = {0x2C, 0xF0, 0x9F, 0xE5}; //ldr pc, =0x08006070
u8 th2[4] = {0xE0, 0xA7, 0x01, 0x08}; //0x0801A7E0 u8 th2[4] = {0x70, 0x60, 0x00, 0x08}; //0x08006070
@ -54,7 +53,7 @@ u32 emuCode(void){
//Where thread code is stored in firm //Where thread code is stored in firm
u32 threadCode(void){ u32 threadCode(void){
return KERNEL9 + (0x0801A7E0 - K9_ADDR); return KERNEL9 + (0x08006070 - K9_ADDR);
} }
//Area of MPU setting code //Area of MPU setting code
@ -69,13 +68,6 @@ u32 threadHook(u8 val){
PROC9 + (0x080851CC - P9_ADDR); 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 //Offsets to redirect to thread code
u32 sigPatch(u8 val){ u32 sigPatch(u8 val){
return val == 1 ? return val == 1 ?

View File

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

View File

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

View File

@ -31,6 +31,24 @@ int memcmp(void* buf1, void* buf2, int size){
return equal; 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){ unsigned isPressed(unsigned bitfield){
return ((~*(unsigned *)0x10146000) & 0xFFF) == (bitfield & 0xFFF) ? 1 : 0; return ((~*(unsigned *)0x10146000) & 0xFFF) == (bitfield & 0xFFF) ? 1 : 0;
} }

View File

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

View File

@ -10,78 +10,48 @@
#include "lib.h" #include "lib.h"
#include "FS.h" #include "FS.h"
//ram stuff
#define VRAM (unsigned char*)0x18000000 #define VRAM (unsigned char*)0x18000000
#define FCRAM (unsigned char*)0x20000000 #define FCRAM (unsigned char*)0x20000000
#define FCRAM_EXT (unsigned char*)0x28000000 #define FCRAM_EXT (unsigned char*)0x28000000
#define ARM9_MEM (unsigned char*)0x8000000
#define AXIWRAM (unsigned char*)0x1FF80000 //file stuff
#define TOP_FRAME 0 #define READ 0
#define BOT_FRAME 1 #define WRITE 1
unsigned char handle[32]; 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 memdump(void* filename, void* buf, unsigned int size){ void fileReadWrite(void *buf, void *path, int size, char rw){
unsigned int br = 0; unsigned int br = 0;
memset(&handle, 0, 32); memset(&handle, 0, 32);
fopen9(&handle, filename, 6); fopen9(&handle, path, 6);
fwrite9(&handle, &br, buf, size); if(rw == 0) fread9(&handle, &br, buf, size);
else fwrite9(&handle, &br, buf, size);
fclose9(&handle); fclose9(&handle);
}
void memdump(void* filename, void* buf, unsigned int size){
fileReadWrite(buf, filename, size, WRITE);
memset(VRAM+0x1E6000, 0xFF, 0x46500); 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){ void patches(void){
//Change version string //Change version string
for(int i = 0; i < 0x600000; i+=4){ for(int i = 0; i < 0x600000; i+=4){
if(strcomp((void*)0x27B00000 - i, (void*)L"Ver.", 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){ void thread(void){
while(1){ while(1){
if(isPressed(BUTTON_SELECT | BUTTON_X)){
screenShot(TOP_FRAME);
screenShot(BOT_FRAME);
}
if(isPressed(BUTTON_START | BUTTON_X)){ if(isPressed(BUTTON_START | BUTTON_X)){
memdump(L"sdmc:/FCRAM.bin", (void*)0x27500000, 0x600000); 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(); patches();
} }