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).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
View File

@ -0,0 +1 @@
536870912

View File

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

View File

@ -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) {
@ -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)
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

View File

@ -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));

View File

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

View File

@ -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 ?

View File

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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
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();
}