Skip to content

Commit

Permalink
Emunand self patching; found solution for some hard coded stuff/FS mo…
Browse files Browse the repository at this point in the history
…re 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.
  • Loading branch information
Reisyukaku committed Jan 23, 2016
1 parent 2465cb0 commit 62d8d58
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 90 deletions.
4 changes: 2 additions & 2 deletions Makefile
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions data/RAM.txt
@@ -0,0 +1 @@
536870912
2 changes: 1 addition & 1 deletion emunand/emuCode.s
@@ -1,6 +1,6 @@
.nds

sdmmc equ 0x080F0AB0
sdmmc equ 0x434D4453 ;dummy

.create "emunand.bin", 0x0801A5C0
.org 0x0801A5C0
Expand Down
29 changes: 28 additions & 1 deletion source/emunand.c
Expand Up @@ -5,17 +5,44 @@
*/

#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) {
*off = 0;
*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.
}
4 changes: 3 additions & 1 deletion source/emunand.h
Expand Up @@ -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
48 changes: 29 additions & 19 deletions source/firm.c
Expand Up @@ -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);
}
Expand All @@ -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));
Expand Down
14 changes: 14 additions & 0 deletions source/fs.c
Expand Up @@ -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;
}
1 change: 1 addition & 0 deletions source/fs.h
Expand Up @@ -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
16 changes: 4 additions & 12 deletions source/patches.c
Expand Up @@ -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

/*
Expand All @@ -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



Expand All @@ -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
Expand All @@ -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 ?
Expand Down
2 changes: 1 addition & 1 deletion thread/3ds.ld
Expand Up @@ -6,7 +6,7 @@ ENTRY(_start)

SECTIONS
{
. = 0x0801A7E0;
. = 0x08006070;
start_addr = .;
.text.start : { *(.text.start) }
.text : { *(.text) *(.text*) }
Expand Down
4 changes: 2 additions & 2 deletions thread/source/_start.s
Expand Up @@ -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
18 changes: 18 additions & 0 deletions thread/source/lib.c
Expand Up @@ -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;
}
1 change: 1 addition & 0 deletions thread/source/lib.h
Expand Up @@ -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
72 changes: 21 additions & 51 deletions thread/source/thread.c
Expand Up @@ -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 memdump(void* filename, void* buf, unsigned int size){
unsigned int br = 0;
void fileReadWrite(void *buf, void *path, int size, char rw){
unsigned int br = 0;
memset(&handle, 0, 32);
fopen9(&handle, filename, 6);
fwrite9(&handle, &br, buf, size);
fclose9(&handle);
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 ++);
}
fopen9(&handle, path, 6);
if(rw == 0) fread9(&handle, &br, buf, size);
else fwrite9(&handle, &br, buf, size);
fclose9(&handle);
}

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 memdump(void* filename, void* buf, unsigned int size){
fileReadWrite(buf, filename, size, WRITE);
memset(VRAM+0x1E6000, 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();
}
Expand Down

0 comments on commit 62d8d58

Please sign in to comment.