mirror of
https://gitlab.com/Theopse/fbi-i18n-zh.git
synced 2025-04-26 19:36:38 +08:00
Clean up kernel exploit code.
This commit is contained in:
parent
3a4187ad39
commit
e1b2a7e4c7
@ -131,6 +131,10 @@ void util_panic(const char* s, ...) {
|
|||||||
gfxFlushBuffers();
|
gfxFlushBuffers();
|
||||||
gspWaitForVBlank();
|
gspWaitForVBlank();
|
||||||
|
|
||||||
|
util_panic_quiet();
|
||||||
|
}
|
||||||
|
|
||||||
|
void util_panic_quiet() {
|
||||||
while(aptMainLoop()) {
|
while(aptMainLoop()) {
|
||||||
hidScanInput();
|
hidScanInput();
|
||||||
if(hidKeysDown() & ~KEY_TOUCH) {
|
if(hidKeysDown() & ~KEY_TOUCH) {
|
||||||
|
@ -40,6 +40,7 @@ typedef struct {
|
|||||||
|
|
||||||
void util_store_console_std();
|
void util_store_console_std();
|
||||||
void util_panic(const char* s, ...);
|
void util_panic(const char* s, ...);
|
||||||
|
void util_panic_quiet();
|
||||||
|
|
||||||
FS_Path* util_make_path_utf8(const char* path);
|
FS_Path* util_make_path_utf8(const char* path);
|
||||||
void util_free_path_utf8(FS_Path* path);
|
void util_free_path_utf8(FS_Path* path);
|
||||||
|
106
source/hax/khax.c
Normal file
106
source/hax/khax.c
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include <3ds.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
3
source/hax/khax.h
Normal file
3
source/hax/khax.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
bool khax_execute();
|
@ -3,7 +3,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include "svchax.h"
|
#include "svchax.h"
|
||||||
#include "waithax.h"
|
|
||||||
|
|
||||||
#define CURRENT_KTHREAD 0xFFFF9000
|
#define CURRENT_KTHREAD 0xFFFF9000
|
||||||
#define CURRENT_KPROCESS 0xFFFF9004
|
#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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool g_is_new3ds;
|
static void k_enable_all_svcs(u32 isNew3DS)
|
||||||
|
|
||||||
static void k_enable_all_svcs()
|
|
||||||
{
|
{
|
||||||
u32* thread_ACL = *(*(u32***)CURRENT_KTHREAD + 0x22) - 0x6;
|
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(thread_ACL, 0xFF, 0x10);
|
||||||
memset(process_ACL, 0xFF, 0x10);
|
memset(process_ACL, 0xFF, 0x10);
|
||||||
@ -230,7 +227,7 @@ static void do_memchunkhax2(void)
|
|||||||
if (!mch2.threads[i].keep)
|
if (!mch2.threads[i].keep)
|
||||||
svcCloseHandle(mch2.threads[i].handle);
|
svcCloseHandle(mch2.threads[i].handle);
|
||||||
|
|
||||||
svcCreateEvent(&mch2.dummy_threads_lock, RESET_STICKY);
|
svcCreateEvent(&mch2.dummy_threads_lock, 1);
|
||||||
svcClearEvent(mch2.dummy_threads_lock);
|
svcClearEvent(mch2.dummy_threads_lock);
|
||||||
|
|
||||||
for (i = 0; i < mch2.threads_limit; i++)
|
for (i = 0; i < mch2.threads_limit; i++)
|
||||||
@ -315,8 +312,8 @@ static void do_memchunkhax2(void)
|
|||||||
|
|
||||||
volatile u32* thread_ACL = &mapped_page[THREAD_PAGE_ACL_OFFSET >> 2];
|
volatile u32* thread_ACL = &mapped_page[THREAD_PAGE_ACL_OFFSET >> 2];
|
||||||
|
|
||||||
svcCreateEvent(&mch2.main_thread_lock, RESET_ONESHOT);
|
svcCreateEvent(&mch2.main_thread_lock, 0);
|
||||||
svcCreateEvent(&mch2.target_threads_lock, RESET_STICKY);
|
svcCreateEvent(&mch2.target_threads_lock, 1);
|
||||||
svcClearEvent(mch2.target_threads_lock);
|
svcClearEvent(mch2.target_threads_lock);
|
||||||
|
|
||||||
for (i = 0; i < mch2.threads_limit; i++)
|
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)
|
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);
|
memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000);
|
||||||
GSPGPU_InvalidateDataCache((void*)dst, size);
|
GSPGPU_InvalidateDataCache((void*)dst, size);
|
||||||
GSPGPU_FlushDataCache((void*)src, size);
|
GSPGPU_FlushDataCache((void*)src, size);
|
||||||
memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000);
|
memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000);
|
||||||
|
|
||||||
|
svcClearEvent(gspEvents[GSPGPU_EVENT_PPF]);
|
||||||
GX_TextureCopy((void*)src, 0, (void*)dst, 0, size, 8);
|
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);
|
memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000);
|
||||||
}
|
}
|
||||||
@ -463,66 +463,37 @@ static void do_memchunkhax1(void)
|
|||||||
|
|
||||||
Result svchax_init(bool patch_srv)
|
Result svchax_init(bool patch_srv)
|
||||||
{
|
{
|
||||||
APT_CheckNew3DS(&g_is_new3ds);
|
bool isNew3DS;
|
||||||
|
APT_CheckNew3DS(&isNew3DS);
|
||||||
|
|
||||||
u32 kver = osGetKernelVersion();
|
u32 kver = osGetKernelVersion();
|
||||||
|
|
||||||
if(!__ctr_svchax) {
|
if (!__ctr_svchax)
|
||||||
if(__service_ptr) {
|
{
|
||||||
if(kver > SYSTEM_VERSION(2, 51, 2)) {
|
if (__service_ptr)
|
||||||
printf("Unsupported firmware version.\n");
|
{
|
||||||
|
if (kver > SYSTEM_VERSION(2, 50, 11))
|
||||||
return -1;
|
return -1;
|
||||||
} else if(kver > SYSTEM_VERSION(2, 50, 11)) {
|
else if (kver > SYSTEM_VERSION(2, 46, 0))
|
||||||
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();
|
do_memchunkhax2();
|
||||||
} else {
|
else
|
||||||
printf("Executing memchunkhax1...\n");
|
|
||||||
do_memchunkhax1();
|
do_memchunkhax1();
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Executing k_enable_all_svcs...\n");
|
svc_7b((backdoor_fn)k_enable_all_svcs, isNew3DS);
|
||||||
svc_7b((backdoor_fn) k_enable_all_svcs);
|
|
||||||
|
|
||||||
printf("memchunkhax complete.\n");
|
|
||||||
__ctr_svchax = 1;
|
__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");
|
if (patch_srv && !__ctr_svchax_srv)
|
||||||
__ctr_svchax = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (patch_srv && __ctr_svchax && !__ctr_svchax_srv)
|
|
||||||
{
|
{
|
||||||
printf("Patching PID to 0...\n");
|
u32 PID_kaddr = read_kaddr(CURRENT_KPROCESS) + (isNew3DS ? 0xBC : (kver > SYSTEM_VERSION(2, 40, 0)) ? 0xB4 : 0xAC);
|
||||||
u32 PID_kaddr = read_kaddr(CURRENT_KPROCESS) + (g_is_new3ds ? 0xBC : (kver > SYSTEM_VERSION(2, 40, 0)) ? 0xB4 : 0xAC);
|
|
||||||
u32 old_PID = read_kaddr(PID_kaddr);
|
u32 old_PID = read_kaddr(PID_kaddr);
|
||||||
write_kaddr(PID_kaddr, 0);
|
write_kaddr(PID_kaddr, 0);
|
||||||
|
|
||||||
printf("Reinitializing srv...\n");
|
|
||||||
srvExit();
|
srvExit();
|
||||||
srvInit();
|
srvInit();
|
||||||
|
|
||||||
printf("Restoring PID...\n");
|
|
||||||
write_kaddr(PID_kaddr, old_PID);
|
write_kaddr(PID_kaddr, old_PID);
|
||||||
|
|
||||||
printf("Service access patch complete.\n");
|
|
||||||
__ctr_svchax_srv = 1;
|
__ctr_svchax_srv = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -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(...)
|
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 svcCreateSemaphoreKAddr(Handle *semaphore, s32 initialCount, s32 maxCount, u32 **kaddr);
|
||||||
Result svcGetHandleInfo(s64* out, Handle handle, u32 type);
|
|
@ -18,16 +18,6 @@ svcCreateSemaphoreKAddr:
|
|||||||
str r1, [r3]
|
str r1, [r3]
|
||||||
bx lr
|
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
|
@ Here for debug/dev purposes
|
||||||
.global svc_7b
|
.global svc_7b
|
@ -7,7 +7,7 @@
|
|||||||
#include "core/clipboard.h"
|
#include "core/clipboard.h"
|
||||||
#include "core/screen.h"
|
#include "core/screen.h"
|
||||||
#include "core/util.h"
|
#include "core/util.h"
|
||||||
#include "hax/svchax.h"
|
#include "hax/khax.h"
|
||||||
#include "ui/error.h"
|
#include "ui/error.h"
|
||||||
#include "ui/mainmenu.h"
|
#include "ui/mainmenu.h"
|
||||||
#include "ui/ui.h"
|
#include "ui/ui.h"
|
||||||
@ -94,8 +94,12 @@ void init() {
|
|||||||
consoleInit(GFX_TOP, NULL);
|
consoleInit(GFX_TOP, NULL);
|
||||||
util_store_console_std();
|
util_store_console_std();
|
||||||
|
|
||||||
printf("Attempting to acquire kernel access...");
|
if(!khax_execute()) {
|
||||||
svchax_init(true);
|
printf("Press any key to exit.\n");
|
||||||
|
|
||||||
|
util_panic_quiet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
devoptab_list[STD_OUT] = oldStdOut;
|
devoptab_list[STD_OUT] = oldStdOut;
|
||||||
devoptab_list[STD_ERR] = oldStdErr;
|
devoptab_list[STD_ERR] = oldStdErr;
|
||||||
@ -103,11 +107,6 @@ void init() {
|
|||||||
gfxSetScreenFormat(GFX_TOP, GSP_BGR8_OES);
|
gfxSetScreenFormat(GFX_TOP, GSP_BGR8_OES);
|
||||||
gfxSetDoubleBuffering(GFX_TOP, true);
|
gfxSetDoubleBuffering(GFX_TOP, true);
|
||||||
|
|
||||||
if(!__ctr_svchax || !__ctr_svchax_srv) {
|
|
||||||
util_panic("Failed to acquire kernel access.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result initRes = init_services();
|
Result initRes = init_services();
|
||||||
if(R_FAILED(initRes)) {
|
if(R_FAILED(initRes)) {
|
||||||
util_panic("Failed to initialize services: %08lX", initRes);
|
util_panic("Failed to initialize services: %08lX", initRes);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user