dont remove mono if flooding, instead use config file for which hook to insert

This commit is contained in:
Akash Mozumdar 2020-02-27 04:26:01 -07:00
parent 565f99cced
commit c8853a1af8
6 changed files with 39 additions and 13 deletions

View File

@ -58,7 +58,6 @@ void TextThread::Push(BYTE* data, int length)
if (std::all_of(buffer.begin(), buffer.end(), [&](wchar_t ch) { return repeatingChars.find(ch) != repeatingChars.end(); })) buffer.clear(); if (std::all_of(buffer.begin(), buffer.end(), [&](wchar_t ch) { return repeatingChars.find(ch) != repeatingChars.end(); })) buffer.clear();
if (RemoveRepetition(buffer)) // sentence repetition detected, which means the entire sentence has already been received if (RemoveRepetition(buffer)) // sentence repetition detected, which means the entire sentence has already been received
{ {
if (hp.type & BLOCK_FLOOD) Host::RemoveHook(tp.processId, tp.addr);
repeatingChars = std::unordered_set(buffer.begin(), buffer.end()); repeatingChars = std::unordered_set(buffer.begin(), buffer.end());
AddSentence(std::move(buffer)); AddSentence(std::move(buffer));
buffer.clear(); buffer.clear();
@ -88,7 +87,6 @@ void TextThread::Flush()
sentence.erase(std::remove(sentence.begin(), sentence.end(), L'\0')); sentence.erase(std::remove(sentence.begin(), sentence.end(), L'\0'));
if (Output(*this, sentence)) storage->append(sentence); if (Output(*this, sentence)) storage->append(sentence);
} }
if (hp.type & BLOCK_FLOOD && totalSize > PIPE_BUFFER_SIZE) Host::RemoveHook(tp.processId, tp.addr);
std::scoped_lock lock(bufferMutex); std::scoped_lock lock(bufferMutex);
if (buffer.empty()) return; if (buffer.empty()) return;

View File

@ -4,7 +4,7 @@
// 8/23/2013 jichi // 8/23/2013 jichi
// Branch: ITH/common.h, rev 128 // Branch: ITH/common.h, rev 128
enum { STRING = 12, MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 10000, SHIFT_JIS = 932, MAX_MODULE_SIZE = 120, PATTERN_SIZE = 30, HOOK_NAME_SIZE = 30, FIXED_SPLIT_VALUE = 0x10001 }; enum { STRING = 12, MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 10000, SHIFT_JIS = 932, MAX_MODULE_SIZE = 120, PATTERN_SIZE = 30, HOOK_NAME_SIZE = 60, FIXED_SPLIT_VALUE = 0x10001 };
enum WildcardByte { XX = 0x11 }; enum WildcardByte { XX = 0x11 };
enum HostCommandType { HOST_COMMAND_NEW_HOOK, HOST_COMMAND_REMOVE_HOOK, HOST_COMMAND_FIND_HOOK, HOST_COMMAND_MODIFY_HOOK, HOST_COMMAND_HIJACK_PROCESS, HOST_COMMAND_DETACH }; enum HostCommandType { HOST_COMMAND_NEW_HOOK, HOST_COMMAND_REMOVE_HOOK, HOST_COMMAND_FIND_HOOK, HOST_COMMAND_MODIFY_HOOK, HOST_COMMAND_HIJACK_PROCESS, HOST_COMMAND_DETACH };
@ -27,8 +27,7 @@ enum HookParamType : unsigned
FIXING_SPLIT = 0x800, FIXING_SPLIT = 0x800,
DIRECT_READ = 0x1000, // /R read code instead of classic /H hook code DIRECT_READ = 0x1000, // /R read code instead of classic /H hook code
FULL_STRING = 0x2000, FULL_STRING = 0x2000,
BLOCK_FLOOD = 0x4000, // remove this hook if flooding text causing perf issues HEX_DUMP = 0x4000,
HEX_DUMP = 0x8000, HOOK_ENGINE = 0x8000,
HOOK_ENGINE = 0x10000, HOOK_ADDITIONAL = 0x10000,
HOOK_ADDITIONAL = 0x20000,
}; };

