forked from Public-Mirror/Textractor
add mono x64 support
This commit is contained in:
parent
d9ba1e5854
commit
c915432763
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user