mirror of
https://github.com/Artikash/Textractor.git
synced 2024-12-23 17:04:12 +08:00
more consistent hook searching ui and fix critical error in searching for text and custom codepage for hook searches
This commit is contained in:
parent
3f004554f8
commit
562c6e1a3a
@ -59,7 +59,7 @@ namespace
|
|||||||
};
|
};
|
||||||
|
|
||||||
size_t HashThreadParam(ThreadParam tp) { return std::hash<int64_t>()(tp.processId + tp.addr) + std::hash<int64_t>()(tp.ctx + tp.ctx2); }
|
size_t HashThreadParam(ThreadParam tp) { return std::hash<int64_t>()(tp.processId + tp.addr) + std::hash<int64_t>()(tp.ctx + tp.ctx2); }
|
||||||
Synchronized<std::unordered_map<ThreadParam, TextThread, Functor<HashThreadParam>>, std::recursive_mutex> textThreadsByParams;
|
Synchronized<std::unordered_map<ThreadParam, TextThread, Functor<HashThreadParam>>> textThreadsByParams;
|
||||||
Synchronized<std::unordered_map<DWORD, ProcessRecord>> processRecordsByIds;
|
Synchronized<std::unordered_map<DWORD, ProcessRecord>> processRecordsByIds;
|
||||||
|
|
||||||
Host::ProcessEventHandler OnConnect, OnDisconnect;
|
Host::ProcessEventHandler OnConnect, OnDisconnect;
|
||||||
@ -68,7 +68,10 @@ namespace
|
|||||||
void RemoveThreads(std::function<bool(ThreadParam)> removeIf)
|
void RemoveThreads(std::function<bool(ThreadParam)> removeIf)
|
||||||
{
|
{
|
||||||
std::vector<TextThread*> threadsToRemove;
|
std::vector<TextThread*> threadsToRemove;
|
||||||
|
{
|
||||||
|
auto textThreadsByParams = ::textThreadsByParams.Acquire();
|
||||||
std::for_each(textThreadsByParams->begin(), textThreadsByParams->end(), [&](auto& it) { if (removeIf(it.first)) threadsToRemove.push_back(&it.second); });
|
std::for_each(textThreadsByParams->begin(), textThreadsByParams->end(), [&](auto& it) { if (removeIf(it.first)) threadsToRemove.push_back(&it.second); });
|
||||||
|
}
|
||||||
for (auto thread : threadsToRemove)
|
for (auto thread : threadsToRemove)
|
||||||
{
|
{
|
||||||
OnDestroy(*thread);
|
OnDestroy(*thread);
|
||||||
@ -106,10 +109,9 @@ namespace
|
|||||||
std::wstring wide = info.text;
|
std::wstring wide = info.text;
|
||||||
if (wide.size() > STRING) OnHookFound(info.hp, info.text);
|
if (wide.size() > STRING) OnHookFound(info.hp, info.text);
|
||||||
info.hp.type &= ~USING_UNICODE;
|
info.hp.type &= ~USING_UNICODE;
|
||||||
if (auto converted = Util::StringToWideString((char*)info.text, Host::defaultCodepage))
|
if (auto converted = Util::StringToWideString((char*)info.text, info.hp.codepage))
|
||||||
if (converted->size() > STRING) OnHookFound(info.hp, converted.value());
|
if (converted->size() > STRING) OnHookFound(info.hp, converted.value());
|
||||||
info.hp.codepage = CP_UTF8;
|
if (auto converted = Util::StringToWideString((char*)info.text, info.hp.codepage = CP_UTF8))
|
||||||
if (auto converted = Util::StringToWideString((char*)info.text, CP_UTF8))
|
|
||||||
if (converted->size() > STRING) OnHookFound(info.hp, converted.value());
|
if (converted->size() > STRING) OnHookFound(info.hp, converted.value());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "host.h"
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
|
|
||||||
@ -47,28 +46,6 @@ namespace
|
|||||||
return hp;
|
return hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<HookParam> ParseSCode(std::wstring SCode)
|
|
||||||
{
|
|
||||||
std::wsmatch match;
|
|
||||||
HookParam hp = {};
|
|
||||||
hp.type |= READ_SEARCH;
|
|
||||||
|
|
||||||
// [codepage#]
|
|
||||||
if (std::regex_search(SCode, match, std::wregex(L"^([0-9]+)#")))
|
|
||||||
{
|
|
||||||
hp.codepage = std::stoi(match[1]);
|
|
||||||
SCode.erase(0, match[0].length());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hp.codepage = Host::defaultCodepage;
|
|
||||||
}
|
|
||||||
|
|
||||||
wcsncpy_s(hp.text, SCode.c_str(), MAX_MODULE_SIZE - 1);
|
|
||||||
|
|
||||||
return hp;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<HookParam> ParseHCode(std::wstring HCode)
|
std::optional<HookParam> ParseHCode(std::wstring HCode)
|
||||||
{
|
{
|
||||||
std::wsmatch match;
|
std::wsmatch match;
|
||||||
@ -325,7 +302,6 @@ namespace Util
|
|||||||
{
|
{
|
||||||
if (code[0] == L'/') code.erase(0, 1); // legacy/AGTH compatibility
|
if (code[0] == L'/') code.erase(0, 1); // legacy/AGTH compatibility
|
||||||
if (code[0] == L'R') return ParseRCode(code.erase(0, 1));
|
if (code[0] == L'R') return ParseRCode(code.erase(0, 1));
|
||||||
else if (code[0] == L'S') return ParseSCode(code.erase(0, 1));
|
|
||||||
else if (code[0] == L'H') return ParseHCode(code.erase(0, 1));
|
else if (code[0] == L'H') return ParseHCode(code.erase(0, 1));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@ extern const char* MAX_ADDRESS;
|
|||||||
extern const char* STRING_OFFSET;
|
extern const char* STRING_OFFSET;
|
||||||
extern const char* MAX_HOOK_SEARCH_RECORDS;
|
extern const char* MAX_HOOK_SEARCH_RECORDS;
|
||||||
extern const char* HOOK_SEARCH_FILTER;
|
extern const char* HOOK_SEARCH_FILTER;
|
||||||
|
extern const char* SEARCH_FOR_TEXT;
|
||||||
|
extern const char* TEXT;
|
||||||
|
extern const char* CODEPAGE;
|
||||||
extern const char* START_HOOK_SEARCH;
|
extern const char* START_HOOK_SEARCH;
|
||||||
extern const char* SAVE_SEARCH_RESULTS;
|
extern const char* SAVE_SEARCH_RESULTS;
|
||||||
extern const char* TEXT_FILES;
|
extern const char* TEXT_FILES;
|
||||||
@ -360,7 +363,8 @@ void MainWindow::AddHook()
|
|||||||
void MainWindow::AddHook(QString hook)
|
void MainWindow::AddHook(QString hook)
|
||||||
{
|
{
|
||||||
if (QString hookCode = QInputDialog::getText(this, ADD_HOOK, CODE_INFODUMP, QLineEdit::Normal, hook, &ok, Qt::WindowCloseButtonHint); ok)
|
if (QString hookCode = QInputDialog::getText(this, ADD_HOOK, CODE_INFODUMP, QLineEdit::Normal, hook, &ok, Qt::WindowCloseButtonHint); ok)
|
||||||
if (auto hp = Util::ParseCode(S(hookCode))) try { Host::InsertHook(GetSelectedProcessId(), hp.value()); } catch (std::out_of_range) {}
|
if (hookCode.startsWith("S") || hookCode.startsWith("/S")) FindHooks();
|
||||||
|
else if (auto hp = Util::ParseCode(S(hookCode))) try { Host::InsertHook(GetSelectedProcessId(), hp.value()); } catch (std::out_of_range) {}
|
||||||
else Host::AddConsoleOutput(INVALID_CODE);
|
else Host::AddConsoleOutput(INVALID_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,23 +422,48 @@ void MainWindow::FindHooks()
|
|||||||
|
|
||||||
DWORD processId = GetSelectedProcessId();
|
DWORD processId = GetSelectedProcessId();
|
||||||
SearchParam sp = {};
|
SearchParam sp = {};
|
||||||
bool customSettings = false;
|
sp.codepage = Host::defaultCodepage;
|
||||||
|
bool searchForText = false, customSettings = false;
|
||||||
std::wregex filter(L".");
|
std::wregex filter(L".");
|
||||||
|
|
||||||
QDialog dialog(this, Qt::WindowCloseButtonHint);
|
QDialog dialog(this, Qt::WindowCloseButtonHint);
|
||||||
QFormLayout layout(&dialog);
|
QFormLayout layout(&dialog);
|
||||||
QCheckBox cjkCheckbox(&dialog);
|
QCheckBox cjkCheckbox(&dialog);
|
||||||
layout.addRow(SEARCH_CJK, &cjkCheckbox);
|
layout.addRow(SEARCH_CJK, &cjkCheckbox);
|
||||||
QDialogButtonBox confirm(QDialogButtonBox::Ok | QDialogButtonBox::Help, &dialog);
|
QDialogButtonBox confirm(QDialogButtonBox::Ok | QDialogButtonBox::Help | QDialogButtonBox::Retry, &dialog);
|
||||||
layout.addRow(&confirm);
|
layout.addRow(&confirm);
|
||||||
confirm.button(QDialogButtonBox::Ok)->setText(START_HOOK_SEARCH);
|
confirm.button(QDialogButtonBox::Ok)->setText(START_HOOK_SEARCH);
|
||||||
|
confirm.button(QDialogButtonBox::Retry)->setText(SEARCH_FOR_TEXT);
|
||||||
confirm.button(QDialogButtonBox::Help)->setText(SETTINGS);
|
confirm.button(QDialogButtonBox::Help)->setText(SETTINGS);
|
||||||
connect(&confirm, &QDialogButtonBox::helpRequested, [&customSettings] { customSettings = true; });
|
connect(&confirm, &QDialogButtonBox::clicked, [&](QAbstractButton* button)
|
||||||
connect(&confirm, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
{
|
||||||
connect(&confirm, &QDialogButtonBox::helpRequested, &dialog, &QDialog::accept);
|
if (button == confirm.button(QDialogButtonBox::Retry)) searchForText = true;
|
||||||
|
if (button == confirm.button(QDialogButtonBox::Help)) customSettings = true;
|
||||||
|
dialog.accept();
|
||||||
|
});
|
||||||
dialog.setWindowTitle(SEARCH_FOR_HOOKS);
|
dialog.setWindowTitle(SEARCH_FOR_HOOKS);
|
||||||
if (!dialog.exec()) return;
|
if (!dialog.exec()) return;
|
||||||
|
|
||||||
|
if (searchForText)
|
||||||
|
{
|
||||||
|
QDialog dialog(this, Qt::WindowCloseButtonHint);
|
||||||
|
QFormLayout layout(&dialog);
|
||||||
|
QLineEdit textInput(&dialog);
|
||||||
|
layout.addRow(TEXT, &textInput);
|
||||||
|
QSpinBox codepageInput(&dialog);
|
||||||
|
codepageInput.setMaximum(INT_MAX);
|
||||||
|
codepageInput.setValue(sp.codepage);
|
||||||
|
layout.addRow(CODEPAGE, &codepageInput);
|
||||||
|
QDialogButtonBox confirm(QDialogButtonBox::Ok);
|
||||||
|
connect(&confirm, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||||
|
layout.addRow(&confirm);
|
||||||
|
if (!dialog.exec()) return;
|
||||||
|
wcsncpy_s(sp.text, S(textInput.text()).c_str(), PATTERN_SIZE - 1);
|
||||||
|
try { Host::FindHooks(GetSelectedProcessId(), sp); }
|
||||||
|
catch (std::out_of_range) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (customSettings)
|
if (customSettings)
|
||||||
{
|
{
|
||||||
QDialog dialog(this, Qt::WindowCloseButtonHint);
|
QDialog dialog(this, Qt::WindowCloseButtonHint);
|
||||||
@ -446,6 +475,7 @@ void MainWindow::FindHooks()
|
|||||||
{ sp.searchTime, SEARCH_DURATION },
|
{ sp.searchTime, SEARCH_DURATION },
|
||||||
{ sp.offset, PATTERN_OFFSET },
|
{ sp.offset, PATTERN_OFFSET },
|
||||||
{ sp.maxRecords, MAX_HOOK_SEARCH_RECORDS },
|
{ sp.maxRecords, MAX_HOOK_SEARCH_RECORDS },
|
||||||
|
{ sp.codepage, CODEPAGE },
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
auto spinBox = new QSpinBox(&dialog);
|
auto spinBox = new QSpinBox(&dialog);
|
||||||
|
@ -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 = 2000, SHIFT_JIS = 932, MAX_MODULE_SIZE = 120, HOOK_NAME_SIZE = 30, FIXED_SPLIT_VALUE = 0x10001 };
|
enum { STRING = 12, MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 2000, SHIFT_JIS = 932, MAX_MODULE_SIZE = 120, PATTERN_SIZE = 30, HOOK_NAME_SIZE = 30, 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 };
|
||||||
@ -22,12 +22,11 @@ enum HookParamType : unsigned
|
|||||||
MODULE_OFFSET = 0x40, // address is relative to module
|
MODULE_OFFSET = 0x40, // address is relative to module
|
||||||
FUNCTION_OFFSET = 0x80, // address is relative to function
|
FUNCTION_OFFSET = 0x80, // address is relative to function
|
||||||
USING_UTF8 = 0x100,
|
USING_UTF8 = 0x100,
|
||||||
READ_SEARCH = 0x200, // unspecified address: search for text instead
|
NO_CONTEXT = 0x200,
|
||||||
NO_CONTEXT = 0x400,
|
HOOK_EMPTY = 0x400,
|
||||||
HOOK_EMPTY = 0x800,
|
FIXING_SPLIT = 0x800,
|
||||||
FIXING_SPLIT = 0x1000,
|
DIRECT_READ = 0x1000, // /R read code instead of classic /H hook code
|
||||||
DIRECT_READ = 0x2000, // /R read code instead of classic /H hook code
|
FULL_STRING = 0x2000,
|
||||||
FULL_STRING = 0x4000,
|
HOOK_ENGINE = 0x4000,
|
||||||
HOOK_ENGINE = 0x8000,
|
HOOK_ADDITIONAL = 0x8000,
|
||||||
HOOK_ADDITIONAL = 0x10000,
|
|
||||||
};
|
};
|
||||||
|
@ -31,11 +31,9 @@ struct HookParam
|
|||||||
split, // offset of the split character
|
split, // offset of the split character
|
||||||
split_index, // deref_offset2
|
split_index, // deref_offset2
|
||||||
null_length;
|
null_length;
|
||||||
union
|
|
||||||
{
|
|
||||||
wchar_t module[MAX_MODULE_SIZE];
|
wchar_t module[MAX_MODULE_SIZE];
|
||||||
wchar_t text[MAX_MODULE_SIZE];
|
|
||||||
};
|
|
||||||
char function[MAX_MODULE_SIZE];
|
char function[MAX_MODULE_SIZE];
|
||||||
DWORD type; // flags
|
DWORD type; // flags
|
||||||
UINT codepage; // text encoding
|
UINT codepage; // text encoding
|
||||||
@ -62,12 +60,14 @@ struct ThreadParam
|
|||||||
|
|
||||||
struct SearchParam
|
struct SearchParam
|
||||||
{
|
{
|
||||||
BYTE pattern[25] = { 0xcc, 0xcc, x64 ? 0x48 : 0x55, x64 ? 0x89 : 0x8b, 0xec }; // pattern in memory to search for
|
BYTE pattern[PATTERN_SIZE] = { 0xcc, 0xcc, x64 ? 0x48 : 0x55, x64 ? 0x89 : 0x8b, 0xec }; // pattern in memory to search for
|
||||||
int length = x64 ? 4 : 5, // length of pattern (zero means this SearchParam is invalid and the default should be used)
|
int length = x64 ? 4 : 5, // length of pattern (zero means this SearchParam is invalid and the default should be used)
|
||||||
offset = 2, // offset from start of pattern to add hook
|
offset = 2, // offset from start of pattern to add hook
|
||||||
searchTime = 20000, // ms
|
searchTime = 20000, // ms
|
||||||
maxRecords = 100000;
|
maxRecords = 100000,
|
||||||
|
codepage = SHIFT_JIS;
|
||||||
uintptr_t padding = 0, minAddress = 0, maxAddress = (uintptr_t)-1;
|
uintptr_t padding = 0, minAddress = 0, maxAddress = (uintptr_t)-1;
|
||||||
|
wchar_t text[PATTERN_SIZE] = {}; // text to search for
|
||||||
void(*hookPostProcessor)(HookParam&) = nullptr;
|
void(*hookPostProcessor)(HookParam&) = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
3
text.cpp
3
text.cpp
@ -63,6 +63,9 @@ const char* MIN_ADDRESS = u8"Minimum address (hex)";
|
|||||||
const char* MAX_ADDRESS = u8"Maximum address (hex)";
|
const char* MAX_ADDRESS = u8"Maximum address (hex)";
|
||||||
const char* STRING_OFFSET = u8"String offset (hex)";
|
const char* STRING_OFFSET = u8"String offset (hex)";
|
||||||
const char* HOOK_SEARCH_FILTER = u8"Results must match this regex";
|
const char* HOOK_SEARCH_FILTER = u8"Results must match this regex";
|
||||||
|
const char* TEXT = u8"Text";
|
||||||
|
const char* CODEPAGE = u8"Codepage";
|
||||||
|
const char* SEARCH_FOR_TEXT = u8"Search for specific text";
|
||||||
const char* START_HOOK_SEARCH = u8"Start hook search";
|
const char* START_HOOK_SEARCH = u8"Start hook search";
|
||||||
const char* SAVE_SEARCH_RESULTS = u8"Save search results";
|
const char* SAVE_SEARCH_RESULTS = u8"Save search results";
|
||||||
const char* TEXT_FILES = u8"Text (*.txt)";
|
const char* TEXT_FILES = u8"Text (*.txt)";
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
extern const char* STARTING_SEARCH;
|
extern const char* STARTING_SEARCH;
|
||||||
extern const char* HOOK_SEARCH_INITIALIZED;
|
extern const char* HOOK_SEARCH_INITIALIZED;
|
||||||
extern const char* HOOK_SEARCH_FINISHED;
|
extern const char* HOOK_SEARCH_FINISHED;
|
||||||
|
extern const char* NOT_ENOUGH_TEXT;
|
||||||
|
extern const char* COULD_NOT_FIND;
|
||||||
|
|
||||||
extern WinMutex viewMutex;
|
extern WinMutex viewMutex;
|
||||||
|
|
||||||
@ -24,6 +26,7 @@ namespace
|
|||||||
hp.type = USING_UNICODE | USING_STRING;
|
hp.type = USING_UNICODE | USING_STRING;
|
||||||
hp.address = address;
|
hp.address = address;
|
||||||
hp.padding = sp.padding;
|
hp.padding = sp.padding;
|
||||||
|
hp.codepage = sp.codepage;
|
||||||
if (sp.hookPostProcessor) sp.hookPostProcessor(hp);
|
if (sp.hookPostProcessor) sp.hookPostProcessor(hp);
|
||||||
NotifyHookFound(hp, (wchar_t*)text);
|
NotifyHookFound(hp, (wchar_t*)text);
|
||||||
}
|
}
|
||||||
@ -204,3 +207,31 @@ void SearchForHooks(SearchParam spUser)
|
|||||||
ConsoleOutput(HOOK_SEARCH_FINISHED, sp.maxRecords - recordsAvailable);
|
ConsoleOutput(HOOK_SEARCH_FINISHED, sp.maxRecords - recordsAvailable);
|
||||||
}).detach();
|
}).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchForText(wchar_t* text, UINT codepage)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
char utf8Text[PATTERN_SIZE * 4] = {};
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, text, PATTERN_SIZE, utf8Text, PATTERN_SIZE * 4, nullptr, nullptr);
|
||||||
|
char codepageText[PATTERN_SIZE * 4] = {};
|
||||||
|
WideCharToMultiByte(codepage, 0, text, PATTERN_SIZE, codepageText, PATTERN_SIZE * 4, nullptr, nullptr);
|
||||||
|
if (strlen(utf8Text) < 4 || strlen(codepageText) < 4 || wcslen(text) < 4) return ConsoleOutput(NOT_ENOUGH_TEXT);
|
||||||
|
ConsoleOutput(STARTING_SEARCH);
|
||||||
|
auto GenerateHooks = [&](std::vector<uint64_t> addresses, HookParamType type)
|
||||||
|
{
|
||||||
|
for (auto addr : addresses)
|
||||||
|
{
|
||||||
|
if (abs((long long)(utf8Text - addr)) < 20000) continue; // don't add read code if text is on this thread's stack
|
||||||
|
found = true;
|
||||||
|
HookParam hp = {};
|
||||||
|
hp.type = DIRECT_READ | type;
|
||||||
|
hp.address = addr;
|
||||||
|
hp.codepage = codepage;
|
||||||
|
NewHook(hp, "Search", 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
GenerateHooks(Util::SearchMemory(utf8Text, strlen(utf8Text), PAGE_READWRITE), USING_UTF8);
|
||||||
|
GenerateHooks(Util::SearchMemory(codepageText, strlen(codepageText), PAGE_READWRITE), USING_STRING);
|
||||||
|
GenerateHooks(Util::SearchMemory(text, wcslen(text) * sizeof(wchar_t), PAGE_READWRITE), USING_UNICODE);
|
||||||
|
if (!found) ConsoleOutput(COULD_NOT_FIND);
|
||||||
|
}
|
||||||
|
@ -3,5 +3,5 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
void SearchForText(wchar_t* text);
|
void SearchForText(wchar_t* text, UINT codepage);
|
||||||
void SearchForHooks(SearchParam sp);
|
void SearchForHooks(SearchParam sp);
|
||||||
|
@ -15,9 +15,6 @@ extern const char* INSERTING_HOOK;
|
|||||||
extern const char* REMOVING_HOOK;
|
extern const char* REMOVING_HOOK;
|
||||||
extern const char* HOOK_FAILED;
|
extern const char* HOOK_FAILED;
|
||||||
extern const char* TOO_MANY_HOOKS;
|
extern const char* TOO_MANY_HOOKS;
|
||||||
extern const char* STARTING_SEARCH;
|
|
||||||
extern const char* NOT_ENOUGH_TEXT;
|
|
||||||
extern const char* COULD_NOT_FIND;
|
|
||||||
|
|
||||||
WinMutex viewMutex;
|
WinMutex viewMutex;
|
||||||
|
|
||||||
@ -74,7 +71,8 @@ DWORD WINAPI Pipe(LPVOID)
|
|||||||
case HOST_COMMAND_FIND_HOOK:
|
case HOST_COMMAND_FIND_HOOK:
|
||||||
{
|
{
|
||||||
auto info = *(FindHookCmd*)buffer;
|
auto info = *(FindHookCmd*)buffer;
|
||||||
SearchForHooks(info.sp);
|
if (*info.sp.text) SearchForText(info.sp.text, info.sp.codepage);
|
||||||
|
else SearchForHooks(info.sp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOST_COMMAND_DETACH:
|
case HOST_COMMAND_DETACH:
|
||||||
@ -156,34 +154,6 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
|
|||||||
|
|
||||||
void NewHook(HookParam hp, LPCSTR lpname, DWORD flag)
|
void NewHook(HookParam hp, LPCSTR lpname, DWORD flag)
|
||||||
{
|
{
|
||||||
if (hp.type & READ_SEARCH)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
char utf8Text[MAX_MODULE_SIZE * 4] = {};
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, hp.text, MAX_MODULE_SIZE, utf8Text, MAX_MODULE_SIZE * 4, nullptr, nullptr);
|
|
||||||
char codepageText[MAX_MODULE_SIZE * 4] = {};
|
|
||||||
WideCharToMultiByte(hp.codepage, 0, hp.text, MAX_MODULE_SIZE, codepageText, MAX_MODULE_SIZE * 4, nullptr, nullptr);
|
|
||||||
if (strlen(utf8Text) < 8 || strlen(codepageText) < 8 || wcslen(hp.text) < 4) return ConsoleOutput(NOT_ENOUGH_TEXT);
|
|
||||||
ConsoleOutput(STARTING_SEARCH);
|
|
||||||
for (auto [addrs, type] : Array<std::tuple<std::vector<uint64_t>, HookParamType>>{
|
|
||||||
{ Util::SearchMemory(utf8Text, strlen(utf8Text), PAGE_READWRITE), USING_UTF8 },
|
|
||||||
{ Util::SearchMemory(codepageText, strlen(codepageText), PAGE_READWRITE), USING_STRING },
|
|
||||||
{ Util::SearchMemory(hp.text, wcslen(hp.text) * 2, PAGE_READWRITE), USING_UNICODE }
|
|
||||||
})
|
|
||||||
for (auto addr : addrs)
|
|
||||||
{
|
|
||||||
if (abs((long long)(utf8Text - addr)) < 20000) continue; // don't add read code if text is on this thread's stack
|
|
||||||
found = true;
|
|
||||||
HookParam h = {};
|
|
||||||
h.type = DIRECT_READ | type;
|
|
||||||
h.address = addr;
|
|
||||||
h.codepage = hp.codepage;
|
|
||||||
NewHook(h, lpname, 0);
|
|
||||||
}
|
|
||||||
if (!found) ConsoleOutput(COULD_NOT_FIND);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (++currentHook >= MAX_HOOK) return ConsoleOutput(TOO_MANY_HOOKS);
|
if (++currentHook >= MAX_HOOK) return ConsoleOutput(TOO_MANY_HOOKS);
|
||||||
if (lpname && *lpname) strncpy_s(hp.name, lpname, HOOK_NAME_SIZE - 1);
|
if (lpname && *lpname) strncpy_s(hp.name, lpname, HOOK_NAME_SIZE - 1);
|
||||||
ConsoleOutput(INSERTING_HOOK, hp.name);
|
ConsoleOutput(INSERTING_HOOK, hp.name);
|
||||||
@ -193,7 +163,6 @@ void NewHook(HookParam hp, LPCSTR lpname, DWORD flag)
|
|||||||
ConsoleOutput(HOOK_FAILED);
|
ConsoleOutput(HOOK_FAILED);
|
||||||
(*hooks)[currentHook].Clear();
|
(*hooks)[currentHook].Clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveHook(uint64_t addr, int maxOffset)
|
void RemoveHook(uint64_t addr, int maxOffset)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user