add mono x64 support

This commit is contained in:
Akash Mozumdar 2019-06-18 00:41:39 -04:00
parent d9ba1e5854
commit c915432763
3 changed files with 68 additions and 1 deletions

View File

@ -16,6 +16,7 @@ namespace Engine {
extern wchar_t *processName, // cached extern wchar_t *processName, // cached
processPath[MAX_PATH]; // cached processPath[MAX_PATH]; // cached
// Artikash 6/17/2019 TODO: These have the wrong values on x64
/** jichi 12/24/2014 /** jichi 12/24/2014
* @param addr function address * @param addr function address
* @param frame real address of the function, supposed to be the same as addr * @param frame real address of the function, supposed to be the same as addr

View File

@ -1,6 +1,9 @@
#include "match.h" #include "match.h"
#include "main.h" #include "main.h"
#include "texthook.h"
#include "native/pchooks.h" #include "native/pchooks.h"
#include "mono/monoobject.h"
#include "mono/funcinfo.h"
#include "engine.h" #include "engine.h"
#include "util.h" #include "util.h"
@ -43,10 +46,71 @@ namespace Engine
return found; return found;
} }
bool InsertMonoHooks(HMODULE module)
{
auto SpecialHookMonoString = nullptr;
static HMODULE mono = module;
bool ret = false;
for (auto func : Array<MonoFunction>{ MONO_FUNCTIONS_INITIALIZER })
{
HookParam hp = {};
if (!(hp.address = (uintptr_t)GetProcAddress(mono, func.functionName))) continue;
hp.type = HOOK_EMPTY;
NewHook(hp, "Mono Searcher");
ret = true;
}
/* Artikash 2/13/2019:
How to hook Mono/Unity3D:
Find all standard function prologs in memory with write/execute permission: these represent possible JIT compiled functions
Then use Mono APIs to reflect what these functions are, and hook them if they are string member functions
Mono calling convention uses 'this' as first argument on stack
Must be dynamic hook bootstrapped from other mono api or mono_domain_get won't work
*/
trigger_fun = [](LPVOID addr, DWORD, DWORD)
{
static auto getDomain = (MonoDomain*(*)())GetProcAddress(mono, "mono_domain_get");
static auto getJitInfo = (MonoObject*(*)(MonoDomain*, uintptr_t))GetProcAddress(mono, "mono_jit_info_table_find");
static auto getName = (char*(*)(uintptr_t))GetProcAddress(mono, "mono_pmip");
if (!getDomain || !getName || !getJitInfo) goto failed;
static auto domain = getDomain();
if (!domain) goto failed;
const BYTE prolog[] = { 0x55, 0x48, 0x8b, 0xec };
for (auto addr : Util::SearchMemory(prolog, sizeof(prolog), PAGE_EXECUTE_READWRITE))
{
[](uint64_t addr)
{
__try
{
if (getJitInfo(domain, addr))
if (char* name = getName(addr))
if (strstr(name, "string:") && !strstr(name, "string:mem"))
{
HookParam hp = {};
hp.address = addr;
hp.type = USING_STRING | USING_UNICODE;
hp.offset = -0x20;
hp.padding = 20;
NewHook(hp, name);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
}(addr);
}
return true;
failed:
ConsoleOutput("Textractor: Mono Dynamic failed");
return true;
};
SetTrigger();
return ret;
}
bool UnsafeDetermineEngineType() bool UnsafeDetermineEngineType()
{ {
if (Util::CheckFile(L"PPSSPP*.exe") && FindPPSSPP()) return true; if (Util::CheckFile(L"PPSSPP*.exe") && FindPPSSPP()) return true;
for (const wchar_t* monoName : { L"mono", L"mono-2.0-bdwgc" }) if (HMODULE module = GetModuleHandleW(monoName)) if (InsertMonoHooks(module)) return true;
for (std::wstring DXVersion : { L"d3dx9", L"d3dx10" }) for (std::wstring DXVersion : { L"d3dx9", L"d3dx10" })
if (HMODULE module = GetModuleHandleW(DXVersion.c_str())) PcHooks::hookD3DXFunctions(module); if (HMODULE module = GetModuleHandleW(DXVersion.c_str())) PcHooks::hookD3DXFunctions(module);
else for (int i = 0; i < 50; ++i) else for (int i = 0; i < 50; ++i)

View File

@ -122,13 +122,14 @@ void TextHook::Send(uintptr_t dwDataBase)
{ {
__try __try
{ {
if (trigger) trigger = Engine::InsertDynamicHook(location, *(DWORD *)(dwDataBase - 0x1c), *(DWORD *)(dwDataBase - 0x18));
#ifndef _WIN64 #ifndef _WIN64
DWORD dwCount = 0, DWORD dwCount = 0,
dwSplit = 0, dwSplit = 0,
dwDataIn = *(DWORD*)(dwDataBase + hp.offset), // default values dwDataIn = *(DWORD*)(dwDataBase + hp.offset), // default values
dwRetn = *(DWORD*)dwDataBase; // first value on stack (if hooked start of function, this is return address) dwRetn = *(DWORD*)dwDataBase; // first value on stack (if hooked start of function, this is return address)
if (trigger) trigger = Engine::InsertDynamicHook(location, *(DWORD *)(dwDataBase - 0x1c), *(DWORD *)(dwDataBase - 0x18));
// jichi 10/24/2014: generic hook function // jichi 10/24/2014: generic hook function
if (hp.hook_fun && !hp.hook_fun(dwDataBase, &hp)) hp.hook_fun = nullptr; if (hp.hook_fun && !hp.hook_fun(dwDataBase, &hp)) hp.hook_fun = nullptr;
@ -166,6 +167,7 @@ void TextHook::Send(uintptr_t dwDataBase)
TextOutput({ GetCurrentProcessId(), address, dwRetn, dwSplit }, pbData, dwCount); TextOutput({ GetCurrentProcessId(), address, dwRetn, dwSplit }, pbData, dwCount);
#else // _WIN32 #else // _WIN32
if (hp.type & HOOK_EMPTY) return; // jichi 10/24/2014: dummy hook only for dynamic hook
int count = 0; int count = 0;
ThreadParam tp = { GetCurrentProcessId(), address, *(uintptr_t*)dwDataBase, 0 }; // first value on stack (if hooked start of function, this is return address) ThreadParam tp = { GetCurrentProcessId(), address, *(uintptr_t*)dwDataBase, 0 }; // first value on stack (if hooked start of function, this is return address)
uintptr_t data = *(uintptr_t*)(dwDataBase + hp.offset); // default value uintptr_t data = *(uintptr_t*)(dwDataBase + hp.offset); // default value