diff --git a/k11_extension/include/kernel.h b/k11_extension/include/kernel.h index b1f58ca..fb1bed8 100644 --- a/k11_extension/include/kernel.h +++ b/k11_extension/include/kernel.h @@ -27,6 +27,7 @@ #pragma once #include "types.h" +#include extern u32 kernelVersion; @@ -1161,29 +1162,37 @@ offsetof(classname##O3DSPre8x, field))) #define KPROCESSHWINFO_GET_RVALUE(obj, field) *(KPROCESSHWINFO_GET_PTR(obj, field)) #define KPROCESSHWINFO_GET_RVALUE_TYPE(type, obj, field) *(KPROCESSHWINFO_GET_PTR_TYPE(type, obj, field)) +extern u32 pidOffsetKProcess, hwInfoOffsetKProcess, codeSetOffsetKProcess, handleTableOffsetKProcess, debugOffsetKProcess; + static inline u32 idOfProcess(KProcess *process) { - return KPROCESS_GET_RVALUE(process, processId); + u32 id; + memcpy(&id, (const u8 *)process + pidOffsetKProcess, 4); + return id; } static inline KProcessHwInfo *hwInfoOfProcess(KProcess *process) { - return KPROCESS_GET_PTR_TYPE(KProcessHwInfo, process, hwInfo); + return (KProcessHwInfo *)((uintptr_t)process + hwInfoOffsetKProcess); } static inline KCodeSet *codeSetOfProcess(KProcess *process) { - return KPROCESS_GET_RVALUE(process, codeSet); + KCodeSet *cs; + memcpy(&cs, (const u8 *)process + codeSetOffsetKProcess, 4); + return cs; } static inline KProcessHandleTable *handleTableOfProcess(KProcess *process) { - return KPROCESS_GET_PTR(process, handleTable); + return (KProcessHandleTable *)((uintptr_t)process + handleTableOffsetKProcess); } static inline KDebug *debugOfProcess(KProcess *process) { - return KPROCESS_GET_RVALUE(process, debug); + KDebug *debug; + memcpy(&debug, (const u8 *)process + debugOffsetKProcess, 4); + return debug; } static inline const char *classNameOfAutoObject(KAutoObject *object) diff --git a/k11_extension/include/svc.h b/k11_extension/include/svc.h index d2cf45b..cbe4848 100644 --- a/k11_extension/include/svc.h +++ b/k11_extension/include/svc.h @@ -32,7 +32,9 @@ #include "utils.h" extern void *officialSVCs[0x7E]; +extern void *alteredSvcTable[0x100]; + +void buildAlteredSvcTable(void); void postprocessSvc(void); void svcDefaultHandler(u8 svcId); -void *svcHook(u8 *pageEnd); diff --git a/k11_extension/include/svc/KernelSetState.h b/k11_extension/include/svc/KernelSetState.h index aae13ae..9179b77 100644 --- a/k11_extension/include/svc/KernelSetState.h +++ b/k11_extension/include/svc/KernelSetState.h @@ -30,5 +30,7 @@ #include "kernel.h" #include "svc.h" +extern bool svcSignalingEnabled; + bool shouldSignalSyscallDebugEvent(KProcess *process, u8 svcId); Result KernelSetStateHook(u32 type, u32 varg1, u32 varg2, u32 varg3); diff --git a/k11_extension/source/globals.c b/k11_extension/source/globals.c index 030e41e..26584d6 100644 --- a/k11_extension/source/globals.c +++ b/k11_extension/source/globals.c @@ -113,3 +113,5 @@ u32 stolenSystemMemRegionSize; vu32 rosalinaState; bool hasStartedRosalinaNetworkFuncsOnce; + +u32 pidOffsetKProcess, hwInfoOffsetKProcess, codeSetOffsetKProcess, handleTableOffsetKProcess, debugOffsetKProcess; diff --git a/k11_extension/source/main.c b/k11_extension/source/main.c index 0048189..d76debd 100644 --- a/k11_extension/source/main.c +++ b/k11_extension/source/main.c @@ -121,6 +121,12 @@ void configHook(vu8 *cfgPage) *(vu32 *)(configPage + 0x44) = fcramLayout.systemSize; *(vu32 *)(configPage + 0x48) = fcramLayout.baseSize; *isDevUnit = true; // enable debug features + + pidOffsetKProcess = KPROCESS_OFFSETOF(processId); + hwInfoOffsetKProcess = KPROCESS_OFFSETOF(hwInfo); + codeSetOffsetKProcess = KPROCESS_OFFSETOF(codeSet); + handleTableOffsetKProcess = KPROCESS_OFFSETOF(handleTable); + debugOffsetKProcess = KPROCESS_OFFSETOF(debug); } static void findUsefulSymbols(void) @@ -302,6 +308,7 @@ void main(FcramLayout *layout, KCoreContext *ctxs) void **arm11SvcTable = (void**)originalHandlers[2]; while(*arm11SvcTable != NULL) arm11SvcTable++; //Look for SVC0 (NULL) memcpy(officialSVCs, arm11SvcTable, 4 * 0x7E); + buildAlteredSvcTable(); findUsefulSymbols(); diff --git a/k11_extension/source/svc.c b/k11_extension/source/svc.c index 84f32cb..8c1bbc7 100644 --- a/k11_extension/source/svc.c +++ b/k11_extension/source/svc.c @@ -47,28 +47,68 @@ #include "svc/TranslateHandle.h" void *officialSVCs[0x7E] = {NULL}; +void *alteredSvcTable[0x100] = {NULL}; -void signalSvcEntry(u8 *pageEnd) +static Result BreakHook(UserBreakType breakReason, const void* croInfo, u32 croInfoSize) { - u32 svcId = (u32) *(u8 *)(pageEnd - 0xB5); KProcess *currentProcess = currentCoreContext->objectContext.currentProcess; - if(svcId == 0xFE) - svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x3FFFFFFF. We don't support catching svcIds >= 0x100 atm either + void *funptr = (debugOfProcess(currentProcess) != NULL) ? officialSVCs[0x3C] : (void *)Break; + return ((Result (*)(UserBreakType, const void *, u32))funptr)(breakReason, croInfo, croInfoSize); +} + +void buildAlteredSvcTable(void) +{ + memcpy(alteredSvcTable, officialSVCs, 4 * 0x7E); + + alteredSvcTable[0x01] = ControlMemoryHookWrapper; + + alteredSvcTable[0x29] = GetHandleInfoHookWrapper; + alteredSvcTable[0x2A] = GetSystemInfoHookWrapper; + alteredSvcTable[0x2B] = GetProcessInfoHookWrapper; + alteredSvcTable[0x2C] = GetThreadInfoHookWrapper; + alteredSvcTable[0x2D] = ConnectToPortHookWrapper; + + alteredSvcTable[0x32] = SendSyncRequestHook; + alteredSvcTable[0x3C] = BreakHook; + + alteredSvcTable[0x59] = SetGpuProt; + alteredSvcTable[0x5A] = SetWifiEnabled; + + alteredSvcTable[0x7B] = Backdoor; + alteredSvcTable[0x7C] = KernelSetStateHook; + + // Custom SVCs past that point + alteredSvcTable[0x80] = CustomBackdoor; + + alteredSvcTable[0x90] = convertVAToPA; + alteredSvcTable[0x91] = flushDataCacheRange; + alteredSvcTable[0x92] = flushEntireDataCache; + alteredSvcTable[0x93] = invalidateInstructionCacheRange; + alteredSvcTable[0x94] = invalidateEntireInstructionCache; + + alteredSvcTable[0xA0] = MapProcessMemoryEx; + alteredSvcTable[0xA1] = UnmapProcessMemoryEx; + alteredSvcTable[0xA2] = ControlMemoryEx; + + alteredSvcTable[0xB0] = ControlService; + alteredSvcTable[0xB1] = CopyHandleWrapper; + alteredSvcTable[0xB2] = TranslateHandleWrapper; +} + +void signalSvcEntry(u32 svcId) +{ + KProcess *currentProcess = currentCoreContext->objectContext.currentProcess; // Since DBGEVENT_SYSCALL_ENTRY is non blocking, we'll cheat using EXCEVENT_UNDEFINED_SYSCALL (debug->svcId is fortunately an u16!) if(debugOfProcess(currentProcess) != NULL && shouldSignalSyscallDebugEvent(currentProcess, svcId)) SignalDebugEvent(DBGEVENT_OUTPUT_STRING, 0xFFFFFFFE, svcId); } -void signalSvcReturn(u8 *pageEnd) +void signalSvcReturn(u32 svcId) { - u32 svcId = (u32) *(u8 *)(pageEnd - 0xB5); KProcess *currentProcess = currentCoreContext->objectContext.currentProcess; - if(svcId == 0xFE) - svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x1FFFFFFF. We don't support catching svcIds >= 0x100 atm either - // Since DBGEVENT_SYSCALL_RETURN is non blocking, we'll cheat using EXCEVENT_UNDEFINED_SYSCALL (debug->svcId is fortunately an u16!) if(debugOfProcess(currentProcess) != NULL && shouldSignalSyscallDebugEvent(currentProcess, svcId)) SignalDebugEvent(DBGEVENT_OUTPUT_STRING, 0xFFFFFFFF, svcId); @@ -82,71 +122,3 @@ void postprocessSvc(void) officialPostProcessSvc(); } - -void *svcHook(u8 *pageEnd) -{ - KProcess *currentProcess = currentCoreContext->objectContext.currentProcess; - - u32 svcId = *(u8 *)(pageEnd - 0xB5); - if(svcId == 0xFE) - svcId = *(u32 *)(pageEnd - 0x110 + 8 * 4); // r12 ; note: max theortical SVC atm: 0x3FFFFFFF. We don't support catching svcIds >= 0x100 atm either - switch(svcId) - { - case 0x01: - return ControlMemoryHookWrapper; - case 0x29: - return GetHandleInfoHookWrapper; - case 0x2A: - return GetSystemInfoHookWrapper; - case 0x2B: - return GetProcessInfoHookWrapper; - case 0x2C: - return GetThreadInfoHookWrapper; - case 0x2D: - return ConnectToPortHookWrapper; - case 0x32: - return SendSyncRequestHook; - case 0x3C: - return (debugOfProcess(currentProcess) != NULL) ? officialSVCs[0x3C] : (void *)Break; - case 0x59: - return SetGpuProt; - case 0x5A: - return SetWifiEnabled; - case 0x7B: - return Backdoor; - case 0x7C: - return KernelSetStateHook; - - - case 0x80: - return CustomBackdoor; - - case 0x90: - return convertVAToPA; - case 0x91: - return flushDataCacheRange; - case 0x92: - return flushEntireDataCache; - case 0x93: - return invalidateInstructionCacheRange; - case 0x94: - return invalidateEntireInstructionCache; - - case 0xA0: - return MapProcessMemoryEx; - case 0xA1: - return UnmapProcessMemoryEx; - case 0xA2: - return ControlMemoryEx; - - case 0xB0: - return ControlService; - case 0xB1: - return CopyHandleWrapper; - case 0xB2: - return TranslateHandleWrapper; - - default: - return (svcId <= 0x7D) ? officialSVCs[svcId] : NULL; - } -} diff --git a/k11_extension/source/svc/KernelSetState.c b/k11_extension/source/svc/KernelSetState.c index 629a983..324e4f7 100644 --- a/k11_extension/source/svc/KernelSetState.c +++ b/k11_extension/source/svc/KernelSetState.c @@ -36,6 +36,8 @@ static u32 nbEnabled = 0; static u32 maskedPids[MAX_DEBUG]; static u32 masks[MAX_DEBUG][8] = {0}; +bool svcSignalingEnabled = false; + bool shouldSignalSyscallDebugEvent(KProcess *process, u8 svcId) { u32 pid = idOfProcess(process); @@ -65,6 +67,7 @@ Result SetSyscallDebugEventMask(u32 pid, bool enable, const u32 *mask) { maskedPids[nbEnabled] = pid; memcpy(&masks[nbEnabled++], tmpMask, 32); + svcSignalingEnabled = true; } else { @@ -84,6 +87,7 @@ Result SetSyscallDebugEventMask(u32 pid, bool enable, const u32 *mask) } maskedPids[--nbEnabled] = 0; memset(&masks[nbEnabled], 0, 32); + svcSignalingEnabled = false; } KRecursiveLock__Unlock(&syscallDebugEventMaskLock); diff --git a/k11_extension/source/svcHandler.s b/k11_extension/source/svcHandler.s index e44e999..a865b1b 100644 --- a/k11_extension/source/svcHandler.s +++ b/k11_extension/source/svcHandler.s @@ -43,22 +43,24 @@ svcHandler: strb r9, [sp, #0x58+3] @ page end - 0xb8 + 3: svc being handled strb r10, [sp, #0x58+1] @ page end - 0xb8 + 1: "allow debug" flag - @ sp = page end - 0x110 + ldr r8, =alteredSvcTable + ldr r8, [r8, r9,lsl#2] + /*@ sp = page end - 0x110 add r0, sp, #0x110 @ page end bl svcHook cpsid i mov r8, r0 ldmfd sp, {r0-r7, r12, lr} + */ + cmp r8, #0 beq _fallback @ invalid svc, or svc 0xff (stop point) _handled_svc: @ unused label, just here for formatting - push {r0-r12, lr} - add r0, sp, #0x148 - cpsie i - bl signalSvcEntry - cpsid i - pop {r0-r12, lr} + ldr r10, =svcSignalingEnabled @ should work, I guess + ldrb r10, [r10] + cmp r10, #0 + bne _call_svc_debugged @ returns to _fallback_end*/ cpsie i blx r8 @@ -82,16 +84,10 @@ svcHandler: popne {r0-r7, r12} add sp, #4 - cmp r9, #0xff - beq _no_signal_return - - push {r0-r7, r12, lr} - add r0, sp, #0x110 @ page end - cpsie i - bl signalSvcReturn - cpsid i - pop {r0-r7, r12} - add sp, #4 + ldr r10, =svcSignalingEnabled @ should work, I guess + ldr r10, [r10] + cmp r10, #0 + bne _signal_svc_end @ returns to _no_signal_return _no_signal_return: @@ -123,3 +119,24 @@ svcHandler: popne {r0-r7, r12} add sp, #4 b _svc_finished + +_call_svc_debugged: + push {r0-r3, r12, lr} + mov r0, r9 + cpsie i + bl signalSvcEntry + pop {r0-r3, r12, lr} + blx r8 + + cpsid i + ldrb lr, [sp, #0x58+0] @ page end - 0xb8 + 0: scheduling flags + b _fallback_end + +_signal_svc_end: + push {r0-r3, r12, lr} + mov r0, r9 + cpsie i + bl signalSvcReturn + cpsid i + pop {r0-r3, r12, lr} + b _no_signal_return