From 6470f82f910851032ee84ebf71cdc0089ca7b25a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <1173718158@qq.com> Date: Sun, 24 Nov 2024 19:52:26 +0800 Subject: [PATCH] . --- cpp/LunaHook/LunaHook/engine64/Ryujinx.cpp | 186 +++++++++++++++++---- 1 file changed, 150 insertions(+), 36 deletions(-) diff --git a/cpp/LunaHook/LunaHook/engine64/Ryujinx.cpp b/cpp/LunaHook/LunaHook/engine64/Ryujinx.cpp index 91036176..b7d6d6af 100644 --- a/cpp/LunaHook/LunaHook/engine64/Ryujinx.cpp +++ b/cpp/LunaHook/LunaHook/engine64/Ryujinx.cpp @@ -3,18 +3,18 @@ namespace { /* - const char* CEEInfo::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftnHnd, - const char** className, - const char** namespaceName, - const char** enclosingClassNames, - size_t maxEnclosingClassNames) + UnsafeJitFunction-> + invokeCompileMethodHelper-> + jitMgr->m_jit->compileMethod + + FlushInstructionCache */ /* - CorJitResult CILJit::compileMethod(ICorJitInfo* compHnd, - CORINFO_METHOD_INFO* methodInfo, - unsigned flags, - uint8_t** entryAddress, - uint32_t* nativeSizeOfCode) + unsigned __int8 *__fastcall UnsafeJitFunction( + PrepareCodeConfig *config, + COR_ILMETHOD_DECODER *ILHeader, + CORJIT_FLAGS *pJitFlags, + unsigned int *a4) */ /* CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, @@ -24,6 +24,21 @@ namespace BYTE **nativeEntry, uint32_t *nativeSizeOfCode) */ + /* + CorJitResult CILJit::compileMethod(ICorJitInfo* compHnd, + CORINFO_METHOD_INFO* methodInfo, + unsigned flags, + uint8_t** entryAddress, + uint32_t* nativeSizeOfCode) + */ + + /* + const char* CEEInfo::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftnHnd, + const char** className, + const char** namespaceName, + const char** enclosingClassNames, + size_t maxEnclosingClassNames) + */ struct CEEInfo; struct CORINFO_METHOD_HANDLE; struct CORINFO_METHOD_INFO @@ -42,15 +57,84 @@ namespace const char *(*getMethodNameFromMetadata)(CEEInfo *, CORINFO_METHOD_HANDLE *, const char **, const char **, const char **) = 0; } +struct passinfo +{ + void **nativeEntry; + std::string methodname; + std::string className; + std::string namespaceName; + std::string enclosingClassName; +}; bool Ryujinx::attach_function() { WarningOutput("not support ryuujinx, please use yuzu/sudachi instead."); return true; - auto invokeCompileMethodHelper = processStartAddress + 0x84CC0; - getMethodNameFromMetadata = (decltype(getMethodNameFromMetadata))(processStartAddress + 0x7AED0); - HookParam hp; - hp.address = invokeCompileMethodHelper; - hp.text_fun = [](hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) + /* + UnsafeJitFunction + + if ( !EEJitManager::LoadJIT(ExecutionManager::m_pEEJitManager) ) + { + if ( !v10->m_jit ) + { + CurrentIP = GetCurrentIP(); + EEPolicy::HandleFatalError(0x80131506, CurrentIP, L"Failed to load JIT compiler", 0i64, 0i64, 0i64); + __debugbreak(); + } + if ( !v10->m_alternateJit ) + { + v46 = GetCurrentIP(); + EEPolicy::HandleFatalError(0x80131506, v46, L"Failed to load alternative JIT compiler", 0i64, 0i64, 0i64); +LABEL_89: + RealCOMPlusThrow(kInvalidProgramException); + } + } + */ + wchar_t aFailedToLoadJi[] = L"Failed to load JIT compiler"; + auto paFailedToLoadJi = MemDbg::findBytes(aFailedToLoadJi, sizeof(aFailedToLoadJi), processStartAddress, processStopAddress); + if (!paFailedToLoadJi) + return false; + auto lea_aFailedToLoadJi = MemDbg::findleaaddr(paFailedToLoadJi, processStartAddress, processStopAddress); + if (!lea_aFailedToLoadJi) + return false; + ConsoleOutput("lea_aFailedToLoadJi %p", lea_aFailedToLoadJi - processStartAddress); + BYTE funcstart[] = {0x48, 0x89, 0x5c, 0x24, 0x10, 0x55, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57}; + auto UnsafeJitFunction = reverseFindBytes(funcstart, sizeof(funcstart), lea_aFailedToLoadJi - 0x1000, lea_aFailedToLoadJi); + if (!UnsafeJitFunction) + return false; + ConsoleOutput("UnsafeJitFunction %p", UnsafeJitFunction - processStartAddress); + BYTE sig_call_invokeCompileMethodHelper[] = { + 0x48, 0x8D, 0x44, 0x24, XX, // lea rax,[rbp+xx] + 0x48, 0x89, 0x44, 0x24, 0x28, // mov [rsp+28],rax + 0x48, 0x8d, 0x45, XX, // lea rax,[rbp-xx] + 0x48, 0x89, 0x44, 0x24, 0x20, // mov [rsp+20],rax + 0x4c, 0x8d, 0x8d, XX4, // lea r9,[rbp+xx] + 0x4c, 0x8d, 0x85, XX4, // lea r8,[rbp+xx] + 0x48, 0x8d, 0x95, XX4, // lea rdx,[rbp+xx] + 0x49, 0x8b, 0xcc, // mov rcx,r12 + 0xe8, XX4}; + auto call_invokeCompileMethodHelper = MemDbg::findBytes(sig_call_invokeCompileMethodHelper, sizeof(sig_call_invokeCompileMethodHelper), UnsafeJitFunction, UnsafeJitFunction + 0x1000); + if (!call_invokeCompileMethodHelper) + return call_invokeCompileMethodHelper; + BYTE sig_getMethodNameFromMetadata[] = { + 0x41, 0xb8, 0xff, 0x0f, 0x00, 0x00, + 0x66, 0x41, 0x23, 0xc8, + 0x0f, 0xb7, 0x02, + 0x66, 0x41, 0x23, 0xc0, + 0x44, 0x0f, 0xb7, 0xc9, + 0x41, 0x81, 0xc9, 0x00, 0x60, 0x00, 0x00, + 0x41, 0xc1, 0xe1, 0x0c}; + auto ptr_sig_getMethodNameFromMetadata = MemDbg::findBytes(sig_getMethodNameFromMetadata, sizeof(sig_getMethodNameFromMetadata), processStartAddress, processStopAddress); + if (!ptr_sig_getMethodNameFromMetadata) + return false; + BYTE start_getMethodNameFromMetadata[] = {0x48, 0x89, XX, XX}; + getMethodNameFromMetadata = (decltype(getMethodNameFromMetadata))reverseFindBytes(start_getMethodNameFromMetadata, sizeof(start_getMethodNameFromMetadata), ptr_sig_getMethodNameFromMetadata - 0x100, ptr_sig_getMethodNameFromMetadata, 0, true); + if (!getMethodNameFromMetadata) + return false; + ConsoleOutput("getMethodNameFromMetadata %p", (uintptr_t)getMethodNameFromMetadata - processStartAddress); + HookParam hp_invokeCompileMethodHelper; + hp_invokeCompileMethodHelper.address = *(int *)(call_invokeCompileMethodHelper + sizeof(sig_call_invokeCompileMethodHelper) - 4) + call_invokeCompileMethodHelper + sizeof(sig_call_invokeCompileMethodHelper); + hp_invokeCompileMethodHelper.user_value = (uintptr_t) new passinfo{}; + hp_invokeCompileMethodHelper.text_fun = [](hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) { auto methodInfo = (CORINFO_METHOD_INFO *)stack->r8; @@ -59,27 +143,57 @@ bool Ryujinx::attach_function() const char *enclosingClassName; auto methodname = getMethodNameFromMetadata((CEEInfo *)stack->rdx, methodInfo->ftn, &className, &namespaceName, &enclosingClassName); if (!methodname) - return; - if (strcmp(methodname, "RegisterFunction") != 0) - return; - - ConsoleOutput("%s %s %s %s", className, namespaceName, enclosingClassName, methodname); - HookParam hpinternal; - hpinternal.user_value = stack->stack[5]; // entryAddress->RegisterFunction - hpinternal.address = stack->retaddr; - hpinternal.text_fun = [](hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) { - HookParam hp_cs_function; - hp_cs_function.address = *(uintptr_t *)hp->user_value; - hp_cs_function.text_fun = [](hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) - { - ConsoleOutput("%p %p %p %p %p %p", stack->rcx, stack->rdx, stack->r8, stack->r9, stack->r10, stack->r11); - }; - NewHook(hp_cs_function, "RegisterFunction"); - - hp->type = HOOK_EMPTY; - }; - NewHook(hpinternal, "invokeCompileMethodHelper Return"); + ((passinfo *)hp->user_value)->nativeEntry = 0; + } + else + { + ((passinfo *)hp->user_value)->nativeEntry = (void **)stack->stack[5]; + ((passinfo *)hp->user_value)->methodname = methodname; + ((passinfo *)hp->user_value)->className = className; + ((passinfo *)hp->user_value)->namespaceName = namespaceName; + // ((passinfo *)hp->user_value)->enclosingClassName = enclosingClassName; + } }; - return NewHook(hp, "invokeCompileMethodHelper"); + bool succ = NewHook(hp_invokeCompileMethodHelper, "invokeCompileMethodHelper"); + BYTE sig_call_FlushInstructionCache[] = { + /* + .text:0000000140086454 call cs:__imp_GetCurrentProcess + .text:000000014008645A mov config, rax ; hProcess + .text:000000014008645D mov r8d, ebx ; dwSize + .text:0000000140086460 mov ILHeader, rsi ; lpBaseAddress + .text:0000000140086463 call cs:__imp_FlushInstructionCache + */ + 0xFF, 0x15, XX4, + 0x48, 0x8B, XX, + 0x44, 0x8B, XX, + 0x48, 0x8B, XX, + 0xFF, 0x15, XX4}; + auto ptr_sig_call_FlushInstructionCache = MemDbg::findBytes(sig_call_FlushInstructionCache, sizeof(sig_call_FlushInstructionCache), hp_invokeCompileMethodHelper.address, hp_invokeCompileMethodHelper.address + 0x1000); + if (!ptr_sig_call_FlushInstructionCache) + return false; + HookParam hp_call_FlushInstructionCache; + hp_call_FlushInstructionCache.address = ptr_sig_call_FlushInstructionCache + sizeof(sig_call_FlushInstructionCache) - 6; + hp_call_FlushInstructionCache.user_value = hp_invokeCompileMethodHelper.user_value; + hp_call_FlushInstructionCache.text_fun = [](hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) + { + auto info = (passinfo *)hp->user_value; + if (!info->nativeEntry) + return; + if (info->methodname != "RegisterFunction") + return; + if (info->className != "Translator") + return; + // Ryujinx.HLE.HOS:ArmProcessContext`1:Initialize + // Ryujinx.Cpu.Jit:JitCpuContext:Execute + HookParam hp_cs_function; + hp_cs_function.address = *(uintptr_t *)info->nativeEntry; + hp_cs_function.text_fun = [](hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) + { + ConsoleOutput("%s\n%p %p %p %p %p %p", hp->name, stack->rcx, stack->rdx, stack->r8, stack->r9, stack->r10, stack->r11); + }; + NewHook(hp_cs_function, (info->namespaceName + ":" + info->className + ":" + info->methodname).c_str()); + }; + succ |= NewHook(hp_call_FlushInstructionCache, "FlushInstructionCache"); + return succ; } \ No newline at end of file