Encrypted illegal stuff ;^) ..and more work on smart patching system
This commit is contained in:
parent
62d8d582c1
commit
7f2597fe2f
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,9 +1,6 @@
|
|||||||
build.bat
|
|
||||||
data/firmware.bin
|
|
||||||
out
|
out
|
||||||
CakeHax
|
CakeHax
|
||||||
CakeBrah
|
CakeBrah
|
||||||
rnInstaller
|
|
||||||
build
|
build
|
||||||
*.bin
|
*.bin
|
||||||
*.3dsx
|
*.3dsx
|
||||||
@ -11,3 +8,4 @@ build
|
|||||||
*.o
|
*.o
|
||||||
*.d
|
*.d
|
||||||
*.elf
|
*.elf
|
||||||
|
*.bat
|
14
README.md
14
README.md
@ -1,16 +1,14 @@
|
|||||||
# ReiNand
|
# ReiNand
|
||||||
The original open source N3DS CFW!
|
*The original open source N3DS CFW!*
|
||||||
|
|
||||||
|
|
||||||
**Compiling:**
|
**Compiling:**
|
||||||
|
|
||||||
First you'll need the firmware file that I didnt include because reasons. Get that [HERE](https://www.dropbox.com/s/782eyz22lkmh434/firmware.bin?dl=0)
|
You'll need armips added to your Path. [HERE](https://www.dropbox.com/s/ceuv2qeqp38lpah/armips.exe?dl=0) is a pre-compiled version.
|
||||||
|
|
||||||
Secondly, You'll need armips added to your Path. [HERE](https://www.dropbox.com/s/ceuv2qeqp38lpah/armips.exe?dl=0) is a pre-compiled version.
|
|
||||||
|
|
||||||
Lastly, just run Make and everything should work!
|
Lastly, just run Make and everything should work!
|
||||||
|
|
||||||
Pre-compiled version can still be found on my [pastebin](http://pastebin.com/c5AW3TJp)
|
Copy everything in 'out' folder to SD root and run!
|
||||||
|
|
||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
@ -19,11 +17,9 @@ Pre-compiled version can still be found on my [pastebin](http://pastebin.com/c5A
|
|||||||
|
|
||||||
* Sig checks disabled
|
* Sig checks disabled
|
||||||
|
|
||||||
* screenshots (set for pokemon game offsets currently) [Select Button + X]
|
* RAM dump (edit RAM.txt with a base 10 number for offset) [Start Button + X]
|
||||||
|
|
||||||
* RAM dump (currently set for FCRAM) [Start Button + X]
|
* Emunand (with 'Rei' version string)
|
||||||
|
|
||||||
* emunand (with 'Rei' version string)
|
|
||||||
|
|
||||||
|
|
||||||
**Credits:**
|
**Credits:**
|
||||||
|
BIN
data/firmware.bin
Normal file
BIN
data/firmware.bin
Normal file
Binary file not shown.
@ -353,21 +353,32 @@ int rsa_verify(const void* data, u32 size, const void* sig, u32 mode)
|
|||||||
return memcmp(dataHash, decSig + (sigSize - SHA_256_HASH_SIZE), SHA_256_HASH_SIZE) == 0;
|
return memcmp(dataHash, decSig + (sigSize - SHA_256_HASH_SIZE), SHA_256_HASH_SIZE) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void xor(u8 *dest, u8 *data1, u8 *data2, u32 size){
|
||||||
|
int i; for(i = 0; i < size; i++) *(dest+i) = *(data1+i) ^ *(data2+i);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
* Nand/FIRM Crypto stuff
|
* Nand/FIRM Crypto stuff
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
|
const u8 memeKey[0x10] = {
|
||||||
|
0x52, 0x65, 0x69, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x67, 0x69, 0x72, 0x6C
|
||||||
|
};
|
||||||
|
|
||||||
//Emulates the Arm9loader process
|
//Emulates the Arm9loader process
|
||||||
void arm9loader(void *armHdr){
|
void arm9loader(void *armHdr){
|
||||||
//Set Nand key#2 here (decrypted from 0x12C10)
|
//Nand key#2 (0x12C10)
|
||||||
u8 key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
|
u8 key2[0x10] = {
|
||||||
|
0x10, 0x5A, 0xE8, 0x5A, 0x4A, 0x21, 0x78, 0x53, 0x0B, 0x06, 0xFA, 0x1A, 0x5E, 0x2A, 0x5C, 0xBC
|
||||||
|
};
|
||||||
|
|
||||||
|
//Firm keys
|
||||||
u8 keyX[0x10];
|
u8 keyX[0x10];
|
||||||
u8 keyY[0x10];
|
u8 keyY[0x10];
|
||||||
u8 CTR[0x10];
|
u8 CTR[0x10];
|
||||||
u32 slot = 0x16;
|
u32 slot = 0x16;
|
||||||
|
|
||||||
//Setupkeys needed for arm9bin decryption
|
//Setup keys needed for arm9bin decryption
|
||||||
|
xor(key2, key2, memeKey, 0x10);
|
||||||
memcpy((u8*)keyY, (void *)((uintptr_t)armHdr+0x10), 0x10);
|
memcpy((u8*)keyY, (void *)((uintptr_t)armHdr+0x10), 0x10);
|
||||||
memcpy((u8*)CTR, (void *)((uintptr_t)armHdr+0x20), 0x10);
|
memcpy((u8*)CTR, (void *)((uintptr_t)armHdr+0x20), 0x10);
|
||||||
u32 size = atoi((void *)((uintptr_t)armHdr+0x30));
|
u32 size = atoi((void *)((uintptr_t)armHdr+0x30));
|
||||||
|
@ -129,8 +129,10 @@ void sha(void* res, const void* src, u32 size, u32 mode);
|
|||||||
void rsa_setkey(u32 keyslot, const void* mod, const void* exp, u32 mode);
|
void rsa_setkey(u32 keyslot, const void* mod, const void* exp, u32 mode);
|
||||||
void rsa_use_keyslot(u32 keyslot);
|
void rsa_use_keyslot(u32 keyslot);
|
||||||
int rsa_verify(const void* data, u32 size, const void* sig, u32 mode);
|
int rsa_verify(const void* data, u32 size, const void* sig, u32 mode);
|
||||||
|
void xor(u8 *dest, u8 *data1, u8 *data2, u32 size);
|
||||||
|
|
||||||
//NAND/FIRM stuff
|
//NAND/FIRM stuff
|
||||||
|
extern const u8 memeKey[0x10];
|
||||||
void arm9loader(void *armHdr);
|
void arm9loader(void *armHdr);
|
||||||
|
|
||||||
#endif /*__CRYPTO_H*/
|
#endif /*__CRYPTO_H*/
|
||||||
|
@ -21,10 +21,10 @@ void getEmunandSect(u32 *off, u32 *head){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSDMMC(void *offset, u32 *off, u32 size){
|
void getSDMMC(void *pos, u32 *off, u32 size){
|
||||||
//Look for struct code
|
//Look for struct code
|
||||||
unsigned char pattern[] = {0x01, 0x21, 0x20, 0x18, 0x20, 0x30};
|
unsigned char pattern[] = {0x01, 0x21, 0x20, 0x18, 0x20, 0x30};
|
||||||
*off = memsearch(offset, pattern, size, 6);
|
*off = memsearch(pos, pattern, size, 4);
|
||||||
|
|
||||||
//Get DCD values
|
//Get DCD values
|
||||||
unsigned char buf[4];
|
unsigned char buf[4];
|
||||||
@ -43,6 +43,14 @@ void getSDMMC(void *offset, u32 *off, u32 size){
|
|||||||
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
||||||
//Look for read/write code
|
//Look for read/write code
|
||||||
unsigned char pattern[] = {0x04, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x1E, 0x00, 0xC8, 0x05};
|
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.
|
*readOff = memsearch(pos, pattern, size, 4);
|
||||||
|
*writeOff = memsearch(readOff, pattern, 0x1000, 4);
|
||||||
|
//fileWrite(readOff, "/readoff.bin", 4);
|
||||||
|
*readOff = 0x240CEC40;
|
||||||
|
*writeOff = 0x240CEC80;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getMPU(void *pos, u32 *off){
|
||||||
|
*off = 0x2407D7D4;
|
||||||
}
|
}
|
@ -12,7 +12,8 @@
|
|||||||
#define NCSD_MAGIC (0x4453434E)
|
#define NCSD_MAGIC (0x4453434E)
|
||||||
|
|
||||||
void getEmunandSect(u32 *off, u32 *head);
|
void getEmunandSect(u32 *off, u32 *head);
|
||||||
void getSDMMC(void *offset, u32 *off, u32 size);
|
void getSDMMC(void *pos, u32 *off, u32 size);
|
||||||
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
|
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
|
||||||
|
void getMPU(void *pos, u32 *off);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -18,7 +18,8 @@ u32 emuOffset = 0,
|
|||||||
emuRead = 0,
|
emuRead = 0,
|
||||||
emuWrite = 0,
|
emuWrite = 0,
|
||||||
sdmmcOffset = 0,
|
sdmmcOffset = 0,
|
||||||
firmSize = 0;
|
firmSize = 0,
|
||||||
|
mpuOffset = 0;
|
||||||
|
|
||||||
//Load firm into FCRAM
|
//Load firm into FCRAM
|
||||||
void loadFirm(void){
|
void loadFirm(void){
|
||||||
@ -26,6 +27,14 @@ void loadFirm(void){
|
|||||||
const char firmPath[] = "/rei/firmware.bin";
|
const char firmPath[] = "/rei/firmware.bin";
|
||||||
firmSize = fileSize(firmPath);
|
firmSize = fileSize(firmPath);
|
||||||
fileRead((u8*)firmLocation, firmPath, firmSize);
|
fileRead((u8*)firmLocation, firmPath, firmSize);
|
||||||
|
|
||||||
|
//Decrypt firmware blob
|
||||||
|
u8 firmIV[0x10] = {0};
|
||||||
|
aes_setkey(0x16, memeKey, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
aes_use_keyslot(0x16);
|
||||||
|
aes((u8*)firmLocation, (u8*)firmLocation, firmSize / AES_BLOCK_SIZE, firmIV, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
|
//Parse firmware
|
||||||
section = firmLocation->section;
|
section = firmLocation->section;
|
||||||
arm9loader((u8*)firmLocation + section[2].offset);
|
arm9loader((u8*)firmLocation + section[2].offset);
|
||||||
}
|
}
|
||||||
@ -37,7 +46,7 @@ void loadEmu(void){
|
|||||||
u32 code = emuCode();
|
u32 code = emuCode();
|
||||||
const char path[] = "/rei/emunand/emunand.bin";
|
const char path[] = "/rei/emunand/emunand.bin";
|
||||||
u32 size = fileSize(path);
|
u32 size = fileSize(path);
|
||||||
fileRead(code, path, size);
|
fileRead((u8*)code, path, size);
|
||||||
|
|
||||||
//Find and patch emunand related offsets
|
//Find and patch emunand related offsets
|
||||||
u32 *pos_sdmmc = memsearch(code, "SDMC", size, 4);
|
u32 *pos_sdmmc = memsearch(code, "SDMC", size, 4);
|
||||||
@ -46,6 +55,7 @@ void loadEmu(void){
|
|||||||
getSDMMC(firmLocation, &sdmmcOffset, firmSize);
|
getSDMMC(firmLocation, &sdmmcOffset, firmSize);
|
||||||
getEmunandSect(&emuOffset, &emuHeader);
|
getEmunandSect(&emuOffset, &emuHeader);
|
||||||
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
|
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
|
||||||
|
getMPU(firmLocation, &mpuOffset);
|
||||||
*pos_sdmmc = sdmmcOffset;
|
*pos_sdmmc = sdmmcOffset;
|
||||||
*pos_offset = emuOffset;
|
*pos_offset = emuOffset;
|
||||||
*pos_header = emuHeader;
|
*pos_header = emuHeader;
|
||||||
@ -53,12 +63,13 @@ void loadEmu(void){
|
|||||||
//Add emunand hooks
|
//Add emunand hooks
|
||||||
memcpy((u8*)emuRead, nandRedir, sizeof(nandRedir));
|
memcpy((u8*)emuRead, nandRedir, sizeof(nandRedir));
|
||||||
memcpy((u8*)emuWrite, nandRedir, sizeof(nandRedir));
|
memcpy((u8*)emuWrite, nandRedir, sizeof(nandRedir));
|
||||||
memcpy((u8*)mpuCode(), mpu, sizeof(mpu));
|
|
||||||
|
//Set MPU for emu code region
|
||||||
|
memcpy((u8*)mpuOffset, mpu, sizeof(mpu));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Patches
|
//Patches
|
||||||
void patchFirm(){
|
void patchFirm(){
|
||||||
|
|
||||||
//Disable signature checks
|
//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));
|
||||||
|
@ -56,11 +56,6 @@ u32 threadCode(void){
|
|||||||
return KERNEL9 + (0x08006070 - K9_ADDR);
|
return KERNEL9 + (0x08006070 - K9_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Area of MPU setting code
|
|
||||||
u32 mpuCode(void){
|
|
||||||
return KERNEL9 + (0x0801B3D4 - K9_ADDR);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Offsets to redirect to thread code
|
//Offsets to redirect to thread code
|
||||||
u32 threadHook(u8 val){
|
u32 threadHook(u8 val){
|
||||||
return val == 1 ?
|
return val == 1 ?
|
||||||
|
@ -39,7 +39,7 @@ 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 + 0x0A, (void*)L"%d.%d.%d-%d", 11)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
|
if(strcomp((void*)0x27B00000 - i + 0x28, (void*)"T_ver_00", 4)) strcopy((void*)0x27B00000 - i, (void*)L"\uE024Rei", 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ void thread(void){
|
|||||||
int loc = 0;
|
int loc = 0;
|
||||||
fileReadWrite(buf, L"sdmc:/rei/RAM.txt", 0x20, READ);
|
fileReadWrite(buf, L"sdmc:/rei/RAM.txt", 0x20, READ);
|
||||||
loc = atoi(buf);
|
loc = atoi(buf);
|
||||||
memdump(L"sdmc:/RAMdmp.bin", (void*)loc, 0x500000);
|
memdump(L"sdmc:/RAMdmp.bin", (void*)loc, 0x10000);
|
||||||
}
|
}
|
||||||
patches();
|
patches();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user