forked from Public-Mirror/Textractor
limit hook searches to a named module, also make 0 CCs default for x86 due to perf/stability improvements
This commit is contained in:
parent
bf2838f3fc
commit
3db37ac450
@ -31,6 +31,7 @@ extern const char* HOOK_SEARCH_UNSTABLE_WARNING;
|
||||
extern const char* SEARCH_CJK;
|
||||
extern const char* SEARCH_PATTERN;
|
||||
extern const char* SEARCH_DURATION;
|
||||
extern const char* SEARCH_MODULE;
|
||||
extern const char* PATTERN_OFFSET;
|
||||
extern const char* MIN_ADDRESS;
|
||||
extern const char* MAX_ADDRESS;
|
||||
@ -471,7 +472,7 @@ void MainWindow::FindHooks()
|
||||
{
|
||||
QDialog dialog(this, Qt::WindowCloseButtonHint);
|
||||
QFormLayout layout(&dialog);
|
||||
QLineEdit patternInput(x64 ? "CC CC 48 89" : "CC CC 55 8B EC", &dialog);
|
||||
QLineEdit patternInput(x64 ? "CC CC 48 89" : "55 8B EC", &dialog);
|
||||
assert(QByteArray::fromHex(patternInput.text().toUtf8()) == QByteArray((const char*)sp.pattern, sp.length));
|
||||
layout.addRow(SEARCH_PATTERN, &patternInput);
|
||||
for (auto [value, label] : Array<std::tuple<int&, const char*>>{
|
||||
@ -487,6 +488,8 @@ void MainWindow::FindHooks()
|
||||
layout.addRow(label, spinBox);
|
||||
connect(spinBox, qOverload<int>(&QSpinBox::valueChanged), [&value](int newValue) { value = newValue; });
|
||||
}
|
||||
QLineEdit boundInput(QFileInfo(S(Util::GetModuleFilename(GetSelectedProcessId()).value_or(L""))).fileName(), &dialog);
|
||||
layout.addRow(SEARCH_MODULE, &boundInput);
|
||||
for (auto [value, label] : Array<std::tuple<uintptr_t&, const char*>>{
|
||||
{ sp.minAddress, MIN_ADDRESS },
|
||||
{ sp.maxAddress, MAX_ADDRESS },
|
||||
@ -505,7 +508,7 @@ void MainWindow::FindHooks()
|
||||
if (!dialog.exec()) return;
|
||||
if (patternInput.text().contains('.'))
|
||||
{
|
||||
wcsncpy_s(sp.module, S(patternInput.text()).c_str(), MAX_MODULE_SIZE - 1);
|
||||
wcsncpy_s(sp.exportModule, S(patternInput.text()).c_str(), MAX_MODULE_SIZE - 1);
|
||||
sp.length = 1;
|
||||
}
|
||||
else
|
||||
@ -513,6 +516,7 @@ void MainWindow::FindHooks()
|
||||
QByteArray pattern = QByteArray::fromHex(patternInput.text().replace("??", QString::number(XX, 16)).toUtf8());
|
||||
memcpy(sp.pattern, pattern.data(), sp.length = min(pattern.size(), PATTERN_SIZE));
|
||||
}
|
||||
wcsncpy_s(sp.boundaryModule, S(boundInput.text()).c_str(), MAX_MODULE_SIZE - 1);
|
||||
try { filter = S(filterInput.text()); } catch (std::regex_error) {}
|
||||
}
|
||||
else
|
||||
|
@ -60,14 +60,16 @@ struct ThreadParam
|
||||
|
||||
struct SearchParam
|
||||
{
|
||||
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)
|
||||
offset = 2, // offset from start of pattern to add hook
|
||||
BYTE pattern[PATTERN_SIZE] = { x64 ? 0xcc : 0x55, x64 ? 0xcc : 0x8b, x64 ? 0x48 : 0xec, 0x89 }; // pattern in memory to search for
|
||||
int length = x64 ? 4 : 3, // length of pattern (zero means this SearchParam is invalid and the default should be used)
|
||||
offset = x64 ? 2 : 0, // offset from start of pattern to add hook
|
||||
searchTime = 20000, // ms
|
||||
maxRecords = 100000,
|
||||
codepage = SHIFT_JIS;
|
||||
uintptr_t padding = 0, minAddress = 0, maxAddress = (uintptr_t)-1;
|
||||
wchar_t module[MAX_MODULE_SIZE] = {};
|
||||
uintptr_t padding = 0, // same as hook param padding
|
||||
minAddress = 0, maxAddress = (uintptr_t)-1; // hook all functions between these addresses (used only if both modules empty)
|
||||
wchar_t boundaryModule[MAX_MODULE_SIZE] = {}; // hook all functions within this module (middle priority)
|
||||
wchar_t exportModule[MAX_MODULE_SIZE] = {}; // hook the exports of this module (highest priority)
|
||||
wchar_t text[PATTERN_SIZE] = {}; // text to search for
|
||||
void(*hookPostProcessor)(HookParam&) = nullptr;
|
||||
};
|
||||
|
1
text.cpp
1
text.cpp
@ -53,6 +53,7 @@ const char* HOOK_SEARCH_UNSTABLE_WARNING = u8"Searching for hooks is unstable! B
|
||||
const char* SEARCH_CJK = u8"Search for Chinese/Japanese/Korean";
|
||||
const char* SEARCH_PATTERN = u8"Search pattern (hex byte array)";
|
||||
const char* SEARCH_DURATION = u8"Search duration (ms)";
|
||||
const char* SEARCH_MODULE = u8"Search within module";
|
||||
const char* PATTERN_OFFSET = u8"Offset from pattern start";
|
||||
const char* MAX_HOOK_SEARCH_RECORDS = u8"Search result cap";
|
||||
const char* MIN_ADDRESS = u8"Minimum address (hex)";
|
||||
|
@ -200,19 +200,12 @@ void SearchForHooks(SearchParam spUser)
|
||||
|
||||
ConsoleOutput(STARTING_SEARCH);
|
||||
std::vector<uint64_t> addresses;
|
||||
if (*sp.module) addresses = GetFunctions((uintptr_t)GetModuleHandleW(sp.module));
|
||||
if (*sp.boundaryModule) std::tie(sp.minAddress, sp.maxAddress) = Util::QueryModuleLimits(GetModuleHandleW(sp.boundaryModule));
|
||||
if (*sp.exportModule) addresses = GetFunctions((uintptr_t)GetModuleHandleW(sp.exportModule));
|
||||
else for (auto& addr : addresses = Util::SearchMemory(sp.pattern, sp.length, PAGE_EXECUTE, sp.minAddress, sp.maxAddress)) addr += sp.offset;
|
||||
|
||||
uintptr_t moduleStartAddress = (uintptr_t)GetModuleHandleW(ITH_DLL);
|
||||
uintptr_t moduleStopAddress = moduleStartAddress;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
do
|
||||
{
|
||||
VirtualQuery((void*)moduleStopAddress, &info, sizeof(info));
|
||||
moduleStopAddress = (uintptr_t)info.BaseAddress + info.RegionSize;
|
||||
} while (info.Protect >= PAGE_EXECUTE);
|
||||
moduleStopAddress -= info.RegionSize;
|
||||
addresses.erase(std::remove_if(addresses.begin(), addresses.end(), [&](uint64_t addr) { return addr > moduleStartAddress && addr < moduleStopAddress; }), addresses.end());
|
||||
auto limits = Util::QueryModuleLimits(GetModuleHandleW(ITH_DLL));
|
||||
addresses.erase(std::remove_if(addresses.begin(), addresses.end(), [&](uint64_t addr) { return addr > limits.first && addr < limits.second; }), addresses.end());
|
||||
|
||||
auto trampolines = (decltype(trampoline)*)VirtualAlloc(NULL, sizeof(trampoline) * addresses.size(), MEM_COMMIT, PAGE_READWRITE);
|
||||
VirtualProtect(trampolines, addresses.size() * sizeof(trampoline), PAGE_EXECUTE_READWRITE, DUMMY);
|
||||
|
@ -301,6 +301,20 @@ bool SearchResourceString(LPCWSTR str)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<uint64_t, uint64_t> QueryModuleLimits(HMODULE module)
|
||||
{
|
||||
uintptr_t moduleStartAddress = (uintptr_t)module + 0x1000;
|
||||
uintptr_t moduleStopAddress = moduleStartAddress;
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
do
|
||||
{
|
||||
VirtualQuery((void*)moduleStopAddress, &info, sizeof(info));
|
||||
moduleStopAddress = (uintptr_t)info.BaseAddress + info.RegionSize;
|
||||
} while (info.Protect >= PAGE_EXECUTE);
|
||||
moduleStopAddress -= info.RegionSize;
|
||||
return { moduleStartAddress, moduleStopAddress };
|
||||
}
|
||||
|
||||
std::vector<uint64_t> SearchMemory(const void* bytes, short length, DWORD protect, uintptr_t minAddr, uintptr_t maxAddr)
|
||||
{
|
||||
SYSTEM_INFO systemInfo;
|
||||
|
@ -22,6 +22,7 @@ bool CheckFile(LPCWSTR name);
|
||||
|
||||
bool SearchResourceString(LPCWSTR str);
|
||||
|
||||
std::pair<uint64_t, uint64_t> QueryModuleLimits(HMODULE module);
|
||||
std::vector<uint64_t> SearchMemory(const void* bytes, short length, DWORD protect = PAGE_EXECUTE, uintptr_t minAddr = 0, uintptr_t maxAddr = -1ULL);
|
||||
|
||||
} // namespace Util
|
||||
|
Loading…
x
Reference in New Issue
Block a user