Last active
June 11, 2022 23:33
-
-
Save Mrrraou/c74572c04d13c586d363bf64eba0d3a1 to your computer and use it in GitHub Desktop.
svcGlobalBackdoor usage demonstration. Licensed under the MIT License - Mrrraou 2017
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <3ds/types.h> | |
typedef u32(*backdoor_fn)(u32 arg0, u32 arg1); | |
u32 svc_30(void *entry_fn, ...); // can pass up to two arguments to entry_fn(...) | |
Result svcGlobalBackdoor(s32 (*callback)(void)); | |
bool checkSvcGlobalBackdoor(void); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.global svc_30 | |
.type svc_30, %function | |
svc_30: | |
push {r0, r1, r2} | |
mov r3, sp | |
adr r0, svc_30_callback | |
svc 0x30 | |
add sp, sp, #8 | |
ldr r0, [sp], #4 | |
bx lr | |
svc_30_callback: | |
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 | |
.global svcGlobalBackdoor | |
.type svcGlobalBackdoor, %function | |
svcGlobalBackdoor: | |
svc 0x30 | |
bx lr | |
.global checkSvcGlobalBackdoor | |
.type checkSvcGlobalBackdoor, %function | |
checkSvcGlobalBackdoor: | |
adr r0, checkSvcGlobalBackdoor_callback | |
mov r3, #0 | |
svc 0x30 | |
mov r0, r3 | |
bx lr | |
checkSvcGlobalBackdoor_callback: | |
cpsid aif | |
mov r3, #1 | |
bx lr |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "kernel_patches.h" | |
#include <3ds.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include "global_backdoor.h" | |
// Shamelessly copied from | |
// https://github.com/Steveice10/memchunkhax2/blob/master/source/memchunkhax2.c#L16 | |
#define OLDNEW(x) (g_is_new3ds ? x ## _NEW : x ## _OLD) | |
#define CURRENT_KTHREAD (*((u8**)0xFFFF9000)) | |
#define CURRENT_KPROCESS (*((u8**)0xFFFF9004)) | |
#define SVC_ACL_SIZE (0x10) | |
#define KPROCESS_ACL_START_OLD (0x88) | |
#define KPROCESS_ACL_START_NEW (0x90) | |
#define KPROCESS_PID_OFFSET_OLD (0xB4) | |
#define KPROCESS_PID_OFFSET_NEW (0xBC) | |
#define KTHREAD_THREADPAGEPTR_OFFSET (0x8C) | |
#define KSVCTHREADAREA_BEGIN_OFFSET (0xC8) | |
static bool g_is_new3ds = false; | |
static u32 g_original_pid = 0; | |
static void K_PatchPID(void) | |
{ | |
u8 *proc = CURRENT_KPROCESS; | |
u32 *pidPtr = (u32*)(proc + OLDNEW(KPROCESS_PID_OFFSET)); | |
g_original_pid = *pidPtr; | |
// We're now PID zero, all we have to do is reinitialize the service manager in user-mode. | |
*pidPtr = 0; | |
} | |
static void K_RestorePID(void) | |
{ | |
u8 *proc = CURRENT_KPROCESS; | |
u32 *pidPtr = (u32*)(proc + OLDNEW(KPROCESS_PID_OFFSET)); | |
// Restore the original PID | |
*pidPtr = g_original_pid; | |
} | |
static void K_PatchACL(void) | |
{ | |
// Patch the process first (for newly created threads). | |
u8 *proc = CURRENT_KPROCESS; | |
u8 *procacl = proc + OLDNEW(KPROCESS_ACL_START); | |
memset(procacl, 0xFF, SVC_ACL_SIZE); | |
// Now patch the current thread. | |
u8 *thread = CURRENT_KTHREAD; | |
u8 *thread_pageend = *(u8**)(thread + KTHREAD_THREADPAGEPTR_OFFSET); | |
u8 *thread_page = thread_pageend - KSVCTHREADAREA_BEGIN_OFFSET; | |
memset(thread_page, 0xFF, SVC_ACL_SIZE); | |
} | |
void initsrv_allservices(void) | |
{ | |
APT_CheckNew3DS(&g_is_new3ds); | |
printf("Patching PID\n"); | |
svc_30(K_PatchPID); | |
printf("Reiniting srv:\n"); | |
srvExit(); | |
srvInit(); | |
printf("Restoring PID\n"); | |
svc_30(K_RestorePID); | |
} | |
void patch_svcaccesstable(void) | |
{ | |
APT_CheckNew3DS(&g_is_new3ds); | |
printf("Patching SVC access table\n"); | |
svc_30(K_PatchACL); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <3ds/types.h> | |
void initsrv_allservices(void); | |
void patch_svcaccesstable(void); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <3ds.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include "global_backdoor.h" | |
#include "kernel_patches.h" | |
int main(int argc, char **argv) | |
{ | |
bool isNew3ds = false; | |
gfxInitDefault(); | |
consoleInit(GFX_TOP, NULL); | |
nsInit(); | |
aptInit(); | |
osSetSpeedupEnable(true); | |
APT_CheckNew3DS(&isNew3ds); | |
printf("System type: %s\n\n", isNew3ds ? "New" : "Old"); | |
if(checkSvcGlobalBackdoor()) | |
{ | |
printf("svcGlobalBackdoor was found\n"); | |
initsrv_allservices(); | |
patch_svcaccesstable(); | |
} | |
else | |
printf("svcGlobalBackdoor is not implemented\n"); | |
printf("\nPress START to exit.\n"); | |
while(aptMainLoop()) | |
{ | |
hidScanInput(); | |
if(hidKeysDown() & KEY_START) | |
break; | |
gfxFlushBuffers(); | |
gfxSwapBuffers(); | |
gspWaitForVBlank(); | |
} | |
aptExit(); | |
nsExit(); | |
gfxExit(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wonderful work, thanks a lot.