Textractor_test/texthook/engine/match64.cc
2019-06-18 00:41:39 -04:00

123 lines
4.2 KiB
C++

#include "match.h"
#include "main.h"
#include "texthook.h"
#include "native/pchooks.h"
#include "mono/monoobject.h"
#include "mono/funcinfo.h"
#include "engine.h"
#include "util.h"
namespace Engine
{
/** Artikash 6/7/2019
* PPSSPP JIT code has pointers, but they are all added to an offset before being used.
Find that offset so that hook searching works properly.
To find the offset, find a page of mapped memory with size 0x1f00000, read and write permissions, take its address and subtract 0x8000000.
The above is useful for emulating PSP hardware, so unlikely to change between versions.
*/
bool FindPPSSPP()
{
bool found = false;
SYSTEM_INFO systemInfo;
GetNativeSystemInfo(&systemInfo);
for (BYTE* probe = NULL; probe < systemInfo.lpMaximumApplicationAddress;)
{
MEMORY_BASIC_INFORMATION info;
if (!VirtualQuery(probe, &info, sizeof(info)))
{
probe += systemInfo.dwPageSize;
}
else
{
if (info.RegionSize == 0x1f00000 && info.Protect == PAGE_READWRITE && info.Type == MEM_MAPPED)
{
found = true;
ConsoleOutput("Textractor: PPSSPP memory found: searching for hooks should yield working hook codes");
memcpy(spDefault.pattern, Array<BYTE>{ 0x79, 0x10, 0x41, 0xc7 }, spDefault.length = 4);
spDefault.offset = 0;
spDefault.minAddress = 0;
spDefault.maxAddress = -1ULL;
spDefault.padding = (uintptr_t)probe - 0x8000000;
spDefault.hookPostProcesser = [](HookParam& hp) { hp.type |= NO_CONTEXT; };
}
probe += info.RegionSize;
}
}
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()
{
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" })
if (HMODULE module = GetModuleHandleW(DXVersion.c_str())) PcHooks::hookD3DXFunctions(module);
else for (int i = 0; i < 50; ++i)
if (HMODULE module = GetModuleHandleW((DXVersion + L"_" + std::to_wstring(i)).c_str())) PcHooks::hookD3DXFunctions(module);
PcHooks::hookGDIFunctions();
PcHooks::hookGDIPlusFunctions();
return false;
}
}