From 83a0293af45abd18844a060d1eb75870d619f773 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Sun, 28 Aug 2016 00:32:47 +0200 Subject: [PATCH 01/20] Add support (firmprot and firmlaunch patches) for 2.x on sysNAND --- patches/reboot.s | 6 ++++-- source/firm.c | 45 ++++++++++++++++++++++++++------------------- source/firm.h | 4 ++-- source/patches.c | 2 +- source/patches.h | 2 +- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/patches/reboot.s b/patches/reboot.s index 9cb779f..35cb7fb 100644 --- a/patches/reboot.s +++ b/patches/reboot.s @@ -7,12 +7,14 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB .arm ; Interesting registers and locations to keep in mind, set just before this code is ran: ; - r1: FIRM path in exefs. - ; - r7: pointer to file object + ; - r7: pointer to file object (r10 on < 4.x; r7 is equal to 0 in that case) ; - *r7: vtable ; - *(vtable + 0x28): fread function - ; - *(r7 + 8): file handle + ; - *(r7 + 8) = r0: file handle mov r8, r1 + cmp r7, #0 + moveq r7, r10 pxi_wait_recv: ldr r2, =0x44846 diff --git a/source/firm.c b/source/firm.c index 7c9c0c4..385931b 100755 --- a/source/firm.c +++ b/source/firm.c @@ -40,14 +40,14 @@ extern u16 launchedFirmTIDLow[8]; //Defined in start.s static firmHeader *const firm = (firmHeader *)0x24000000; static const firmSectionHeader *section; -u32 emuOffset; +u32 emuOffset, firmVersion; bool isN3DS, isDevUnit, isFirmlaunch; cfgData configData; -FirmwareSource firmSource; +FirmwareSource firmSource, nandType; void main(void) { @@ -213,12 +213,12 @@ void main(void) writeConfig(configPath, configTemp); } - u32 firmVersion = loadFirm(firmType); + loadFirm(firmType); switch(firmType) { case NATIVE_FIRM: - patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh); + patchNativeFirm(emuHeader, isA9lh); break; case SAFE_FIRM: patchSafeFirm(); @@ -232,37 +232,38 @@ void main(void) launchFirm(firmType); } -static inline u32 loadFirm(FirmwareType firmType) +static inline void loadFirm(FirmwareType firmType) { section = firm->section; //Load FIRM from CTRNAND, unless it's an O3DS and we're loading a pre-5.0 NATIVE FIRM - u32 firmVersion = firmRead(firm, (u32)firmType); + firmVersion = firmRead(firm, (u32)firmType); if(!isN3DS && firmType == NATIVE_FIRM && firmVersion < 0x25) { - //We can't boot < 3.x NANDs - if(firmVersion < 0x18) + //We can't boot < 2.x NANDs. No emuNAND either. + if(firmVersion < ((firmSource == FIRMWARE_SYSNAND) ? 9 : 0x18)) error("An old unsupported NAND has been detected.\nLuma3DS is unable to boot it."); //We can't boot a 4.x NATIVE_FIRM, load one from SD - if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) != 0x68) - error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot"); + else if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) != 0x68) + error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot."); //No assumption regarding FIRM version firmVersion = 0xffffffff; } - else decryptExeFs((u8 *)firm); + else if(!isN3DS && firmType == SAFE_FIRM && firmVersion < 1) + error("An old unsupported SAFE_FIRM has been detected."); - return firmVersion; + else decryptExeFs((u8 *)firm); } -static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh) +static inline void patchNativeFirm(u32 emuHeader, bool isA9lh) { u8 *arm9Section = (u8 *)firm + section[2].offset; u8 *arm11Section1 = (u8 *)firm + section[1].offset; - if(isN3DS) + if(firmVersion >= 0x37 && isN3DS) { //Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader arm9Loader(arm9Section); @@ -277,6 +278,15 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 process9MemAddr; u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr); + //Apply firmlaunch patches + patchFirmlaunches(process9Offset, process9Size, process9MemAddr); + + if(firmVersion < 0x18) // < 3.x + { + if(isA9lh) patchOldFirmWrites(process9Offset, process9Size); + return; + } + //Apply signature patches patchSignatureChecks(process9Offset, process9Size); @@ -290,9 +300,6 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 //Apply FIRM0/1 writes patches on sysNAND to protect A9LH else if(isA9lh) patchFirmWrites(process9Offset, process9Size); - //Apply firmlaunch patches - patchFirmlaunches(process9Offset, process9Size, process9MemAddr); - //11.0 FIRM patches if(firmVersion >= (isN3DS ? 0x21 : 0x52)) { @@ -333,7 +340,7 @@ static inline void patchSafeFirm(void) patchFirmWrites(arm9Section, section[2].size); } - else patchFirmWriteSafe(arm9Section, section[2].size); + else patchOldFirmWrites(arm9Section, section[2].size); } static inline void copySection0AndInjectSystemModules(void) @@ -371,7 +378,7 @@ static inline void launchFirm(FirmwareType firmType) { //If we're booting NATIVE_FIRM, section0 needs to be copied separately to inject 3ds_injector u32 sectionNum; - if(firmType == NATIVE_FIRM) + if(firmType == NATIVE_FIRM && firmVersion >= 0x18) { copySection0AndInjectSystemModules(); sectionNum = 1; diff --git a/source/firm.h b/source/firm.h index 7b5d84d..a24b551 100644 --- a/source/firm.h +++ b/source/firm.h @@ -54,8 +54,8 @@ typedef enum ConfigurationStatus CREATE_CONFIGURATION = 2 } ConfigurationStatus; -static inline u32 loadFirm(FirmwareType firmType); -static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh); +static inline void loadFirm(FirmwareType firmType); +static inline void patchNativeFirm(u32 emuHeader, bool isA9lh); static inline void patchLegacyFirm(FirmwareType firmType); static inline void patchSafeFirm(void); static inline void copySection0AndInjectSystemModules(void); diff --git a/source/patches.c b/source/patches.c index 957a9b0..cdad593 100644 --- a/source/patches.c +++ b/source/patches.c @@ -113,7 +113,7 @@ void patchFirmWrites(u8 *pos, u32 size) off2[1] = writeBlock[1]; } -void patchFirmWriteSafe(u8 *pos, u32 size) +void patchOldFirmWrites(u8 *pos, u32 size) { const u16 writeBlockSafe[2] = {0x2400, 0xE01D}; diff --git a/source/patches.h b/source/patches.h index 24e82bb..8b6ccae 100644 --- a/source/patches.h +++ b/source/patches.h @@ -54,7 +54,7 @@ void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); void patchFirmWrites(u8 *pos, u32 size); -void patchFirmWriteSafe(u8 *pos, u32 size); +void patchOldFirmWrites(u8 *pos, u32 size); void reimplementSvcBackdoor(u8 *pos, u32 size); void implementSvcGetCFWInfo(u8 *pos, u32 size); void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); From 9c5248b87a0dbe4e6db417cef176f581a3c1e031 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 02:38:30 +0200 Subject: [PATCH 02/20] Cleanup previous commit --- patches/reboot.s | 6 ++--- source/firm.c | 65 +++++++++++++++++++++++++----------------------- source/firm.h | 4 +-- source/patches.c | 2 +- source/patches.h | 2 +- 5 files changed, 40 insertions(+), 39 deletions(-) diff --git a/patches/reboot.s b/patches/reboot.s index 35cb7fb..9cb779f 100644 --- a/patches/reboot.s +++ b/patches/reboot.s @@ -7,14 +7,12 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB .arm ; Interesting registers and locations to keep in mind, set just before this code is ran: ; - r1: FIRM path in exefs. - ; - r7: pointer to file object (r10 on < 4.x; r7 is equal to 0 in that case) + ; - r7: pointer to file object ; - *r7: vtable ; - *(vtable + 0x28): fread function - ; - *(r7 + 8) = r0: file handle + ; - *(r7 + 8): file handle mov r8, r1 - cmp r7, #0 - moveq r7, r10 pxi_wait_recv: ldr r2, =0x44846 diff --git a/source/firm.c b/source/firm.c index 385931b..321070f 100755 --- a/source/firm.c +++ b/source/firm.c @@ -40,14 +40,14 @@ extern u16 launchedFirmTIDLow[8]; //Defined in start.s static firmHeader *const firm = (firmHeader *)0x24000000; static const firmSectionHeader *section; -u32 emuOffset, firmVersion; +u32 emuOffset; bool isN3DS, isDevUnit, isFirmlaunch; cfgData configData; -FirmwareSource firmSource, nandType; +FirmwareSource firmSource; void main(void) { @@ -213,14 +213,15 @@ void main(void) writeConfig(configPath, configTemp); } - loadFirm(firmType); + u32 firmVersion = loadFirm(&firmType, firmSource); switch(firmType) { case NATIVE_FIRM: - patchNativeFirm(emuHeader, isA9lh); + patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh); break; case SAFE_FIRM: + if(!isFirmlaunch && BOOTCONFIG(5, 1)) error("SAFE_MODE is not supported on 2.x FIRM!"); patchSafeFirm(); break; default: @@ -232,38 +233,46 @@ void main(void) launchFirm(firmType); } -static inline void loadFirm(FirmwareType firmType) +static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) { section = firm->section; //Load FIRM from CTRNAND, unless it's an O3DS and we're loading a pre-5.0 NATIVE FIRM - firmVersion = firmRead(firm, (u32)firmType); + u32 firmVersion = firmRead(firm, (u32)*firmType); - if(!isN3DS && firmType == NATIVE_FIRM && firmVersion < 0x25) + if(!isN3DS && *firmType == NATIVE_FIRM) { - //We can't boot < 2.x NANDs. No emuNAND either. - if(firmVersion < ((firmSource == FIRMWARE_SYSNAND) ? 9 : 0x18)) - error("An old unsupported NAND has been detected.\nLuma3DS is unable to boot it."); + //We can't boot < 2.x SysNANDs and < 3.x EmuNANDs. + if(firmVersion < 0x18) + { + if(firmSource == FIRMWARE_SYSNAND && firmVersion < 9) + error("An old unsupported NAND has been detected.\nLuma3DS is unable to boot it"); - //We can't boot a 4.x NATIVE_FIRM, load one from SD - else if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) != 0x68) - error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot."); + *firmType = SAFE_FIRM; + } - //No assumption regarding FIRM version - firmVersion = 0xffffffff; + //We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD + if(firmVersion > 0xF && firmVersion < 0x25 && firmSource != FIRMWARE_SYSNAND) + { + if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) != 0x68) + error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot"); + + //No assumption regarding FIRM version + firmVersion = 0xFFFFFFFF; + } } - else if(!isN3DS && firmType == SAFE_FIRM && firmVersion < 1) - error("An old unsupported SAFE_FIRM has been detected."); - else decryptExeFs((u8 *)firm); + if(firmVersion != 0xFFFFFFFF) decryptExeFs((u8 *)firm); + + return firmVersion; } -static inline void patchNativeFirm(u32 emuHeader, bool isA9lh) +static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh) { u8 *arm9Section = (u8 *)firm + section[2].offset; u8 *arm11Section1 = (u8 *)firm + section[1].offset; - if(firmVersion >= 0x37 && isN3DS) + if(isN3DS) { //Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader arm9Loader(arm9Section); @@ -278,15 +287,6 @@ static inline void patchNativeFirm(u32 emuHeader, bool isA9lh) process9MemAddr; u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr); - //Apply firmlaunch patches - patchFirmlaunches(process9Offset, process9Size, process9MemAddr); - - if(firmVersion < 0x18) // < 3.x - { - if(isA9lh) patchOldFirmWrites(process9Offset, process9Size); - return; - } - //Apply signature patches patchSignatureChecks(process9Offset, process9Size); @@ -300,6 +300,9 @@ static inline void patchNativeFirm(u32 emuHeader, bool isA9lh) //Apply FIRM0/1 writes patches on sysNAND to protect A9LH else if(isA9lh) patchFirmWrites(process9Offset, process9Size); + //Apply firmlaunch patches + patchFirmlaunches(process9Offset, process9Size, process9MemAddr); + //11.0 FIRM patches if(firmVersion >= (isN3DS ? 0x21 : 0x52)) { @@ -340,7 +343,7 @@ static inline void patchSafeFirm(void) patchFirmWrites(arm9Section, section[2].size); } - else patchOldFirmWrites(arm9Section, section[2].size); + else patchFirmWriteSafe(arm9Section, section[2].size); } static inline void copySection0AndInjectSystemModules(void) @@ -378,7 +381,7 @@ static inline void launchFirm(FirmwareType firmType) { //If we're booting NATIVE_FIRM, section0 needs to be copied separately to inject 3ds_injector u32 sectionNum; - if(firmType == NATIVE_FIRM && firmVersion >= 0x18) + if(firmType == NATIVE_FIRM) { copySection0AndInjectSystemModules(); sectionNum = 1; diff --git a/source/firm.h b/source/firm.h index a24b551..12ae222 100644 --- a/source/firm.h +++ b/source/firm.h @@ -54,8 +54,8 @@ typedef enum ConfigurationStatus CREATE_CONFIGURATION = 2 } ConfigurationStatus; -static inline void loadFirm(FirmwareType firmType); -static inline void patchNativeFirm(u32 emuHeader, bool isA9lh); +static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource); +static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh); static inline void patchLegacyFirm(FirmwareType firmType); static inline void patchSafeFirm(void); static inline void copySection0AndInjectSystemModules(void); diff --git a/source/patches.c b/source/patches.c index cdad593..957a9b0 100644 --- a/source/patches.c +++ b/source/patches.c @@ -113,7 +113,7 @@ void patchFirmWrites(u8 *pos, u32 size) off2[1] = writeBlock[1]; } -void patchOldFirmWrites(u8 *pos, u32 size) +void patchFirmWriteSafe(u8 *pos, u32 size) { const u16 writeBlockSafe[2] = {0x2400, 0xE01D}; diff --git a/source/patches.h b/source/patches.h index 8b6ccae..24e82bb 100644 --- a/source/patches.h +++ b/source/patches.h @@ -54,7 +54,7 @@ void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); void patchFirmWrites(u8 *pos, u32 size); -void patchOldFirmWrites(u8 *pos, u32 size); +void patchFirmWriteSafe(u8 *pos, u32 size); void reimplementSvcBackdoor(u8 *pos, u32 size); void implementSvcGetCFWInfo(u8 *pos, u32 size); void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); From 71c5404bfe4631f6ba0272b4a35535c75995453b Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 02:41:00 +0200 Subject: [PATCH 03/20] Fix derp --- source/firm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/firm.c b/source/firm.c index 321070f..9c0233c 100755 --- a/source/firm.c +++ b/source/firm.c @@ -242,10 +242,10 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) if(!isN3DS && *firmType == NATIVE_FIRM) { - //We can't boot < 2.x SysNANDs and < 3.x EmuNANDs. + //We can't boot < 2.x SysNANDs and < 3.x EmuNANDs if(firmVersion < 0x18) { - if(firmSource == FIRMWARE_SYSNAND && firmVersion < 9) + if(firmSource != FIRMWARE_SYSNAND || firmVersion < 9) error("An old unsupported NAND has been detected.\nLuma3DS is unable to boot it"); *firmType = SAFE_FIRM; From 4c93d2b1f943cf21f1181675964695e9d3c690f0 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 02:49:53 +0200 Subject: [PATCH 04/20] Better to put this here --- source/firm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/firm.c b/source/firm.c index 9c0233c..91203ed 100755 --- a/source/firm.c +++ b/source/firm.c @@ -221,7 +221,6 @@ void main(void) patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh); break; case SAFE_FIRM: - if(!isFirmlaunch && BOOTCONFIG(5, 1)) error("SAFE_MODE is not supported on 2.x FIRM!"); patchSafeFirm(); break; default: @@ -248,6 +247,8 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) if(firmSource != FIRMWARE_SYSNAND || firmVersion < 9) error("An old unsupported NAND has been detected.\nLuma3DS is unable to boot it"); + if(BOOTCONFIG(5, 1)) error("SAFE_MODE is not supported on 2.x FIRM!"); + *firmType = SAFE_FIRM; } From 317899b4bf7e5da3f6aae4290568649d9a86cf48 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 02:54:44 +0200 Subject: [PATCH 05/20] Fix another derp --- source/firm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/firm.c b/source/firm.c index 91203ed..cbf6d17 100755 --- a/source/firm.c +++ b/source/firm.c @@ -236,7 +236,7 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) { section = firm->section; - //Load FIRM from CTRNAND, unless it's an O3DS and we're loading a pre-5.0 NATIVE FIRM + //Load FIRM from CTRNAND u32 firmVersion = firmRead(firm, (u32)*firmType); if(!isN3DS && *firmType == NATIVE_FIRM) @@ -253,7 +253,7 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) } //We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD - if(firmVersion > 0xF && firmVersion < 0x25 && firmSource != FIRMWARE_SYSNAND) + else if(firmVersion < 0x25) { if(!fileRead(firm, "/luma/firmware.bin") || (((u32)section[2].address >> 8) & 0xFF) != 0x68) error("An old unsupported FIRM has been detected.\nCopy firmware.bin in /luma to boot"); From 51c514de84c946d268af5e962e5a90afe03e8ab6 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Sun, 28 Aug 2016 11:48:35 +0200 Subject: [PATCH 06/20] Add back reboot patch on 2.x --- patches/reboot.s | 3 +++ source/firm.c | 13 ++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/patches/reboot.s b/patches/reboot.s index 9cb779f..4c60db1 100644 --- a/patches/reboot.s +++ b/patches/reboot.s @@ -14,6 +14,9 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB mov r8, r1 + cmp r7, #0 + moveq r7, r10 ; for 2.x + pxi_wait_recv: ldr r2, =0x44846 ldr r0, =0x10008000 diff --git a/source/firm.c b/source/firm.c index cbf6d17..569c4af 100755 --- a/source/firm.c +++ b/source/firm.c @@ -341,10 +341,17 @@ static inline void patchSafeFirm(void) //Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader arm9Loader(arm9Section); firm->arm9Entry = (u8 *)0x801B01C; - - patchFirmWrites(arm9Section, section[2].size); } - else patchFirmWriteSafe(arm9Section, section[2].size); + + //Find the Process9 .code location, size and memory address + u32 process9Size, + process9MemAddr; + u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr); + + if(isN3DS) patchFirmWrites(process9Offset, process9Size); + else patchFirmWriteSafe(process9Offset, process9Size); + + patchFirmlaunches(process9Offset, process9Size, process9MemAddr); } static inline void copySection0AndInjectSystemModules(void) From 760aa9970962e76dd3d1a0609413531fa99bf5e4 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 12:33:00 +0200 Subject: [PATCH 07/20] Revert "Add back reboot patch on 2.x" This reverts commit 51c514de84c946d268af5e962e5a90afe03e8ab6. --- patches/reboot.s | 3 --- source/firm.c | 13 +++---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/patches/reboot.s b/patches/reboot.s index 4c60db1..9cb779f 100644 --- a/patches/reboot.s +++ b/patches/reboot.s @@ -14,9 +14,6 @@ payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeB mov r8, r1 - cmp r7, #0 - moveq r7, r10 ; for 2.x - pxi_wait_recv: ldr r2, =0x44846 ldr r0, =0x10008000 diff --git a/source/firm.c b/source/firm.c index 569c4af..cbf6d17 100755 --- a/source/firm.c +++ b/source/firm.c @@ -341,17 +341,10 @@ static inline void patchSafeFirm(void) //Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader arm9Loader(arm9Section); firm->arm9Entry = (u8 *)0x801B01C; + + patchFirmWrites(arm9Section, section[2].size); } - - //Find the Process9 .code location, size and memory address - u32 process9Size, - process9MemAddr; - u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr); - - if(isN3DS) patchFirmWrites(process9Offset, process9Size); - else patchFirmWriteSafe(process9Offset, process9Size); - - patchFirmlaunches(process9Offset, process9Size, process9MemAddr); + else patchFirmWriteSafe(arm9Section, section[2].size); } static inline void copySection0AndInjectSystemModules(void) From 52999db43aeac9f74c87082ee1b0106333331f1b Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 13:49:15 +0200 Subject: [PATCH 08/20] Readability stuff --- injector/source/patcher.c | 5 ++--- loader/source/main.c | 2 +- patches/emunand.s | 2 +- patches/reboot.s | 2 +- patches/twl_k11modules.s | 2 +- source/config.c | 2 +- source/config.h | 2 +- source/firm.c | 26 +++++++++++++------------- source/firm.h | 2 +- source/patches.c | 22 +++++++++++----------- source/patches.h | 2 +- source/pin.c | 19 ++++++++++--------- source/types.h | 3 ++- 13 files changed, 46 insertions(+), 45 deletions(-) diff --git a/injector/source/patcher.c b/injector/source/patcher.c index c5c2627..362230d 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -3,7 +3,7 @@ #include "patcher.h" #include "ifile.h" -static CFWInfo info = {0}; +static CFWInfo info; static int memcmp(const void *buf1, const void *buf2, u32 size) { @@ -97,11 +97,10 @@ static void loadCFWInfo(void) if(!infoLoaded) { svcGetCFWInfo(&info); + IFile file; if(BOOTCONFIG(5, 1) && R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ))) //Init SD card if SAFE_MODE is being booted - { IFile_Close(&file); - } infoLoaded = true; } diff --git a/loader/source/main.c b/loader/source/main.c index 4605d25..f6d9cae 100644 --- a/loader/source/main.c +++ b/loader/source/main.c @@ -23,7 +23,7 @@ #include "memory.h" #include "cache.h" -extern u32 payloadSize; //defined in start.s +extern u32 payloadSize; //Defined in start.s void main(void) { diff --git a/patches/emunand.s b/patches/emunand.s index a7e6cfa..0836c1f 100644 --- a/patches/emunand.s +++ b/patches/emunand.s @@ -43,4 +43,4 @@ nand_sd: sdmmc: .ascii "SDMC" nand_offset: .ascii "NAND" ; for rednand this should be 1 ncsd_header_offset: .ascii "NCSD" ; depends on nand manufacturer + emunand type (GW/RED) -.close +.close \ No newline at end of file diff --git a/patches/reboot.s b/patches/reboot.s index 9cb779f..9174a23 100644 --- a/patches/reboot.s +++ b/patches/reboot.s @@ -125,4 +125,4 @@ dat_fname: .dcw "sdmc:/Luma3DS.dat" bx r0 .pool -.close +.close \ No newline at end of file diff --git a/patches/twl_k11modules.s b/patches/twl_k11modules.s index 88fcc30..d808b27 100644 --- a/patches/twl_k11modules.s +++ b/patches/twl_k11modules.s @@ -143,4 +143,4 @@ patchesEnd: .pool -.close +.close \ No newline at end of file diff --git a/source/config.c b/source/config.c index 6b684fa..a5f7c5c 100644 --- a/source/config.c +++ b/source/config.c @@ -64,7 +64,7 @@ void writeConfig(const char *configPath, u32 configTemp) } } -void configure(void) +void configMenu(void) { initScreens(); diff --git a/source/config.h b/source/config.h index ecdf4b4..899317a 100644 --- a/source/config.h +++ b/source/config.h @@ -43,4 +43,4 @@ extern cfgData configData; bool readConfig(const char *configPath); void writeConfig(const char *configPath, u32 configTemp); -void configure(void); \ No newline at end of file +void configMenu(void); \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index cbf6d17..c6a120d 100755 --- a/source/firm.c +++ b/source/firm.c @@ -137,11 +137,11 @@ void main(void) if(pinExists) verifyPin(&pin); //If no configuration file exists or SELECT is held, load configuration menu - bool shouldLoadConfigurationMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)); + bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)); - if(shouldLoadConfigurationMenu) + if(shouldLoadConfigMenu) { - configure(); + configMenu(); if(!pinExists && CONFIG(8)) newPin(); @@ -164,7 +164,7 @@ void main(void) if(CONFIG(7) && loadSplash()) pressed = HID_PAD; /* If L and R/A/Select or one of the single payload buttons are pressed, - chainload an external payload (the PIN, if any, has been verified)*/ + chainload an external payload */ bool shouldLoadPayload = (pressed & SINGLE_PAYLOAD_BUTTONS) || ((pressed & BUTTON_L1) && (pressed & L_PAYLOAD_BUTTONS)); if(shouldLoadPayload) loadPayload(pressed); @@ -177,8 +177,8 @@ void main(void) //If R is pressed, boot the non-updated NAND with the FIRM of the opposite one if(pressed & BUTTON_R1) { - nandType = (useSysAsDefault) ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND; - firmSource = (useSysAsDefault) ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND; + nandType = useSysAsDefault ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND; + firmSource = useSysAsDefault ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND; } /* Else, boot the NAND the user set to autoboot or the opposite one, depending on L, @@ -221,7 +221,8 @@ void main(void) patchNativeFirm(firmVersion, nandType, emuHeader, isA9lh); break; case SAFE_FIRM: - patchSafeFirm(); + case NATIVE_FIRM2X: + patch2xNativeAndSafeFirm(); break; default: //Skip patching on unsupported O3DS AGB/TWL FIRMs @@ -247,9 +248,9 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource) if(firmSource != FIRMWARE_SYSNAND || firmVersion < 9) error("An old unsupported NAND has been detected.\nLuma3DS is unable to boot it"); - if(BOOTCONFIG(5, 1)) error("SAFE_MODE is not supported on 2.x FIRM!"); + if(BOOTCONFIG(5, 1)) error("SAFE_MODE is not supported on 2.x FIRM"); - *firmType = SAFE_FIRM; + *firmType = NATIVE_FIRM2X; } //We can't boot a 3.x/4.x NATIVE_FIRM, load one from SD @@ -328,11 +329,10 @@ static inline void patchLegacyFirm(FirmwareType firmType) applyLegacyFirmPatches((u8 *)firm, firmType); - if(firmType == TWL_FIRM && CONFIG(5)) - patchTwlBg((u8 *)firm + section[1].offset); + if(firmType == TWL_FIRM && CONFIG(5)) patchTwlBg((u8 *)firm + section[1].offset); } -static inline void patchSafeFirm(void) +static inline void patch2xNativeAndSafeFirm(void) { u8 *arm9Section = (u8 *)firm + section[2].offset; @@ -344,7 +344,7 @@ static inline void patchSafeFirm(void) patchFirmWrites(arm9Section, section[2].size); } - else patchFirmWriteSafe(arm9Section, section[2].size); + else patchOldFirmWrites(arm9Section, section[2].size); } static inline void copySection0AndInjectSystemModules(void) diff --git a/source/firm.h b/source/firm.h index 12ae222..5053910 100644 --- a/source/firm.h +++ b/source/firm.h @@ -57,6 +57,6 @@ typedef enum ConfigurationStatus static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource); static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isA9lh); static inline void patchLegacyFirm(FirmwareType firmType); -static inline void patchSafeFirm(void); +static inline void patch2xNativeAndSafeFirm(void); static inline void copySection0AndInjectSystemModules(void); static inline void launchFirm(FirmwareType firmType); \ No newline at end of file diff --git a/source/patches.c b/source/patches.c index 957a9b0..6bfc7b8 100644 --- a/source/patches.c +++ b/source/patches.c @@ -48,7 +48,7 @@ static void findFreeK11Space(u8 *pos, u32 size) { if(freeK11Space == NULL) { - const u8 pattern[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + const u8 pattern[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; freeK11Space = memsearch(pos, pattern, size, 5) + 1; } @@ -113,23 +113,23 @@ void patchFirmWrites(u8 *pos, u32 size) off2[1] = writeBlock[1]; } -void patchFirmWriteSafe(u8 *pos, u32 size) +void patchOldFirmWrites(u8 *pos, u32 size) { - const u16 writeBlockSafe[2] = {0x2400, 0xE01D}; + const u16 writeBlockOld[2] = {0x2400, 0xE01D}; //Look for FIRM writing code const u8 pattern[] = {0x04, 0x1E, 0x1D, 0xDB}; u16 *off = (u16 *)memsearch(pos, pattern, size, 4); - off[0] = writeBlockSafe[0]; - off[1] = writeBlockSafe[1]; + off[0] = writeBlockOld[0]; + off[1] = writeBlockOld[1]; } void reimplementSvcBackdoor(u8 *pos, u32 size) { //Official implementation of svcBackdoor - const u8 svcBackdoor[40] = {0xFF, 0x10, 0xCD, 0xE3, //bic r1, sp, #0xff + const u8 svcBackdoor[40] = {0xFF, 0x10, 0xCD, 0xE3, //bic r1, sp, #0xff 0x0F, 0x1C, 0x81, 0xE3, //orr r1, r1, #0xf00 0x28, 0x10, 0x81, 0xE2, //add r1, r1, #0x28 0x00, 0x20, 0x91, 0xE5, //ldr r2, [r1] @@ -175,7 +175,7 @@ void implementSvcGetCFWInfo(u8 *pos, u32 size) } else isRelease = rev[4] == 0; - info->flags = 0 /* master branch */ | (((isRelease) ? 1 : 0) << 1) /* is release */; + info->flags = 0 /* master branch */ | ((isRelease ? 1 : 0) << 1) /* is release */; findArm11SvcTable(pos, size); @@ -235,15 +235,15 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType) void patchTwlBg(u8 *pos) { - u8 *dst = pos + ((isN3DS) ? 0xFEA4 : 0xFCA0); + u8 *dst = pos + (isN3DS ? 0xFEA4 : 0xFCA0); memcpy(dst, twl_k11modules, twl_k11modules_size); //Install K11 hook u32 *off = (u32 *)memsearch(dst, "LAUN", twl_k11modules_size, 4); - *off = (isN3DS) ? 0xCDE88 : 0xCD5F8; //Dev SRL launcher offset + *off = isN3DS ? 0xCDE88 : 0xCD5F8; //Dev SRL launcher offset - u16 *src1 = (u16 *)(pos + ((isN3DS) ? 0xE38 : 0xE3C)), - *src2 = (u16 *)(pos + ((isN3DS) ? 0xE54 : 0xE58)); + u16 *src1 = (u16 *)(pos + (isN3DS ? 0xE38 : 0xE3C)), + *src2 = (u16 *)(pos + (isN3DS ? 0xE54 : 0xE58)); //Construct BLX instructions: src1[0] = 0xF000 | ((((u32)dst - (u32)src1 - 4) & (0xFFF << 11)) >> 12); diff --git a/source/patches.h b/source/patches.h index 24e82bb..8b6ccae 100644 --- a/source/patches.h +++ b/source/patches.h @@ -54,7 +54,7 @@ void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); void patchFirmWrites(u8 *pos, u32 size); -void patchFirmWriteSafe(u8 *pos, u32 size); +void patchOldFirmWrites(u8 *pos, u32 size); void reimplementSvcBackdoor(u8 *pos, u32 size); void implementSvcGetCFWInfo(u8 *pos, u32 size); void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); diff --git a/source/pin.c b/source/pin.c index aac0d41..10209fd 100644 --- a/source/pin.c +++ b/source/pin.c @@ -47,7 +47,7 @@ bool readPin(PINData *out) computePINHash(tmp, zeroes, 1); - return memcmp(out->testHash, tmp, 32) == 0; //test vector verification (SD card has (or hasn't) been used on another console) + return memcmp(out->testHash, tmp, 32) == 0; //Test vector verification (SD card has, or hasn't been used on another console) } static inline char PINKeyToLetter(u32 pressed) @@ -66,8 +66,8 @@ void newPin(void) drawString("Enter your NEW PIN: ", 10, 10, COLOR_WHITE); - // Set the default value as 0x00 so we can check if there are any unentered characters. - u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; // pad to AES block length + //Pad to AES block length with zeroes + u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; u32 cnt = 0; int charDrawPos = 20 * SPACING_X; @@ -84,10 +84,11 @@ void newPin(void) pressed &= PIN_BUTTONS & ~BUTTON_START; if(!pressed) continue; - char key = PINKeyToLetter(pressed); - enteredPassword[cnt++] = (u8)key; // add character to password. - // visualize character on screen. + char key = PINKeyToLetter(pressed); + enteredPassword[cnt++] = (u8)key; //Add character to password + + //Visualize character on screen drawCharacter(key, 10 + charDrawPos, 10, COLOR_WHITE); charDrawPos += 2 * SPACING_X; } @@ -123,7 +124,7 @@ void verifyPin(PINData *in) drawString("Press START to shutdown or enter pin to proceed.", 10, 10, COLOR_WHITE); drawString("Pin: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); - // Set the default characters as 0x00 so we can check if there are any unentered characters. + //Pad to AES block length with zeroes u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; u32 cnt = 0; @@ -145,9 +146,9 @@ void verifyPin(PINData *in) if(!pressed) continue; char key = PINKeyToLetter(pressed); - enteredPassword[cnt++] = (u8)key; // add character to password. + enteredPassword[cnt++] = (u8)key; //Add character to password - // visualize character on screen. + //Visualize character on screen drawCharacter(key, 10 + charDrawPos, 10 + 2 * SPACING_Y, COLOR_WHITE); charDrawPos += 2 * SPACING_X; diff --git a/source/types.h b/source/types.h index a6946d5..223d38c 100644 --- a/source/types.h +++ b/source/types.h @@ -49,5 +49,6 @@ typedef enum FirmwareType NATIVE_FIRM = 0, TWL_FIRM = 1, AGB_FIRM = 2, - SAFE_FIRM = 3 + SAFE_FIRM = 3, + NATIVE_FIRM2X = 4 } FirmwareType; \ No newline at end of file From 3f8ad17e86ffae1a99308f6741bc159d4948a966 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 14:59:33 +0200 Subject: [PATCH 09/20] Minor PIN cleanup and UI changes --- source/pin.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/pin.c b/source/pin.c index 10209fd..98718f7 100644 --- a/source/pin.c +++ b/source/pin.c @@ -64,13 +64,14 @@ void newPin(void) { clearScreens(); - drawString("Enter your NEW PIN: ", 10, 10, COLOR_WHITE); + drawString("Enter a new PIN to proceed", 10, 10, COLOR_TITLE); + drawString("PIN: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); //Pad to AES block length with zeroes u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; u32 cnt = 0; - int charDrawPos = 20 * SPACING_X; + int charDrawPos = 5 * SPACING_X; while(cnt < PIN_LENGTH) { @@ -89,7 +90,7 @@ void newPin(void) enteredPassword[cnt++] = (u8)key; //Add character to password //Visualize character on screen - drawCharacter(key, 10 + charDrawPos, 10, COLOR_WHITE); + drawCharacter(key, 10 + charDrawPos, 10 + 2 * SPACING_Y, COLOR_WHITE); charDrawPos += 2 * SPACING_X; } @@ -121,9 +122,6 @@ void verifyPin(PINData *in) { initScreens(); - drawString("Press START to shutdown or enter pin to proceed.", 10, 10, COLOR_WHITE); - drawString("Pin: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); - //Pad to AES block length with zeroes u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; @@ -133,6 +131,9 @@ void verifyPin(PINData *in) while(!unlock) { + drawString("Press START to shutdown or enter PIN to proceed", 10, 10, COLOR_TITLE); + drawString("PIN: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); + u32 pressed; do { @@ -143,6 +144,7 @@ void verifyPin(PINData *in) if(pressed & BUTTON_START) mcuPowerOff(); pressed &= PIN_BUTTONS & ~BUTTON_START; + if(!pressed) continue; char key = PINKeyToLetter(pressed); @@ -166,9 +168,7 @@ void verifyPin(PINData *in) clearScreens(); - drawString("Press START to shutdown or enter pin to proceed.", 10, 10, COLOR_WHITE); - drawString("Pin: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); - drawString("Wrong pin! Try again!", 10, 10 + 3 * SPACING_Y, COLOR_RED); + drawString("Wrong PIN, try again", 10, 10 + 4 * SPACING_Y, COLOR_RED); } } } From 92328c6a7e3c7612b1a1f4bd3043e8c4ab4ec64e Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 15:50:11 +0200 Subject: [PATCH 10/20] Made it easier to change your PIN, added PIN file deletion when needed --- source/config.c | 10 ++++++++-- source/config.h | 2 +- source/firm.c | 6 +----- source/fs.c | 5 +++++ source/fs.h | 1 + source/pin.c | 17 ++++++++--------- source/pin.h | 2 +- 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/source/config.c b/source/config.c index a5f7c5c..b0fed6a 100644 --- a/source/config.c +++ b/source/config.c @@ -27,6 +27,7 @@ #include "screen.h" #include "draw.h" #include "buttons.h" +#include "pin.h" bool readConfig(const char *configPath) { @@ -64,7 +65,7 @@ void writeConfig(const char *configPath, u32 configTemp) } } -void configMenu(void) +void configMenu(bool oldPinStatus) { initScreens(); @@ -231,6 +232,11 @@ void configMenu(void) for(u32 i = 0; i < singleOptionsAmount; i++) configData.config |= (singleOptions[i].enabled ? 1 : 0) << (i + 16); + if(CONFIG(8)) newPin(oldPinStatus); + else if(oldPinStatus) fileDelete("/luma/pin.bin"); + //Wait for the pressed buttons to change - while(HID_PAD == BUTTON_START); + while(HID_PAD & PIN_BUTTONS); + + chrono(2); } \ No newline at end of file diff --git a/source/config.h b/source/config.h index 899317a..96f558e 100644 --- a/source/config.h +++ b/source/config.h @@ -43,4 +43,4 @@ extern cfgData configData; bool readConfig(const char *configPath); void writeConfig(const char *configPath, u32 configTemp); -void configMenu(void); \ No newline at end of file +void configMenu(bool oldPinStatus); \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index c6a120d..94da610 100755 --- a/source/firm.c +++ b/source/firm.c @@ -141,11 +141,7 @@ void main(void) if(shouldLoadConfigMenu) { - configMenu(); - - if(!pinExists && CONFIG(8)) newPin(); - - chrono(2); + configMenu(pinExists); //Update pressed buttons pressed = HID_PAD; diff --git a/source/fs.c b/source/fs.c index 59d1c0d..f318026 100644 --- a/source/fs.c +++ b/source/fs.c @@ -76,6 +76,11 @@ bool fileWrite(const void *buffer, const char *path, u32 size) return false; } +void fileDelete(const char *path) +{ + f_unlink(path); +} + void createDirectory(const char *path) { f_mkdir(path); diff --git a/source/fs.h b/source/fs.h index 805c099..7e7d9a9 100644 --- a/source/fs.h +++ b/source/fs.h @@ -32,6 +32,7 @@ void mountFs(void); u32 fileRead(void *dest, const char *path); u32 getFileSize(const char *path); bool fileWrite(const void *buffer, const char *path, u32 size); +void fileDelete(const char *path); void createDirectory(const char *path); void loadPayload(u32 pressed); u32 firmRead(void *dest, u32 firmType); \ No newline at end of file diff --git a/source/pin.c b/source/pin.c index 98718f7..a3b0479 100644 --- a/source/pin.c +++ b/source/pin.c @@ -60,11 +60,12 @@ static inline char PINKeyToLetter(u32 pressed) return keys[31 - i]; } -void newPin(void) +void newPin(bool allowSkipping) { clearScreens(); - drawString("Enter a new PIN to proceed", 10, 10, COLOR_TITLE); + char *title = allowSkipping ? "Press START to skip or enter a new PIN" : "Enter a new PIN to proceed"; + drawString(title, 10, 10, COLOR_TITLE); drawString("PIN: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); //Pad to AES block length with zeroes @@ -80,10 +81,12 @@ void newPin(void) { pressed = waitInput(); } - while(!(pressed & PIN_BUTTONS & ~BUTTON_START)); + while(!(pressed & PIN_BUTTONS)); - pressed &= PIN_BUTTONS & ~BUTTON_START; + pressed &= PIN_BUTTONS; + if(!allowSkipping) pressed &= ~BUTTON_START; + if(pressed & BUTTON_START) return; if(!pressed) continue; char key = PINKeyToLetter(pressed); @@ -114,8 +117,6 @@ void newPin(void) if(!fileWrite(&pin, "/luma/pin.bin", sizeof(PINData))) error("Error writing the PIN file"); } - - while(HID_PAD & PIN_BUTTONS); } void verifyPin(PINData *in) @@ -143,9 +144,7 @@ void verifyPin(PINData *in) if(pressed & BUTTON_START) mcuPowerOff(); - pressed &= PIN_BUTTONS & ~BUTTON_START; - - if(!pressed) continue; + pressed &= PIN_BUTTONS; char key = PINKeyToLetter(pressed); enteredPassword[cnt++] = (u8)key; //Add character to password diff --git a/source/pin.h b/source/pin.h index ce6f370..79b1dd2 100644 --- a/source/pin.h +++ b/source/pin.h @@ -44,5 +44,5 @@ typedef struct __attribute__((packed)) } PINData; bool readPin(PINData* out); -void newPin(void); +void newPin(bool allowSkipping); void verifyPin(PINData *in); \ No newline at end of file From e2d828a4a2ba79171fd94bd8c91e5ba749b6f3c7 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 15:58:10 +0200 Subject: [PATCH 11/20] Fixed derp --- source/pin.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/pin.c b/source/pin.c index a3b0479..030efc4 100644 --- a/source/pin.c +++ b/source/pin.c @@ -146,6 +146,8 @@ void verifyPin(PINData *in) pressed &= PIN_BUTTONS; + if(!pressed) continue; + char key = PINKeyToLetter(pressed); enteredPassword[cnt++] = (u8)key; //Add character to password From 82699f3e00b9ab70390773272e15014585ac9769 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 28 Aug 2016 23:41:41 +0200 Subject: [PATCH 12/20] Merge readPin and verifyPin --- source/crypto.c | 4 ++-- source/crypto.h | 6 ++---- source/firm.c | 7 +------ source/pin.c | 52 ++++++++++++++++++++++++------------------------- source/pin.h | 3 +-- 5 files changed, 32 insertions(+), 40 deletions(-) diff --git a/source/crypto.c b/source/crypto.c index 7014027..e6a4751 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -457,13 +457,13 @@ void arm9Loader(u8 *arm9Section) } } -void computePINHash(u8 out[32], u8 *in, u32 blockCount) +void computePinHash(u8 *out, u8 *in, u32 blockCount) { u8 __attribute__((aligned(4))) cid[0x10]; u8 __attribute__((aligned(4))) cipherText[0x10]; sdmmc_get_cid(1, (u32 *)cid); - aes_use_keyslot(4); // console-unique keyslot which keys are set by the Arm9 bootROM + aes_use_keyslot(4); //Console-unique keyslot whose keys are set by the ARM9 bootROM aes(cipherText, in, blockCount, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); sha(out, cipherText, 0x10, SHA_256_MODE); diff --git a/source/crypto.h b/source/crypto.h index 0b30bf9..c7221c8 100755 --- a/source/crypto.h +++ b/source/crypto.h @@ -100,8 +100,7 @@ #define SHA_1_HASH_SIZE (160 / 8) extern u32 emuOffset; -extern bool isN3DS; -extern bool isDevUnit; +extern bool isN3DS, isDevUnit; extern FirmwareSource firmSource; void ctrNandInit(void); @@ -109,5 +108,4 @@ u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); void setRSAMod0DerivedKeys(void); void decryptExeFs(u8 *inbuf); void arm9Loader(u8 *arm9Section); - -void computePINHash(u8 out[32], u8 *in, u32 blockCount); \ No newline at end of file +void computePinHash(u8 *out, u8 *in, u32 blockCount); \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index 94da610..ce51dac 100755 --- a/source/firm.c +++ b/source/firm.c @@ -129,12 +129,7 @@ void main(void) //Boot options aren't being forced if(needConfig != DONT_CONFIGURE) { - PINData pin; - - bool pinExists = CONFIG(8) && readPin(&pin); - - //If we get here we should check the PIN (if it exists) in all cases - if(pinExists) verifyPin(&pin); + bool pinExists = CONFIG(8) && verifyPin(); //If no configuration file exists or SELECT is held, load configuration menu bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)); diff --git a/source/pin.c b/source/pin.c index 030efc4..1ea64e8 100644 --- a/source/pin.c +++ b/source/pin.c @@ -34,23 +34,7 @@ #include "pin.h" #include "crypto.h" -bool readPin(PINData *out) -{ - if(fileRead(out, "/luma/pin.bin") != sizeof(PINData) || - memcmp(out->magic, "PINF", 4) != 0 || - out->formatVersionMajor != PIN_VERSIONMAJOR || - out->formatVersionMinor != PIN_VERSIONMINOR) - return false; - - u8 __attribute__((aligned(4))) zeroes[16] = {0}; - u8 __attribute__((aligned(4))) tmp[32]; - - computePINHash(tmp, zeroes, 1); - - return memcmp(out->testHash, tmp, 32) == 0; //Test vector verification (SD card has, or hasn't been used on another console) -} - -static inline char PINKeyToLetter(u32 pressed) +static char pinKeyToLetter(u32 pressed) { const char keys[] = "AB--------XY"; @@ -89,7 +73,7 @@ void newPin(bool allowSkipping) if(pressed & BUTTON_START) return; if(!pressed) continue; - char key = PINKeyToLetter(pressed); + char key = pinKeyToLetter(pressed); enteredPassword[cnt++] = (u8)key; //Add character to password //Visualize character on screen @@ -105,10 +89,10 @@ void newPin(bool allowSkipping) pin.formatVersionMajor = PIN_VERSIONMAJOR; pin.formatVersionMinor = PIN_VERSIONMINOR; - computePINHash(tmp, zeroes, 1); + computePinHash(tmp, zeroes, 1); memcpy(pin.testHash, tmp, 32); - computePINHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16); + computePinHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16); memcpy(pin.hash, tmp, 32); if(!fileWrite(&pin, "/luma/pin.bin", sizeof(PINData))) @@ -119,10 +103,26 @@ void newPin(bool allowSkipping) } } -void verifyPin(PINData *in) +bool verifyPin(void) { initScreens(); + PINData pin; + + if(fileRead(&pin, "/luma/pin.bin") != sizeof(PINData) || + memcmp(pin.magic, "PINF", 4) != 0 || + pin.formatVersionMajor != PIN_VERSIONMAJOR || + pin.formatVersionMinor != PIN_VERSIONMINOR) + return false; + + u8 __attribute__((aligned(4))) zeroes[16] = {0}; + u8 __attribute__((aligned(4))) tmp[32]; + + computePinHash(tmp, zeroes, 1); + + //Test vector verification (SD card has, or hasn't been used on another console) + if(memcmp(pin.testHash, tmp, 32) != 0) return false; + //Pad to AES block length with zeroes u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; @@ -148,7 +148,7 @@ void verifyPin(PINData *in) if(!pressed) continue; - char key = PINKeyToLetter(pressed); + char key = pinKeyToLetter(pressed); enteredPassword[cnt++] = (u8)key; //Add character to password //Visualize character on screen @@ -157,10 +157,8 @@ void verifyPin(PINData *in) if(cnt >= PIN_LENGTH) { - u8 __attribute__((aligned(4))) tmp[32]; - - computePINHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16); - unlock = memcmp(in->hash, tmp, 32) == 0; + computePinHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16); + unlock = memcmp(pin.hash, tmp, 32) == 0; if(!unlock) { @@ -173,4 +171,6 @@ void verifyPin(PINData *in) } } } + + return true; } \ No newline at end of file diff --git a/source/pin.h b/source/pin.h index 79b1dd2..b8aa6de 100644 --- a/source/pin.h +++ b/source/pin.h @@ -43,6 +43,5 @@ typedef struct __attribute__((packed)) u8 hash[32]; } PINData; -bool readPin(PINData* out); void newPin(bool allowSkipping); -void verifyPin(PINData *in); \ No newline at end of file +bool verifyPin(void); \ No newline at end of file From c96f96258f4609e9b6dc0674a0ff43e6f096ade0 Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 29 Aug 2016 01:57:42 +0200 Subject: [PATCH 13/20] Only patch 2.x NATIVE_FIRM on A9LH --- source/firm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/firm.c b/source/firm.c index ce51dac..3fb9439 100755 --- a/source/firm.c +++ b/source/firm.c @@ -213,7 +213,7 @@ void main(void) break; case SAFE_FIRM: case NATIVE_FIRM2X: - patch2xNativeAndSafeFirm(); + if(isA9lh) patch2xNativeAndSafeFirm(); break; default: //Skip patching on unsupported O3DS AGB/TWL FIRMs From ad9e00acaab08331fbd4b349fc9b15774c0b2647 Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 29 Aug 2016 13:45:57 +0200 Subject: [PATCH 14/20] Add delay if a PIN was just verified and SAFE_MODE is being booted --- source/firm.c | 13 ++++++++++--- source/start.s | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/source/firm.c b/source/firm.c index 3fb9439..61c3ea0 100755 --- a/source/firm.c +++ b/source/firm.c @@ -35,7 +35,7 @@ #include "pin.h" #include "../build/injector.h" -extern u16 launchedFirmTIDLow[8]; //Defined in start.s +extern u16 launchedFirmTidLow[8]; //Defined in start.s static firmHeader *const firm = (firmHeader *)0x24000000; static const firmSectionHeader *section; @@ -75,14 +75,14 @@ void main(void) needConfig = readConfig(configPath) ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION; //Determine if this is a firmlaunch boot - if(launchedFirmTIDLow[5] != 0) + if(launchedFirmTidLow[5] != 0) { if(needConfig == CREATE_CONFIGURATION) mcuReboot(); isFirmlaunch = true; //'0' = NATIVE_FIRM, '1' = TWL_FIRM, '2' = AGB_FIRM - firmType = launchedFirmTIDLow[7] == u'3' ? SAFE_FIRM : (FirmwareType)(launchedFirmTIDLow[5] - u'0'); + firmType = launchedFirmTidLow[7] == u'3' ? SAFE_FIRM : (FirmwareType)(launchedFirmTidLow[5] - u'0'); nandType = (FirmwareSource)BOOTCONFIG(0, 3); firmSource = (FirmwareSource)BOOTCONFIG(2, 1); @@ -149,6 +149,13 @@ void main(void) //Flag to tell loader to init SD configTemp |= 1 << 5; + + //If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo + if(pinExists && !shouldLoadConfigMenu) + { + while(HID_PAD & PIN_BUTTONS); + chrono(2); + } } else { diff --git a/source/start.s b/source/start.s index f0f7f3c..3a5b4df 100644 --- a/source/start.s +++ b/source/start.s @@ -26,8 +26,8 @@ _start: b start -.global launchedFirmTIDLow -launchedFirmTIDLow: +.global launchedFirmTidLow +launchedFirmTidLow: .hword 0, 0, 0, 0, 0, 0, 0, 0 start: From 8209433696d55da267fa682414a9aa40bbab11e3 Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 29 Aug 2016 15:35:24 +0200 Subject: [PATCH 15/20] Cleanup and refactoring --- source/emunand.c | 40 ++++++++--------- source/emunand.h | 6 ++- source/fatfs/sdmmc/common.h | 1 - source/firm.c | 14 +++--- source/patches.c | 87 +++++++++++++++---------------------- source/patches.h | 5 ++- 6 files changed, 70 insertions(+), 83 deletions(-) diff --git a/source/emunand.c b/source/emunand.c index 2b6f02c..0115a1c 100644 --- a/source/emunand.c +++ b/source/emunand.c @@ -25,12 +25,12 @@ #include "fatfs/sdmmc/sdmmc.h" #include "../build/emunandpatch.h" -void locateEmuNAND(u32 *off, u32 *head, FirmwareSource *emuNAND) +void locateEmuNand(u32 *off, u32 *head, FirmwareSource *emuNand) { static u8 temp[0x200]; const u32 nandSize = getMMCDevice(0)->total_size; - u32 nandOffset = *emuNAND == FIRMWARE_EMUNAND ? 0 : + u32 nandOffset = *emuNand == FIRMWARE_EMUNAND ? 0 : (nandSize > 0x200000 ? 0x400000 : 0x200000); //Check for RedNAND @@ -53,12 +53,12 @@ void locateEmuNAND(u32 *off, u32 *head, FirmwareSource *emuNAND) or to SysNAND if there isn't any */ else { - *emuNAND = (*emuNAND == FIRMWARE_EMUNAND2) ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND; - if(*emuNAND) locateEmuNAND(off, head, emuNAND); + *emuNand = (*emuNand == FIRMWARE_EMUNAND2) ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND; + if(*emuNand) locateEmuNand(off, head, emuNand); } } -static inline void *getEmuCode(u8 *pos, u32 size) +static inline void *getFreeK9Space(u8 *pos, u32 size) { const u8 pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}; @@ -66,7 +66,7 @@ static inline void *getEmuCode(u8 *pos, u32 size) return memsearch(pos + 0x13500, pattern, size - 0x13500, 6) + 0x455; } -static inline u32 getSDMMC(u8 *pos, u32 size) +static inline u32 getSdmmc(u8 *pos, u32 size) { //Look for struct code const u8 pattern[] = {0x21, 0x20, 0x18, 0x20}; @@ -75,7 +75,7 @@ static inline u32 getSDMMC(u8 *pos, u32 size) return *(u32 *)(off + 9) + *(u32 *)(off + 0xD); } -static inline void patchNANDRW(u8 *pos, u32 size, u32 branchOffset) +static inline void patchNandRw(u8 *pos, u32 size, u32 branchOffset) { const u16 nandRedir[2] = {0x4C00, 0x47A0}; @@ -93,7 +93,7 @@ static inline void patchNANDRW(u8 *pos, u32 size, u32 branchOffset) ((u32 *)writeOffset)[1] = branchOffset; } -static inline void patchMPU(u8 *pos, u32 size) +static inline void patchMpu(u8 *pos, u32 size) { const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603}; @@ -107,26 +107,26 @@ static inline void patchMPU(u8 *pos, u32 size) off[9] = mpuPatch[2]; } -void patchEmuNAND(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuOffset, u32 emuHeader, u32 branchAdditive) +void patchEmuNand(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuHeader, u32 branchAdditive) { //Copy emuNAND code - void *emuCodeOffset = getEmuCode(arm9Section, arm9SectionSize); - memcpy(emuCodeOffset, emunand, emunand_size); + void *freeK9Space = getFreeK9Space(arm9Section, arm9SectionSize); + memcpy(freeK9Space, emunand, emunand_size); //Add the data of the found emuNAND - u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4), - *pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4); - *pos_offset = emuOffset; - *pos_header = emuHeader; + u32 *posOffset = (u32 *)memsearch(freeK9Space, "NAND", emunand_size, 4), + *posHeader = (u32 *)memsearch(freeK9Space, "NCSD", emunand_size, 4); + *posOffset = emuOffset; + *posHeader = emuHeader; //Find and add the SDMMC struct - u32 *pos_sdmmc = (u32 *)memsearch(emuCodeOffset, "SDMC", emunand_size, 4); - *pos_sdmmc = getSDMMC(process9Offset, process9Size); + u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_size, 4); + *posSdmmc = getSdmmc(process9Offset, process9Size); //Add emuNAND hooks - u32 branchOffset = (u32)emuCodeOffset - branchAdditive; - patchNANDRW(process9Offset, process9Size, branchOffset); + u32 branchOffset = (u32)freeK9Space - branchAdditive; + patchNandRw(process9Offset, process9Size, branchOffset); //Set MPU for emu code region - patchMPU(arm9Section, arm9SectionSize); + patchMpu(arm9Section, arm9SectionSize); } \ No newline at end of file diff --git a/source/emunand.h b/source/emunand.h index 1930c34..543fbe0 100644 --- a/source/emunand.h +++ b/source/emunand.h @@ -26,5 +26,7 @@ #define NCSD_MAGIC 0x4453434E -void locateEmuNAND(u32 *off, u32 *head, FirmwareSource *emuNAND); -void patchEmuNAND(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuOffset, u32 emuHeader, u32 branchAdditive); \ No newline at end of file +extern u32 emuOffset; + +void locateEmuNand(u32 *off, u32 *head, FirmwareSource *emuNand); +void patchEmuNand(u8 *arm9Section, u32 arm9SectionSize, u8 *process9Offset, u32 process9Size, u32 emuHeader, u32 branchAdditive); \ No newline at end of file diff --git a/source/fatfs/sdmmc/common.h b/source/fatfs/sdmmc/common.h index 90a327e..3b77ae6 100644 --- a/source/fatfs/sdmmc/common.h +++ b/source/fatfs/sdmmc/common.h @@ -1,4 +1,3 @@ #pragma once -#include #include "../../types.h" \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index 61c3ea0..fe7629f 100755 --- a/source/firm.c +++ b/source/firm.c @@ -197,13 +197,13 @@ void main(void) //If we need to boot emuNAND, make sure it exists if(nandType != FIRMWARE_SYSNAND) { - locateEmuNAND(&emuOffset, &emuHeader, &nandType); + locateEmuNand(&emuOffset, &emuHeader, &nandType); if(nandType == FIRMWARE_SYSNAND) firmSource = FIRMWARE_SYSNAND; } //Same if we're using emuNAND as the FIRM source else if(firmSource != FIRMWARE_SYSNAND) - locateEmuNAND(&emuOffset, &emuHeader, &firmSource); + locateEmuNand(&emuOffset, &emuHeader, &firmSource); if(!isFirmlaunch) { @@ -287,6 +287,10 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 process9MemAddr; u8 *process9Offset = getProcess9(arm9Section + 0x15000, section[2].size - 0x15000, &process9Size, &process9MemAddr); + //Find Kernel11 SVC table and free space locations + u8 *freeK11Space; + u32 *arm11SvcTable = getKernel11Info(arm11Section1, section[1].size, &freeK11Space); + //Apply signature patches patchSignatureChecks(process9Offset, process9Size); @@ -294,7 +298,7 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 if(nandType != FIRMWARE_SYSNAND) { u32 branchAdditive = (u32)firm + section[2].offset - (u32)section[2].address; - patchEmuNAND(arm9Section, section[2].size, process9Offset, process9Size, emuOffset, emuHeader, branchAdditive); + patchEmuNand(arm9Section, section[2].size, process9Offset, process9Size, emuHeader, branchAdditive); } //Apply FIRM0/1 writes patches on sysNAND to protect A9LH @@ -310,10 +314,10 @@ static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 patchTitleInstallMinVersionCheck(process9Offset, process9Size); //Restore svcBackdoor - reimplementSvcBackdoor(arm11Section1, section[1].size); + reimplementSvcBackdoor(arm11Section1, arm11SvcTable, &freeK11Space); } - implementSvcGetCFWInfo(arm11Section1, section[1].size); + implementSvcGetCFWInfo(arm11Section1, arm11SvcTable, &freeK11Space); } static inline void patchLegacyFirm(FirmwareType firmType) diff --git a/source/patches.c b/source/patches.c index 6bfc7b8..4cb4ef3 100644 --- a/source/patches.c +++ b/source/patches.c @@ -27,33 +27,6 @@ #include "../build/svcGetCFWInfopatch.h" #include "../build/twl_k11modulespatch.h" -static u32 *arm11SvcTable = NULL; - -static u8 *freeK11Space = NULL; - -static void findArm11SvcTable(u8 *pos, u32 size) -{ - if(arm11SvcTable == NULL) - { - const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; - - u32 *arm11ExceptionsPage = (u32 *)memsearch(pos, pattern, size, 4) - 0xB; - u32 svcOffset = (-((arm11ExceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch - arm11SvcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address - while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL) - } -} - -static void findFreeK11Space(u8 *pos, u32 size) -{ - if(freeK11Space == NULL) - { - const u8 pattern[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - - freeK11Space = memsearch(pos, pattern, size, 5) + 1; - } -} - u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) { u8 *off = memsearch(pos, "ess9", size, 4); @@ -65,6 +38,22 @@ u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) return off - 0x204 + (*(u32 *)(off - 0x64) * 0x200) + 0x200; } +u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space) +{ + const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; + + u32 *arm11ExceptionsPage = (u32 *)memsearch(pos, pattern, size, 4) - 0xB; + u32 svcOffset = (-((arm11ExceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch + u32 *arm11SvcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address + while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL) + + const u8 pattern2[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + *freeK11Space = memsearch(pos, pattern2, size, 5) + 1; + + return arm11SvcTable; +} + void patchSignatureChecks(u8 *pos, u32 size) { const u16 sigPatch[2] = {0x2000, 0x4770}; @@ -126,40 +115,34 @@ void patchOldFirmWrites(u8 *pos, u32 size) off[1] = writeBlockOld[1]; } -void reimplementSvcBackdoor(u8 *pos, u32 size) +void reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space) { //Official implementation of svcBackdoor const u8 svcBackdoor[40] = {0xFF, 0x10, 0xCD, 0xE3, //bic r1, sp, #0xff - 0x0F, 0x1C, 0x81, 0xE3, //orr r1, r1, #0xf00 - 0x28, 0x10, 0x81, 0xE2, //add r1, r1, #0x28 - 0x00, 0x20, 0x91, 0xE5, //ldr r2, [r1] - 0x00, 0x60, 0x22, 0xE9, //stmdb r2!, {sp, lr} - 0x02, 0xD0, 0xA0, 0xE1, //mov sp, r2 - 0x30, 0xFF, 0x2F, 0xE1, //blx r0 - 0x03, 0x00, 0xBD, 0xE8, //pop {r0, r1} - 0x00, 0xD0, 0xA0, 0xE1, //mov sp, r0 - 0x11, 0xFF, 0x2F, 0xE1}; //bx r1 - - findArm11SvcTable(pos, size); + 0x0F, 0x1C, 0x81, 0xE3, //orr r1, r1, #0xf00 + 0x28, 0x10, 0x81, 0xE2, //add r1, r1, #0x28 + 0x00, 0x20, 0x91, 0xE5, //ldr r2, [r1] + 0x00, 0x60, 0x22, 0xE9, //stmdb r2!, {sp, lr} + 0x02, 0xD0, 0xA0, 0xE1, //mov sp, r2 + 0x30, 0xFF, 0x2F, 0xE1, //blx r0 + 0x03, 0x00, 0xBD, 0xE8, //pop {r0, r1} + 0x00, 0xD0, 0xA0, 0xE1, //mov sp, r0 + 0x11, 0xFF, 0x2F, 0xE1}; //bx r1 if(!arm11SvcTable[0x7B]) { - findFreeK11Space(pos, size); + memcpy(*freeK11Space, svcBackdoor, 40); - memcpy(freeK11Space, svcBackdoor, 40); - - arm11SvcTable[0x7B] = 0xFFF00000 + freeK11Space - pos; - freeK11Space += 40; + arm11SvcTable[0x7B] = 0xFFF00000 + *freeK11Space - pos; + (*freeK11Space) += 40; } } -void implementSvcGetCFWInfo(u8 *pos, u32 size) +void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space) { - findFreeK11Space(pos, size); - - memcpy(freeK11Space, svcGetCFWInfo, svcGetCFWInfo_size); + memcpy(*freeK11Space, svcGetCFWInfo, svcGetCFWInfo_size); - CFWInfo *info = (CFWInfo *)memsearch(freeK11Space, "LUMA", svcGetCFWInfo_size, 4); + CFWInfo *info = (CFWInfo *)memsearch(*freeK11Space, "LUMA", svcGetCFWInfo_size, 4); const char *rev = REVISION; bool isRelease; @@ -177,10 +160,8 @@ void implementSvcGetCFWInfo(u8 *pos, u32 size) info->flags = 0 /* master branch */ | ((isRelease ? 1 : 0) << 1) /* is release */; - findArm11SvcTable(pos, size); - - arm11SvcTable[0x2E] = 0xFFF00000 + freeK11Space - pos; //Stubbed svc - freeK11Space += svcGetCFWInfo_size; + arm11SvcTable[0x2E] = 0xFFF00000 + *freeK11Space - pos; //Stubbed svc + (*freeK11Space) += svcGetCFWInfo_size; } void patchTitleInstallMinVersionCheck(u8 *pos, u32 size) diff --git a/source/patches.h b/source/patches.h index 8b6ccae..65a0e7b 100644 --- a/source/patches.h +++ b/source/patches.h @@ -50,12 +50,13 @@ typedef struct __attribute__((packed)) extern bool isN3DS; u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr); +u32 *getKernel11Info(u8 *pos, u32 size, u8 **freeK11Space); void patchSignatureChecks(u8 *pos, u32 size); void patchTitleInstallMinVersionCheck(u8 *pos, u32 size); void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr); void patchFirmWrites(u8 *pos, u32 size); void patchOldFirmWrites(u8 *pos, u32 size); -void reimplementSvcBackdoor(u8 *pos, u32 size); -void implementSvcGetCFWInfo(u8 *pos, u32 size); +void reimplementSvcBackdoor(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space); +void implementSvcGetCFWInfo(u8 *pos, u32 *arm11SvcTable, u8 **freeK11Space); void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType); void patchTwlBg(u8 *pos); \ No newline at end of file From 18bd4bbcf6c451b7b6bcb071e5894f4ec7330378 Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 29 Aug 2016 15:57:32 +0200 Subject: [PATCH 16/20] Skip PIN verification after a MCU reboot on A9LH --- source/firm.c | 2 +- source/pin.c | 81 ++++++++++++++++++++++++++------------------------- source/pin.h | 2 +- 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/source/firm.c b/source/firm.c index fe7629f..952dd0d 100755 --- a/source/firm.c +++ b/source/firm.c @@ -129,7 +129,7 @@ void main(void) //Boot options aren't being forced if(needConfig != DONT_CONFIGURE) { - bool pinExists = CONFIG(8) && verifyPin(); + bool pinExists = CONFIG(8) && verifyPin(isA9lh && CFG_BOOTENV); //If no configuration file exists or SELECT is held, load configuration menu bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)); diff --git a/source/pin.c b/source/pin.c index 1ea64e8..e64063c 100644 --- a/source/pin.c +++ b/source/pin.c @@ -103,7 +103,7 @@ void newPin(bool allowSkipping) } } -bool verifyPin(void) +bool verifyPin(bool skipVerification) { initScreens(); @@ -123,51 +123,54 @@ bool verifyPin(void) //Test vector verification (SD card has, or hasn't been used on another console) if(memcmp(pin.testHash, tmp, 32) != 0) return false; - //Pad to AES block length with zeroes - u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; - - u32 cnt = 0; - bool unlock = false; - int charDrawPos = 5 * SPACING_X; - - while(!unlock) + if(!skipVerification) { - drawString("Press START to shutdown or enter PIN to proceed", 10, 10, COLOR_TITLE); - drawString("PIN: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); + //Pad to AES block length with zeroes + u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; - u32 pressed; - do + u32 cnt = 0; + bool unlock = false; + int charDrawPos = 5 * SPACING_X; + + while(!unlock) { - pressed = waitInput(); - } - while(!(pressed & PIN_BUTTONS)); + drawString("Press START to shutdown or enter PIN to proceed", 10, 10, COLOR_TITLE); + drawString("PIN: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); - if(pressed & BUTTON_START) mcuPowerOff(); - - pressed &= PIN_BUTTONS; - - if(!pressed) continue; - - char key = pinKeyToLetter(pressed); - enteredPassword[cnt++] = (u8)key; //Add character to password - - //Visualize character on screen - drawCharacter(key, 10 + charDrawPos, 10 + 2 * SPACING_Y, COLOR_WHITE); - charDrawPos += 2 * SPACING_X; - - if(cnt >= PIN_LENGTH) - { - computePinHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16); - unlock = memcmp(pin.hash, tmp, 32) == 0; - - if(!unlock) + u32 pressed; + do { - charDrawPos = 5 * SPACING_X; - cnt = 0; + pressed = waitInput(); + } + while(!(pressed & PIN_BUTTONS)); - clearScreens(); + if(pressed & BUTTON_START) mcuPowerOff(); - drawString("Wrong PIN, try again", 10, 10 + 4 * SPACING_Y, COLOR_RED); + pressed &= PIN_BUTTONS; + + if(!pressed) continue; + + char key = pinKeyToLetter(pressed); + enteredPassword[cnt++] = (u8)key; //Add character to password + + //Visualize character on screen + drawCharacter(key, 10 + charDrawPos, 10 + 2 * SPACING_Y, COLOR_WHITE); + charDrawPos += 2 * SPACING_X; + + if(cnt >= PIN_LENGTH) + { + computePinHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16); + unlock = memcmp(pin.hash, tmp, 32) == 0; + + if(!unlock) + { + charDrawPos = 5 * SPACING_X; + cnt = 0; + + clearScreens(); + + drawString("Wrong PIN, try again", 10, 10 + 4 * SPACING_Y, COLOR_RED); + } } } } diff --git a/source/pin.h b/source/pin.h index b8aa6de..7aa6047 100644 --- a/source/pin.h +++ b/source/pin.h @@ -44,4 +44,4 @@ typedef struct __attribute__((packed)) } PINData; void newPin(bool allowSkipping); -bool verifyPin(void); \ No newline at end of file +bool verifyPin(bool skipVerification); \ No newline at end of file From 2ffe4a5451cec597626ca896d779fbcd18290cfb Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 29 Aug 2016 16:04:17 +0200 Subject: [PATCH 17/20] Revert "Skip PIN verification after a MCU reboot on A9LH" This reverts commit 18bd4bbcf6c451b7b6bcb071e5894f4ec7330378. --- source/firm.c | 2 +- source/pin.c | 81 +++++++++++++++++++++++++-------------------------- source/pin.h | 2 +- 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/source/firm.c b/source/firm.c index 952dd0d..fe7629f 100755 --- a/source/firm.c +++ b/source/firm.c @@ -129,7 +129,7 @@ void main(void) //Boot options aren't being forced if(needConfig != DONT_CONFIGURE) { - bool pinExists = CONFIG(8) && verifyPin(isA9lh && CFG_BOOTENV); + bool pinExists = CONFIG(8) && verifyPin(); //If no configuration file exists or SELECT is held, load configuration menu bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & BUTTON_SELECT) && !(pressed & BUTTON_L1)); diff --git a/source/pin.c b/source/pin.c index e64063c..1ea64e8 100644 --- a/source/pin.c +++ b/source/pin.c @@ -103,7 +103,7 @@ void newPin(bool allowSkipping) } } -bool verifyPin(bool skipVerification) +bool verifyPin(void) { initScreens(); @@ -123,54 +123,51 @@ bool verifyPin(bool skipVerification) //Test vector verification (SD card has, or hasn't been used on another console) if(memcmp(pin.testHash, tmp, 32) != 0) return false; - if(!skipVerification) + //Pad to AES block length with zeroes + u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; + + u32 cnt = 0; + bool unlock = false; + int charDrawPos = 5 * SPACING_X; + + while(!unlock) { - //Pad to AES block length with zeroes - u8 __attribute__((aligned(4))) enteredPassword[16 * ((PIN_LENGTH + 15) / 16)] = {0}; + drawString("Press START to shutdown or enter PIN to proceed", 10, 10, COLOR_TITLE); + drawString("PIN: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); - u32 cnt = 0; - bool unlock = false; - int charDrawPos = 5 * SPACING_X; - - while(!unlock) + u32 pressed; + do { - drawString("Press START to shutdown or enter PIN to proceed", 10, 10, COLOR_TITLE); - drawString("PIN: ", 10, 10 + 2 * SPACING_Y, COLOR_WHITE); + pressed = waitInput(); + } + while(!(pressed & PIN_BUTTONS)); - u32 pressed; - do + if(pressed & BUTTON_START) mcuPowerOff(); + + pressed &= PIN_BUTTONS; + + if(!pressed) continue; + + char key = pinKeyToLetter(pressed); + enteredPassword[cnt++] = (u8)key; //Add character to password + + //Visualize character on screen + drawCharacter(key, 10 + charDrawPos, 10 + 2 * SPACING_Y, COLOR_WHITE); + charDrawPos += 2 * SPACING_X; + + if(cnt >= PIN_LENGTH) + { + computePinHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16); + unlock = memcmp(pin.hash, tmp, 32) == 0; + + if(!unlock) { - pressed = waitInput(); - } - while(!(pressed & PIN_BUTTONS)); + charDrawPos = 5 * SPACING_X; + cnt = 0; - if(pressed & BUTTON_START) mcuPowerOff(); + clearScreens(); - pressed &= PIN_BUTTONS; - - if(!pressed) continue; - - char key = pinKeyToLetter(pressed); - enteredPassword[cnt++] = (u8)key; //Add character to password - - //Visualize character on screen - drawCharacter(key, 10 + charDrawPos, 10 + 2 * SPACING_Y, COLOR_WHITE); - charDrawPos += 2 * SPACING_X; - - if(cnt >= PIN_LENGTH) - { - computePinHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16); - unlock = memcmp(pin.hash, tmp, 32) == 0; - - if(!unlock) - { - charDrawPos = 5 * SPACING_X; - cnt = 0; - - clearScreens(); - - drawString("Wrong PIN, try again", 10, 10 + 4 * SPACING_Y, COLOR_RED); - } + drawString("Wrong PIN, try again", 10, 10 + 4 * SPACING_Y, COLOR_RED); } } } diff --git a/source/pin.h b/source/pin.h index 7aa6047..b8aa6de 100644 --- a/source/pin.h +++ b/source/pin.h @@ -44,4 +44,4 @@ typedef struct __attribute__((packed)) } PINData; void newPin(bool allowSkipping); -bool verifyPin(bool skipVerification); \ No newline at end of file +bool verifyPin(void); \ No newline at end of file From 46227e6763e29dd38f4e13a47018a60b7d86d5d9 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Mon, 29 Aug 2016 17:51:03 +0200 Subject: [PATCH 18/20] Fix build issues on some environments. --- injector/Makefile | 7 ++++++- injector/source/CFWInfo.h | 19 +++++++++++++++++++ injector/source/CFWInfo.s | 9 +++++++++ injector/source/patcher.c | 6 +----- injector/source/patcher.h | 14 -------------- 5 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 injector/source/CFWInfo.h create mode 100644 injector/source/CFWInfo.s diff --git a/injector/Makefile b/injector/Makefile index d568a73..1e96f56 100755 --- a/injector/Makefile +++ b/injector/Makefile @@ -28,7 +28,7 @@ CFLAGS := -Wall -Wextra -MMD -MP -marm $(ARCH) -fno-builtin -std=c11 -O2 -flto - LDFLAGS := -Xlinker --defsym="__start__=0x14000000" -specs=3dsx.specs $(ARCH) objects = $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ - $(call rwildcard, $(dir_source), *.c)) + $(call rwildcard, $(dir_source), *.s *.c)) .PHONY: all all: ../$(dir_build)/$(name).cxi @@ -48,4 +48,9 @@ $(dir_build)/memory.o : CFLAGS += -O3 $(dir_build)/%.o: $(dir_source)/%.c @mkdir -p "$(@D)" $(COMPILE.c) $(OUTPUT_OPTION) $< + +$(dir_build)/%.o: $(dir_source)/%.s + @mkdir -p "$(@D)" + $(COMPILE.c) $(OUTPUT_OPTION) $< + include $(call rwildcard, $(dir_build), *.d) diff --git a/injector/source/CFWInfo.h b/injector/source/CFWInfo.h new file mode 100644 index 0000000..0e9d63f --- /dev/null +++ b/injector/source/CFWInfo.h @@ -0,0 +1,19 @@ +#pragma once + +#include <3ds.h> + +typedef struct __attribute__((packed)) +{ + char magic[4]; + + u8 versionMajor; + u8 versionMinor; + u8 versionBuild; + u8 flags; /* bit 0: dev branch; bit 1: is release */ + + u32 commitHash; + + u32 config; +} CFWInfo; + +int svcGetCFWInfo(CFWInfo *info); \ No newline at end of file diff --git a/injector/source/CFWInfo.s b/injector/source/CFWInfo.s new file mode 100644 index 0000000..8337620 --- /dev/null +++ b/injector/source/CFWInfo.s @@ -0,0 +1,9 @@ +.text +.arm +.align 4 + +.global svcGetCFWInfo +.type svcGetCFWInfo, %function +svcGetCFWInfo: + svc 0x2e + bx lr diff --git a/injector/source/patcher.c b/injector/source/patcher.c index 362230d..3e8af05 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -2,6 +2,7 @@ #include "memory.h" #include "patcher.h" #include "ifile.h" +#include "CFWInfo.h" static CFWInfo info; @@ -85,11 +86,6 @@ static int fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int f return IFile_Open(file, archiveId, archivePath, filePath, flags); } -int __attribute__((naked)) svcGetCFWInfo(CFWInfo __attribute__((unused)) *out) -{ - __asm__ volatile("svc 0x2E; bx lr"); -} - static void loadCFWInfo(void) { static bool infoLoaded = false; diff --git a/injector/source/patcher.h b/injector/source/patcher.h index ea3ea5e..e67e9e6 100644 --- a/injector/source/patcher.h +++ b/injector/source/patcher.h @@ -8,18 +8,4 @@ #define MULTICONFIG(a) ((info.config >> (a * 2 + 6)) & 3) #define BOOTCONFIG(a, b) ((info.config >> a) & b) -typedef struct __attribute__((packed)) -{ - char magic[4]; - - u8 versionMajor; - u8 versionMinor; - u8 versionBuild; - u8 flags; /* bit 0: dev branch; bit 1: is release */ - - u32 commitHash; - - u32 config; -} CFWInfo; - void patchCode(u64 progId, u8 *code, u32 size); \ No newline at end of file From abf7c8e565bec97310bad0df434e4806f8891d42 Mon Sep 17 00:00:00 2001 From: Aurora Date: Mon, 29 Aug 2016 18:11:59 +0200 Subject: [PATCH 19/20] Replace pinKeyToLetter with a C implementation, minor cleanup --- injector/Makefile | 9 ++++----- injector/source/CFWInfo.h | 2 -- source/patches.c | 2 +- source/pin.c | 2 +- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/injector/Makefile b/injector/Makefile index 1e96f56..6fa5844 100755 --- a/injector/Makefile +++ b/injector/Makefile @@ -22,10 +22,10 @@ LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) INCLUDE := $(foreach dir,$(LIBDIRS),-I$(dir)/include) -ARCH := -mcpu=mpcore -mfloat-abi=hard -mtp=soft -CFLAGS := -Wall -Wextra -MMD -MP -marm $(ARCH) -fno-builtin -std=c11 -O2 -flto -ffast-math -mword-relocations \ +ASFLAGS := -mcpu=mpcore -mfloat-abi=hard -mtp=soft +CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -std=c11 -O2 -flto -ffast-math -mword-relocations \ -ffunction-sections -fdata-sections $(INCLUDE) -DARM11 -D_3DS -LDFLAGS := -Xlinker --defsym="__start__=0x14000000" -specs=3dsx.specs $(ARCH) +LDFLAGS := -Xlinker --defsym="__start__=0x14000000" -specs=3dsx.specs $(ASFLAGS) objects = $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c)) @@ -51,6 +51,5 @@ $(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/%.o: $(dir_source)/%.s @mkdir -p "$(@D)" - $(COMPILE.c) $(OUTPUT_OPTION) $< - + $(COMPILE.s) $(OUTPUT_OPTION) $< include $(call rwildcard, $(dir_build), *.d) diff --git a/injector/source/CFWInfo.h b/injector/source/CFWInfo.h index 0e9d63f..bf2c489 100644 --- a/injector/source/CFWInfo.h +++ b/injector/source/CFWInfo.h @@ -1,7 +1,5 @@ #pragma once -#include <3ds.h> - typedef struct __attribute__((packed)) { char magic[4]; diff --git a/source/patches.c b/source/patches.c index 4cb4ef3..b6f3e5b 100644 --- a/source/patches.c +++ b/source/patches.c @@ -216,7 +216,7 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType) void patchTwlBg(u8 *pos) { - u8 *dst = pos + (isN3DS ? 0xFEA4 : 0xFCA0); + u8 *dst = pos + (isN3DS ? 0xFEA4 : 0xFCA0); memcpy(dst, twl_k11modules, twl_k11modules_size); //Install K11 hook diff --git a/source/pin.c b/source/pin.c index 1ea64e8..0f52200 100644 --- a/source/pin.c +++ b/source/pin.c @@ -39,7 +39,7 @@ static char pinKeyToLetter(u32 pressed) const char keys[] = "AB--------XY"; u32 i; - __asm__ volatile("clz %[i], %[pressed]" : [i] "=r" (i) : [pressed] "r" (pressed)); + for(i = 31; pressed > 1; i--) pressed /= 2; return keys[31 - i]; } From 06fe06f9f1f7560bf7f18cf98ddadc703c29914c Mon Sep 17 00:00:00 2001 From: TuxSH Date: Mon, 29 Aug 2016 18:18:11 +0200 Subject: [PATCH 20/20] Update CFWInfo.h --- injector/source/CFWInfo.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/injector/source/CFWInfo.h b/injector/source/CFWInfo.h index bf2c489..30b4781 100644 --- a/injector/source/CFWInfo.h +++ b/injector/source/CFWInfo.h @@ -1,5 +1,7 @@ #pragma once +#include <3ds/types.h> + typedef struct __attribute__((packed)) { char magic[4];