improve x64 mono

This commit is contained in:
Akash Mozumdar 2019-06-18 04:48:48 -04:00
parent 8db76f86e0
commit f7c2641d58
3 changed files with 17 additions and 5 deletions

View File

@ -40,12 +40,13 @@ struct HookParam
DWORD type; // flags DWORD type; // flags
UINT codepage; // text encoding UINT codepage; // text encoding
short length_offset; // index of the string length short length_offset; // index of the string length
uintptr_t padding; // padding uintptr_t padding; // padding before string
DWORD user_value; // 7/20/2014: jichi additional parameters for PSP games DWORD user_value; // 7/20/2014: jichi additional parameters for PSP games
void(*text_fun)(DWORD stack, HookParam* hp, BYTE obsoleteAlwaysZero, DWORD* data, DWORD* split, DWORD* len); void(*text_fun)(DWORD stack, HookParam* hp, BYTE obsoleteAlwaysZero, DWORD* data, DWORD* split, DWORD* len);
bool(*filter_fun)(void* data, DWORD* len, HookParam* hp, BYTE obsoleteAlwaysZero); // jichi 10/24/2014: Add filter function. Return true if skip the text bool(*filter_fun)(void* data, DWORD* len, HookParam* hp, BYTE obsoleteAlwaysZero); // jichi 10/24/2014: Add filter function. Return true if skip the text
bool(*hook_fun)(DWORD stack, HookParam* hp); // jichi 10/24/2014: Add generic hook function, return false if stop execution. bool(*hook_fun)(DWORD stack, HookParam* hp); // jichi 10/24/2014: Add generic hook function, return false if stop execution.
int(*length_fun)(uintptr_t stack, uintptr_t data); // data after padding added
char name[HOOK_NAME_SIZE]; char name[HOOK_NAME_SIZE];
}; };

View File

@ -63,7 +63,7 @@ namespace Engine
How to hook Mono/Unity3D: How to hook Mono/Unity3D:
Find all standard function prologs in memory with write/execute permission: these represent possible JIT compiled functions 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 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 Mono calling convention uses 'this' as first argument
Must be dynamic hook bootstrapped from other mono api or mono_domain_get won't work Must be dynamic hook bootstrapped from other mono api or mono_domain_get won't work
*/ */
trigger_fun = [](LPVOID addr, DWORD, DWORD) trigger_fun = [](LPVOID addr, DWORD, DWORD)
@ -74,8 +74,10 @@ namespace Engine
if (!getDomain || !getName || !getJitInfo) goto failed; if (!getDomain || !getName || !getJitInfo) goto failed;
static auto domain = getDomain(); static auto domain = getDomain();
if (!domain) goto failed; if (!domain) goto failed;
const BYTE prolog[] = { 0x55, 0x48, 0x8b, 0xec }; const BYTE prolog1[] = { 0x55, 0x48, 0x8b, 0xec };
for (auto addr : Util::SearchMemory(prolog, sizeof(prolog), PAGE_EXECUTE_READWRITE)) const BYTE prolog2[] = { 0x48, 0x83, 0xec };
for (auto [prolog, size] : Array<std::tuple<const BYTE*, size_t>>{ { prolog1, sizeof(prolog1) }, { prolog2, sizeof(prolog2) } })
for (auto addr : Util::SearchMemory(prolog, size, PAGE_EXECUTE_READWRITE))
{ {
[](uint64_t addr) [](uint64_t addr)
{ {
@ -83,13 +85,21 @@ namespace Engine
{ {
if (getJitInfo(domain, addr)) if (getJitInfo(domain, addr))
if (char* name = getName(addr)) if (char* name = getName(addr))
if (strstr(name, "string:") && !strstr(name, "string:mem")) if (strstr(name, "string:") && strstr(name, "+ 0x0") && !strstr(name, "string:mem"))
{ {
HookParam hp = {}; HookParam hp = {};
hp.address = addr; hp.address = addr;
hp.type = USING_STRING | USING_UNICODE; hp.type = USING_STRING | USING_UNICODE;
hp.offset = -0x20; hp.offset = -0x20;
hp.padding = 20; hp.padding = 20;
hp.length_fun = [](uintptr_t, uintptr_t data)
{
/* Artikash 6/18/2019:
even though this should get the true length mono uses internally
there's still some garbage picked up on https://vndb.org/v20403 demo, don't know why */
int len = *(int*)(data - 4);
return len > 0 && len < 1000 ? len * 2 : 0;
};
NewHook(hp, name); NewHook(hp, name);
} }
} }

View File

@ -298,6 +298,7 @@ void TextHook::Clear()
int TextHook::GetLength(uintptr_t base, uintptr_t in) int TextHook::GetLength(uintptr_t base, uintptr_t in)
{ {
int len; int len;
if (hp.length_fun) return hp.length_fun(base, in);
switch (hp.length_offset) { switch (hp.length_offset) {
default: // jichi 12/26/2013: I should not put this default branch to the end default: // jichi 12/26/2013: I should not put this default branch to the end
len = *((uintptr_t*)base + hp.length_offset); len = *((uintptr_t*)base + hp.length_offset);