From 615e5dfaa7d559ebcc417a2949791fb18da9ccd6 Mon Sep 17 00:00:00 2001 From: Aurora Date: Tue, 11 Oct 2016 16:52:51 +0200 Subject: [PATCH] Fixed CTRNAND writing leaving encrypted data (thanks to d0k3), added path.txt support for CTRNAND, have the firmlaunch patch panic if both payloads cannot be found --- exceptions/arm9/source/mainHandler.c | 2 +- patches/reboot.s | 12 ++++++++++-- source/config.c | 2 +- source/crypto.c | 26 ++++++++++++++++++++------ source/crypto.h | 3 ++- source/fatfs/diskio.c | 2 +- source/firm.c | 4 ++-- source/firm.h | 2 +- source/main.c | 2 +- source/patches.c | 4 ++-- source/patches.h | 2 +- source/utils.c | 6 +++--- 12 files changed, 45 insertions(+), 22 deletions(-) diff --git a/exceptions/arm9/source/mainHandler.c b/exceptions/arm9/source/mainHandler.c index 5023f6d..98eb52f 100644 --- a/exceptions/arm9/source/mainHandler.c +++ b/exceptions/arm9/source/mainHandler.c @@ -113,6 +113,6 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type) *(ExceptionDumpHeader *)FINAL_BUFFER = dumpHeader; ((void (*)())0xFFFF0830)(); //Ensure that all memory transfers have completed and that the data cache has been flushed - i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot + i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 1); //Reboot while(true); } \ No newline at end of file diff --git a/patches/reboot.s b/patches/reboot.s index e64cc49..091f92a 100644 --- a/patches/reboot.s +++ b/patches/reboot.s @@ -26,9 +26,12 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB bne pxi_wait_recv adr r1, sd_fname + mov r4, #0 open_payload: ; Open file + cmp r4, #2 ; Panic if both payloads don't exist + beq svcBreak add r0, r7, #8 mov r2, #1 ldr r6, [fopen] @@ -36,6 +39,7 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB blx r6 cmp r0, #0 adrne r1, nand_fname + addne r4, #1 bne open_payload ; Read file @@ -73,14 +77,18 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB die: b die + svcBreak: + swi 0x3C + b die + bytes_read: .word 0 fopen: .ascii "OPEN" .pool sd_fname: .dcw "sdmc:/arm9loaderhax.bin" - .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .pool nand_fname: .dcw "nand:/arm9loaderhax.bin" - .word 0 + .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .align 4 kernelcode_start: diff --git a/source/config.c b/source/config.c index c609eff..23676cb 100644 --- a/source/config.c +++ b/source/config.c @@ -213,7 +213,7 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) { .visible = isSdMode }, { .visible = isSdMode }, { .visible = true }, - { .visible = isSdMode }, + { .visible = true }, { .visible = true }, { .visible = true }, { .visible = true }, diff --git a/source/crypto.c b/source/crypto.c index 250b486..b3303ea 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -24,6 +24,7 @@ * Crypto libs from http://github.com/b1l1s/ctr * kernel9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233 * decryptNusFirm code adapted from https://github.com/mid-kid/CakesForeveryWan/blob/master/source/firm.c +* ctrNandWrite logic adapted from https://github.com/d0k3/GodMode9/blob/master/source/nand/nand.c */ #include "crypto.h" @@ -352,18 +353,31 @@ int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf) return result; } -int ctrNandWrite(u32 sector, u32 sectorCount, u8 *inbuf) +int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf) { + u8 *buffer = (u8 *)0x23000000; + u32 bufferSize = 0xF00000; + u8 __attribute__((aligned(4))) tmpCtr[sizeof(nandCtr)]; memcpy(tmpCtr, nandCtr, sizeof(nandCtr)); aes_advctr(tmpCtr, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); - - //Encrypt aes_use_keyslot(nandSlot); - aes(inbuf, inbuf, sectorCount * 0x200 / AES_BLOCK_SIZE, tmpCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); - //Write - return sdmmc_nand_writesectors(sector + fatStart, sectorCount, inbuf); + int result = 0; + for(u32 i = 0; i < sectorCount && !result; i += bufferSize / 0x200) + { + u32 tempAmount = (bufferSize / 0x200) < (sectorCount - i) ? (bufferSize / 0x200) : (sectorCount - i); + + memcpy(buffer, inbuf + (i * 0x200), tempAmount * 0x200); + + //Encrypt + aes(buffer, buffer, tempAmount * 0x200 / AES_BLOCK_SIZE, tmpCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); + + //Write + result = sdmmc_nand_writesectors(i + sector + fatStart, tempAmount, buffer); + } + + return result; } void set6x7xKeys(void) diff --git a/source/crypto.h b/source/crypto.h index dd4cc3f..f332690 100755 --- a/source/crypto.h +++ b/source/crypto.h @@ -24,6 +24,7 @@ * Crypto libs from http://github.com/b1l1s/ctr * kernel9Loader code originally adapted from https://github.com/Reisyukaku/ReiNand/blob/228c378255ba693133dec6f3368e14d386f2cde7/source/crypto.c#L233 * decryptNusFirm code adapted from https://github.com/mid-kid/CakesForeveryWan/blob/master/source/firm.c +* ctrNandWrite logic adapted from https://github.com/d0k3/GodMode9/blob/master/source/nand/nand.c */ #pragma once @@ -106,7 +107,7 @@ extern FirmwareSource firmSource; void ctrNandInit(void); int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); -int ctrNandWrite(u32 sector, u32 sectorCount, u8 *inbuf); +int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf); void set6x7xKeys(void); bool decryptExeFs(Cxi *cxi); bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize); diff --git a/source/fatfs/diskio.c b/source/fatfs/diskio.c index 8fa59e7..048552a 100644 --- a/source/fatfs/diskio.c +++ b/source/fatfs/diskio.c @@ -88,7 +88,7 @@ DRESULT disk_write ( ) { return ((pdrv == SDCARD && !sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) || - (pdrv == CTRNAND && !ctrNandWrite(sector, count, (BYTE *)buff))) ? RES_OK : RES_PARERR; + (pdrv == CTRNAND && !ctrNandWrite(sector, count, buff))) ? RES_OK : RES_PARERR; } #endif diff --git a/source/firm.c b/source/firm.c index 7ea5375..0d8226c 100755 --- a/source/firm.c +++ b/source/firm.c @@ -109,7 +109,7 @@ u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStora return firmVersion; } -u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, u32 devMode) +u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isSdMode, u32 devMode) { u8 *arm9Section = (u8 *)firm + firm->section[2].offset, *arm11Section1 = (u8 *)firm + firm->section[1].offset; @@ -148,7 +148,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, u32 else if(ISA9LH || (ISFIRMLAUNCH && BOOTCFG_A9LH != 0)) ret += patchFirmWrites(process9Offset, process9Size); //Apply firmlaunch patches - ret += patchFirmlaunches(process9Offset, process9Size, process9MemAddr); + ret += patchFirmlaunches(process9Offset, process9Size, process9MemAddr, isSdMode); //11.0 FIRM patches if(firmVersion >= (ISN3DS ? 0x21 : 0x52)) diff --git a/source/firm.h b/source/firm.h index 937dde6..e4192e7 100644 --- a/source/firm.h +++ b/source/firm.h @@ -25,7 +25,7 @@ #include "types.h" u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSdMode); -u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, u32 devMode); +u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isSdMode, u32 devMode); u32 patchTwlFirm(u32 firmVersion, u32 devMode); u32 patchAgbFirm(u32 devMode); u32 patch1x2xNativeAndSafeFirm(u32 devMode); diff --git a/source/main.c b/source/main.c index 8dd594c..edc31fd 100644 --- a/source/main.c +++ b/source/main.c @@ -230,7 +230,7 @@ void main(void) switch(firmType) { case NATIVE_FIRM: - res = patchNativeFirm(firmVersion, nandType, emuHeader, devMode); + res = patchNativeFirm(firmVersion, nandType, emuHeader, isSdMode, devMode); break; case SAFE_FIRM: case NATIVE_FIRM1X2X: diff --git a/source/patches.c b/source/patches.c index b727c5d..52448e2 100644 --- a/source/patches.c +++ b/source/patches.c @@ -101,7 +101,7 @@ u32 patchSignatureChecks(u8 *pos, u32 size) return ret; } -u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr) +u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr, bool isSdMode) { //Look for firmlaunch code const u8 pattern[] = {0xE2, 0x20, 0x20, 0x90}; @@ -146,7 +146,7 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr) finalPath[i] = (u16)path[i]; finalPath[pathSize] = 0; - u8 *pos_path = memsearch(off, u"sd", reboot_bin_size, 4) + 0xA; + u8 *pos_path = memsearch(off, isSdMode ? u"sd" : u"na", reboot_bin_size, 4) + 0xA; memcpy(pos_path, finalPath, (pathSize + 1) * 2); } } diff --git a/source/patches.h b/source/patches.h index e762346..092da01 100644 --- a/source/patches.h +++ b/source/patches.h @@ -34,7 +34,7 @@ u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage); u32 patchSignatureChecks(u8 *pos, u32 size); u32 patchTitleInstallMinVersionChecks(u8 *pos, u32 size, u32 firmVersion); -u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); +u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr, bool isSdMode); u32 patchFirmWrites(u8 *pos, u32 size); u32 patchOldFirmWrites(u8 *pos, u32 size); u32 reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u32 baseK11VA, u8 **freeK11Space); diff --git a/source/utils.c b/source/utils.c index edda2a7..c577a80 100644 --- a/source/utils.c +++ b/source/utils.c @@ -56,7 +56,7 @@ u32 waitInput(void) void mcuReboot(void) { - if(ISFIRMLAUNCH && PDN_GPU_CNT != 1) clearScreens(true, true, false); + if(!ISFIRMLAUNCH && PDN_GPU_CNT != 1) clearScreens(true, true, false); //Ensure that all memory transfers have completed and that the data cache has been flushed flushEntireDCache(); @@ -67,11 +67,11 @@ void mcuReboot(void) void mcuPowerOff(void) { - if(ISFIRMLAUNCH && PDN_GPU_CNT != 1) clearScreens(true, true, false); + if(!ISFIRMLAUNCH && PDN_GPU_CNT != 1) clearScreens(true, true, false); //Ensure that all memory transfers have completed and that the data cache has been flushed flushEntireDCache(); - + i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0); while(true); }