forked from Public-Mirror/Textractor
dont remove mono if flooding, instead use config file for which hook to insert
This commit is contained in:
parent
565f99cced
commit
c8853a1af8
@ -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;
|
||||||
|
@ -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,
|
|
||||||
};
|
};
|
||||||
|
@ -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");
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user