View File

@ -16717,6 +16717,7 @@ void InsertMonoHook(HMODULE h)
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;
ConsoleOutput("Textractor: Mono Dynamic ENTER (hook = %s)", loadedConfig ? loadedConfig : "brute force");
const BYTE prolog[] = { 0x55, 0x8b, 0xec }; const BYTE prolog[] = { 0x55, 0x8b, 0xec };
for (auto addr : Util::SearchMemory(prolog, sizeof(prolog), PAGE_EXECUTE_READWRITE)) for (auto addr : Util::SearchMemory(prolog, sizeof(prolog), PAGE_EXECUTE_READWRITE))
{ {
@ -16726,24 +16727,29 @@ void InsertMonoHook(HMODULE h)
{ {
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 ((!loadedConfig && strstr(name, "string:") && !strstr(name, "string:mem")) || (loadedConfig && strstr(name, loadedConfig)))
{ {
HookParam hp = {}; HookParam hp = {};
hp.address = addr; hp.address = addr;
hp.type = USING_UNICODE | FULL_STRING | BLOCK_FLOOD; hp.type = USING_UNICODE | FULL_STRING;
hp.offset = 4; hp.offset = 4;
char nameForUser[HOOK_NAME_SIZE] = {};
strncpy_s(nameForUser, name + 1, HOOK_NAME_SIZE - 1);
if (char* end = strstr(nameForUser, " + 0x0")) *end = 0;
hp.text_fun = [](DWORD esp_base, HookParam*, BYTE, DWORD* data, DWORD* split, DWORD* len) hp.text_fun = [](DWORD esp_base, HookParam*, BYTE, DWORD* data, DWORD* split, DWORD* len)
{ {
MonoString* string = (MonoString*)argof(1, esp_base); MonoString* string = (MonoString*)argof(1, esp_base);
*data = (DWORD)string->chars; *data = (DWORD)string->chars;
*len = string->length * 2; *len = string->length * 2;
}; };
NewHook(hp, name); NewHook(hp, nameForUser);
} }
} }
__except (EXCEPTION_EXECUTE_HANDLER) {} __except (EXCEPTION_EXECUTE_HANDLER) {}
}(addr); }(addr);
} }
if (!loadedConfig) ConsoleOutput("Textractor: Mono Dynamic used brute force: if performance issues arise, please create a TextractorConfig.txt file"
"next to the main executable and put the name of a working hook inside it");
return true; return true;
failed: failed:
ConsoleOutput("Textractor: Mono Dynamic failed"); ConsoleOutput("Textractor: Mono Dynamic failed");

View File

