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
UINT codepage; // text encoding
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
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(*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];
};

View File

@ -63,7 +63,7 @@ namespace Engine
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
Mono calling convention uses 'this' as first argument
Must be dynamic hook bootstrapped from other mono api or mono_domain_get won't work
*/
trigger_fun = [](LPVOID addr, DWORD, DWORD)
@ -74,8 +74,10 @@ namespace Engine
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))
const BYTE prolog1[] = { 0x55, 0x48, 0x8b, 0xec };
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)
{
@ -83,13 +85,21 @@ namespace Engine
{
if (getJitInfo(domain, 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 = {};
hp.address = addr;
hp.type = USING_STRING | USING_UNICODE;
hp.offset = -0x20;
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);
}
}

View File

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