diff --git a/source/core/util.c b/source/core/util.c index d037868..864487e 100644 --- a/source/core/util.c +++ b/source/core/util.c @@ -131,6 +131,10 @@ void util_panic(const char* s, ...) { gfxFlushBuffers(); gspWaitForVBlank(); + util_panic_quiet(); +} + +void util_panic_quiet() { while(aptMainLoop()) { hidScanInput(); if(hidKeysDown() & ~KEY_TOUCH) { diff --git a/source/core/util.h b/source/core/util.h index 373f115..c534b05 100644 --- a/source/core/util.h +++ b/source/core/util.h @@ -40,6 +40,7 @@ typedef struct { void util_store_console_std(); void util_panic(const char* s, ...); +void util_panic_quiet(); FS_Path* util_make_path_utf8(const char* path); void util_free_path_utf8(FS_Path* path); diff --git a/source/hax/khax.c b/source/hax/khax.c new file mode 100644 index 0000000..c0771fa --- /dev/null +++ b/source/hax/khax.c @@ -0,0 +1,106 @@ +#include <3ds.h> +#include + +#include "khax.h" +#include "svchax/svchax.h" +#include "waithax/waithax.h" + +#define CURRENT_KPROCESS 0xFFFF9004 + +static void (*khax_backdoor)(void (*func)()); + +static volatile u32 khax_read32_kernel_addr; +static volatile u32 khax_read32_kernel_result; + +static volatile u32 khax_write32_kernel_addr; +static volatile u32 khax_write32_kernel_value; + +static void khax_read32_kernel_priv() { + khax_read32_kernel_result = *(u32*) khax_read32_kernel_addr; +} + +static u32 khax_read32_kernel(u32 addr) { + khax_read32_kernel_addr = addr; + khax_backdoor(khax_read32_kernel_priv); + return khax_read32_kernel_result; +} + +static void khax_write32_kernel_priv() { + *(u32*) khax_write32_kernel_addr = khax_write32_kernel_value; +} + +static void khax_write32_kernel(u32 addr, u32 value) { + khax_write32_kernel_addr = addr; + khax_write32_kernel_value = value; + khax_backdoor(khax_write32_kernel_priv); +} + +bool khax_execute() { + printf("khax: Retrieving system information...\n"); + + u32 kver = osGetKernelVersion(); + bool n3ds = false; + APT_CheckNew3DS(&n3ds); + + void (*khax_cleanup)() = NULL; + + if(envIsHomebrew()) { + printf("khax: Choosing exploit to execute...\n"); + + if(kver > SYSTEM_VERSION(2, 51, 2)) { + printf("khax: Unsupported firmware version.\n"); + return false; + } else if(kver > SYSTEM_VERSION(2, 50, 11)) { + printf("khax: Executing waithax...\n"); + + if(!waithax_run()) { + printf("khax: waithax failed.\n"); + return false; + } + + khax_backdoor = waithax_backdoor; + khax_cleanup = NULL; + } else { + printf("khax: Executing svchax...\n"); + + svchax_init(false); + + if(!__ctr_svchax) { + printf("khax: svchax failed.\n"); + return false; + } + + khax_backdoor = (void (*)(void (*func)())) svcBackdoor; + khax_cleanup = waithax_cleanup; + } + + printf("khax: Kernel exploit executed successfully.\n"); + } else { + printf("khax: Not running as a 3DSX; assuming CIA/3DS with svcBackdoor access.\n"); + + khax_backdoor = (void (*)(void (*func)())) svcBackdoor; + khax_cleanup = NULL; + } + + printf("khax: Retrieving PID kernel address...\n"); + u32 pidAddr = khax_read32_kernel(CURRENT_KPROCESS) + (n3ds ? 0xBC : (kver > SYSTEM_VERSION(2, 40, 0)) ? 0xB4 : 0xAC); + + printf("khax: Backing up PID and patching to 0...\n"); + u32 oldPid = khax_read32_kernel(pidAddr); + khax_write32_kernel(pidAddr, 0); + + printf("khax: Reinitializing srv...\n"); + srvExit(); + srvInit(); + + printf("khax: Restoring PID...\n"); + khax_write32_kernel(pidAddr, oldPid); + + printf("khax: Cleaning up...\n"); + if(khax_cleanup != NULL) { + khax_cleanup(); + } + + printf("khax: Success.\n"); + return true; +} \ No newline at end of file diff --git a/source/hax/khax.h b/source/hax/khax.h new file mode 100644 index 0000000..d237347 --- /dev/null +++ b/source/hax/khax.h @@ -0,0 +1,3 @@ +#pragma once + +bool khax_execute(); \ No newline at end of file diff --git a/source/hax/svchax.c b/source/hax/svchax/svchax.c similarity index 87% rename from source/hax/svchax.c rename to source/hax/svchax/svchax.c index 6cc7635..a8de6ce 100644 --- a/source/hax/svchax.c +++ b/source/hax/svchax/svchax.c @@ -3,7 +3,6 @@ #include #include #include "svchax.h" -#include "waithax.h" #define CURRENT_KTHREAD 0xFFFF9000 #define CURRENT_KPROCESS 0xFFFF9004 @@ -46,12 +45,10 @@ static u32 svc_7b(backdoor_fn entry_fn, ...) // can pass up to two arguments to return 0; } -static bool g_is_new3ds; - -static void k_enable_all_svcs() +static void k_enable_all_svcs(u32 isNew3DS) { u32* thread_ACL = *(*(u32***)CURRENT_KTHREAD + 0x22) - 0x6; - u32* process_ACL = *(u32**)CURRENT_KPROCESS + (g_is_new3ds ? 0x24 : 0x22); + u32* process_ACL = *(u32**)CURRENT_KPROCESS + (isNew3DS ? 0x24 : 0x22); memset(thread_ACL, 0xFF, 0x10); memset(process_ACL, 0xFF, 0x10); @@ -230,7 +227,7 @@ static void do_memchunkhax2(void) if (!mch2.threads[i].keep) svcCloseHandle(mch2.threads[i].handle); - svcCreateEvent(&mch2.dummy_threads_lock, RESET_STICKY); + svcCreateEvent(&mch2.dummy_threads_lock, 1); svcClearEvent(mch2.dummy_threads_lock); for (i = 0; i < mch2.threads_limit; i++) @@ -247,7 +244,7 @@ static void do_memchunkhax2(void) svcCloseHandle(mch2.threads[i].handle); mch2.threads[i].handle = 0; } - + svcSleepThread(40000000LL); svcCloseHandle(mch2.dummy_threads_lock); @@ -315,8 +312,8 @@ static void do_memchunkhax2(void) volatile u32* thread_ACL = &mapped_page[THREAD_PAGE_ACL_OFFSET >> 2]; - svcCreateEvent(&mch2.main_thread_lock, RESET_ONESHOT); - svcCreateEvent(&mch2.target_threads_lock, RESET_STICKY); + svcCreateEvent(&mch2.main_thread_lock, 0); + svcCreateEvent(&mch2.target_threads_lock, 1); svcClearEvent(mch2.target_threads_lock); for (i = 0; i < mch2.threads_limit; i++) @@ -380,13 +377,16 @@ static void do_memchunkhax2(void) static void gspwn(u32 dst, u32 src, u32 size, u8* flush_buffer) { + extern Handle gspEvents[GSPGPU_EVENT_MAX]; + memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000); GSPGPU_InvalidateDataCache((void*)dst, size); GSPGPU_FlushDataCache((void*)src, size); memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000); + svcClearEvent(gspEvents[GSPGPU_EVENT_PPF]); GX_TextureCopy((void*)src, 0, (void*)dst, 0, size, 8); - gspWaitForPPF(); + svcWaitSynchronization(gspEvents[GSPGPU_EVENT_PPF], U64_MAX); memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000); } @@ -463,66 +463,37 @@ static void do_memchunkhax1(void) Result svchax_init(bool patch_srv) { - APT_CheckNew3DS(&g_is_new3ds); + bool isNew3DS; + APT_CheckNew3DS(&isNew3DS); u32 kver = osGetKernelVersion(); - if(!__ctr_svchax) { - if(__service_ptr) { - if(kver > SYSTEM_VERSION(2, 51, 2)) { - printf("Unsupported firmware version.\n"); + if (!__ctr_svchax) + { + if (__service_ptr) + { + if (kver > SYSTEM_VERSION(2, 50, 11)) return -1; - } else if(kver > SYSTEM_VERSION(2, 50, 11)) { - printf("Executing waithax..."); - if(waithax_run()) { - printf("Executing k_enable_all_svcs...\n"); - waithax_backdoor(k_enable_all_svcs); - - printf("Cleaning up waithax...\n"); - waithax_cleanup(); - - printf("waithax complete.\n"); - __ctr_svchax = 1; - } - } else { - if(kver > SYSTEM_VERSION(2, 46, 0)) { - printf("Executing memchunkhax2...\n"); - do_memchunkhax2(); - } else { - printf("Executing memchunkhax1...\n"); - do_memchunkhax1(); - } - - printf("Executing k_enable_all_svcs...\n"); - svc_7b((backdoor_fn) k_enable_all_svcs); - - printf("memchunkhax complete.\n"); - __ctr_svchax = 1; - } - } else { - printf("Executing k_enable_all_svcs...\n"); - svc_7b((backdoor_fn) k_enable_all_svcs); - - printf("SVC access patch complete.\n"); - __ctr_svchax = 1; + else if (kver > SYSTEM_VERSION(2, 46, 0)) + do_memchunkhax2(); + else + do_memchunkhax1(); } + + svc_7b((backdoor_fn)k_enable_all_svcs, isNew3DS); + + __ctr_svchax = 1; } - if (patch_srv && __ctr_svchax && !__ctr_svchax_srv) + if (patch_srv && !__ctr_svchax_srv) { - printf("Patching PID to 0...\n"); - u32 PID_kaddr = read_kaddr(CURRENT_KPROCESS) + (g_is_new3ds ? 0xBC : (kver > SYSTEM_VERSION(2, 40, 0)) ? 0xB4 : 0xAC); + u32 PID_kaddr = read_kaddr(CURRENT_KPROCESS) + (isNew3DS ? 0xBC : (kver > SYSTEM_VERSION(2, 40, 0)) ? 0xB4 : 0xAC); u32 old_PID = read_kaddr(PID_kaddr); write_kaddr(PID_kaddr, 0); - - printf("Reinitializing srv...\n"); srvExit(); srvInit(); - - printf("Restoring PID...\n"); write_kaddr(PID_kaddr, old_PID); - printf("Service access patch complete.\n"); __ctr_svchax_srv = 1; } diff --git a/source/hax/svchax.h b/source/hax/svchax/svchax.h similarity index 100% rename from source/hax/svchax.h rename to source/hax/svchax/svchax.h diff --git a/source/hax/utils.h b/source/hax/waithax/utils.h similarity index 81% rename from source/hax/utils.h rename to source/hax/waithax/utils.h index 2abffa2..ff1c421 100644 --- a/source/hax/utils.h +++ b/source/hax/waithax/utils.h @@ -7,4 +7,3 @@ typedef u32(*backdoor_fn)(u32 arg0, u32 arg1); u32 svc_7b(void* entry_fn, ...); // can pass up to two arguments to entry_fn(...) Result svcCreateSemaphoreKAddr(Handle *semaphore, s32 initialCount, s32 maxCount, u32 **kaddr); -Result svcGetHandleInfo(s64* out, Handle handle, u32 type); diff --git a/source/hax/utils.s b/source/hax/waithax/utils.s similarity index 82% rename from source/hax/utils.s rename to source/hax/waithax/utils.s index a7c9e41..a6fb37c 100644 --- a/source/hax/utils.s +++ b/source/hax/waithax/utils.s @@ -18,16 +18,6 @@ svcCreateSemaphoreKAddr: str r1, [r3] bx lr -.global svcGetHandleInfo -.type svcGetHandleInfo, %function -svcGetHandleInfo: - str r0, [sp, #-0x4]! - svc 0x29 - ldr r3, [sp], #4 - str r1, [r3] - str r2, [r3, #4] - bx lr - @ Here for debug/dev purposes .global svc_7b diff --git a/source/hax/waithax.c b/source/hax/waithax/waithax.c similarity index 100% rename from source/hax/waithax.c rename to source/hax/waithax/waithax.c diff --git a/source/hax/waithax.h b/source/hax/waithax/waithax.h similarity index 100% rename from source/hax/waithax.h rename to source/hax/waithax/waithax.h diff --git a/source/main.c b/source/main.c index 71533ce..1158405 100644 --- a/source/main.c +++ b/source/main.c @@ -7,7 +7,7 @@ #include "core/clipboard.h" #include "core/screen.h" #include "core/util.h" -#include "hax/svchax.h" +#include "hax/khax.h" #include "ui/error.h" #include "ui/mainmenu.h" #include "ui/ui.h" @@ -94,8 +94,12 @@ void init() { consoleInit(GFX_TOP, NULL); util_store_console_std(); - printf("Attempting to acquire kernel access..."); - svchax_init(true); + if(!khax_execute()) { + printf("Press any key to exit.\n"); + + util_panic_quiet(); + return; + } devoptab_list[STD_OUT] = oldStdOut; devoptab_list[STD_ERR] = oldStdErr; @@ -103,11 +107,6 @@ void init() { gfxSetScreenFormat(GFX_TOP, GSP_BGR8_OES); gfxSetDoubleBuffering(GFX_TOP, true); - if(!__ctr_svchax || !__ctr_svchax_srv) { - util_panic("Failed to acquire kernel access."); - return; - } - Result initRes = init_services(); if(R_FAILED(initRes)) { util_panic("Failed to initialize services: %08lX", initRes);