@ -15,6 +15,7 @@ namespace Engine {
// Global variables // Global variables
extern wchar_t *processName, // cached extern wchar_t *processName, // cached
processPath[MAX_PATH]; // cached processPath[MAX_PATH]; // cached
inline const char *requestedEngine = nullptr, *loadedConfig = nullptr;
// Artikash 6/17/2019 TODO: These have the wrong values on x64 // Artikash 6/17/2019 TODO: These have the wrong values on x64
/** jichi 12/24/2014 /** jichi 12/24/2014

View File

@ -12,6 +12,8 @@ namespace Engine
WCHAR* processName, // cached WCHAR* processName, // cached
processPath[MAX_PATH]; // cached processPath[MAX_PATH]; // cached
char configFileData[1000];
bool UnsafeDetermineEngineType(); bool UnsafeDetermineEngineType();
// jichi 10/21/2014: Return whether found the game engine // jichi 10/21/2014: Return whether found the game engine
@ -41,6 +43,19 @@ namespace Engine
{ {
GetModuleFileNameW(nullptr, processPath, MAX_PATH); GetModuleFileNameW(nullptr, processPath, MAX_PATH);
processName = wcsrchr(processPath, L'\\') + 1; processName = wcsrchr(processPath, L'\\') + 1;
wchar_t configFilename[MAX_PATH + sizeof(L"TextractorConfig.txt")];
wcsncpy_s(configFilename, processPath, MAX_PATH - 1);
wcscpy_s(wcsrchr(configFilename, L'\\') + 1, sizeof(L"TextractorConfig.txt"), L"TextractorConfig.txt");
if (AutoHandle<> configFile = CreateFileW(configFilename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))
{
if (ReadFile(configFile, configFileData, sizeof(configFileData) - 1, DUMMY, nullptr)) ConsoleOutput("Textractor: game configuration loaded");
if (strncmp(configFileData, "Engine:", 7) == 0)
{
if (loadedConfig = strchr(configFileData, '\n')) *(char*)loadedConfig++ = 0;
ConsoleOutput("Textractor: Engine = %s", requestedEngine = configFileData + 7);
}
else loadedConfig = configFileData;
}
processStartAddress = processStopAddress = (uintptr_t)GetModuleHandleW(nullptr); processStartAddress = processStopAddress = (uintptr_t)GetModuleHandleW(nullptr);
MEMORY_BASIC_INFORMATION info; MEMORY_BASIC_INFORMATION info;

View File

@ -80,6 +80,7 @@ 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;
ConsoleOutput("Textractor: Mono Dynamic ENTER (hook = %s)", loadedConfig ? loadedConfig : "brute force");
const BYTE prolog1[] = { 0x55, 0x48, 0x8b, 0xec }; const BYTE prolog1[] = { 0x55, 0x48, 0x8b, 0xec };
const BYTE prolog2[] = { 0x48, 0x83, 0xec }; const BYTE prolog2[] = { 0x48, 0x83, 0xec };
for (auto [prolog, size] : Array<const BYTE*, size_t>{ { prolog1, sizeof(prolog1) }, { prolog2, sizeof(prolog2) } }) for (auto [prolog, size] : Array<const BYTE*, size_t>{ { prolog1, sizeof(prolog1) }, { prolog2, sizeof(prolog2) } })
@ -91,13 +92,17 @@ 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, "+ 0x0") && !strstr(name, "string:mem")) if ((!loadedConfig && strstr(name, "string:") && strstr(name, "+ 0x0") && !strstr(name, "string:mem")) ||
loadedConfig && strstr(name, loadedConfig) && strstr(name, "+ 0x0"))
{ {
HookParam hp = {}; HookParam hp = {};
hp.address = addr; hp.address = addr;
hp.type = USING_STRING | USING_UNICODE | BLOCK_FLOOD | FULL_STRING; hp.type = USING_STRING | USING_UNICODE | FULL_STRING;
hp.offset = -0x20; // rcx hp.offset = -0x20; // rcx
hp.padding = 20; hp.padding = 20;
char nameForUser[HOOK_NAME_SIZE] = {};
strncpy_s(nameForUser, name + 1, HOOK_NAME_SIZE - 1);
if (char* end = strstr(nameForUser, " + 0x0")) *end = 0;
hp.length_fun = [](uintptr_t, uintptr_t data) hp.length_fun = [](uintptr_t, uintptr_t data)
{ {
/* Artikash 6/18/2019: /* Artikash 6/18/2019:
@ -106,12 +111,14 @@ namespace Engine
int len = *(int*)(data - 4); int len = *(int*)(data - 4);
return len > 0 && len < PIPE_BUFFER_SIZE ? len * 2 : 0; return len > 0 && len < PIPE_BUFFER_SIZE ? len * 2 : 0;
}; };
NewHook(hp, name); NewHook(hp, nameForUser);
} }
} }
__except (EXCEPTION_EXECUTE_HANDLER) {} __except (EXCEPTION_EXECUTE_HANDLER) {}
}(addr); }(addr);
} }
if (!loadedConfig) ConsoleOutput("Textractor: Mono Dynamic used brute force: if performance issues arise, please create a TextractorConfig.txt file"
"next to the main executable and put the name of a working hook inside it");
return true; return true;
failed: failed:
ConsoleOutput("Textractor: Mono Dynamic failed"); ConsoleOutput("Textractor: Mono Dynamic failed");