Asynchronous pattern scanning using std::async. (#770)
* feat(pattern): add support for double ? IDA sigs Co-authored-by: Yimura <24669514+Yimura@users.noreply.github.com>
This commit is contained in:
parent
23b016f4c8
commit
fd0b4ebd55
@ -29,6 +29,8 @@ namespace big
|
|||||||
|
|
||||||
void detour_hook::create_hook()
|
void detour_hook::create_hook()
|
||||||
{
|
{
|
||||||
|
if (!m_target) return;
|
||||||
|
|
||||||
fix_hook_address();
|
fix_hook_address();
|
||||||
if (auto status = MH_CreateHook(m_target, m_detour, &m_original); status != MH_OK)
|
if (auto status = MH_CreateHook(m_target, m_detour, &m_original); status != MH_OK)
|
||||||
throw std::runtime_error(std::format("Failed to create hook '{}' at 0x{:X} (error: {})", m_name, uintptr_t(m_target), MH_StatusToString(status)));
|
throw std::runtime_error(std::format("Failed to create hook '{}' at 0x{:X} (error: {})", m_name, uintptr_t(m_target), MH_StatusToString(status)));
|
||||||
@ -36,18 +38,24 @@ namespace big
|
|||||||
|
|
||||||
detour_hook::~detour_hook() noexcept
|
detour_hook::~detour_hook() noexcept
|
||||||
{
|
{
|
||||||
|
if (!m_target) return;
|
||||||
|
|
||||||
if (auto status = MH_RemoveHook(m_target); status != MH_OK)
|
if (auto status = MH_RemoveHook(m_target); status != MH_OK)
|
||||||
LOG(FATAL) << "Failed to remove hook '" << m_name << "' at 0x" << HEX_TO_UPPER(uintptr_t(m_target)) << "(error: " << m_name << ")";
|
LOG(FATAL) << "Failed to remove hook '" << m_name << "' at 0x" << HEX_TO_UPPER(uintptr_t(m_target)) << "(error: " << m_name << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void detour_hook::enable()
|
void detour_hook::enable()
|
||||||
{
|
{
|
||||||
|
if (!m_target) return;
|
||||||
|
|
||||||
if (auto status = MH_QueueEnableHook(m_target); status != MH_OK)
|
if (auto status = MH_QueueEnableHook(m_target); status != MH_OK)
|
||||||
throw std::runtime_error(std::format("Failed to enable hook 0x{:X} ({})", uintptr_t(m_target), MH_StatusToString(status)));
|
throw std::runtime_error(std::format("Failed to enable hook 0x{:X} ({})", uintptr_t(m_target), MH_StatusToString(status)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void detour_hook::disable()
|
void detour_hook::disable()
|
||||||
{
|
{
|
||||||
|
if (!m_target) return;
|
||||||
|
|
||||||
if (auto status = MH_QueueDisableHook(m_target); status != MH_OK)
|
if (auto status = MH_QueueDisableHook(m_target); status != MH_OK)
|
||||||
LOG(WARNING) << "Failed to disable hook '" << m_name << "'.";
|
LOG(WARNING) << "Failed to disable hook '" << m_name << "'.";
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,11 @@
|
|||||||
#include "batch.hpp"
|
#include "batch.hpp"
|
||||||
#include "range.hpp"
|
#include "range.hpp"
|
||||||
|
|
||||||
|
#include <future> //std::async
|
||||||
|
|
||||||
|
static std::mutex s_entry_mutex;
|
||||||
|
static std::vector<std::future<bool>> g_futures;
|
||||||
|
|
||||||
namespace memory
|
namespace memory
|
||||||
{
|
{
|
||||||
void batch::add(std::string name, pattern pattern, std::function<void(handle)> callback)
|
void batch::add(std::string name, pattern pattern, std::function<void(handle)> callback)
|
||||||
@ -10,38 +15,46 @@ namespace memory
|
|||||||
m_entries.emplace_back(std::move(name), std::move(pattern), std::move(callback));
|
m_entries.emplace_back(std::move(name), std::move(pattern), std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
void batch::run(range region)
|
bool scan_pattern_and_execute_callback(range region, memory::batch::entry entry)
|
||||||
{
|
|
||||||
bool all_found = true;
|
|
||||||
for (auto& entry : m_entries)
|
|
||||||
{
|
{
|
||||||
if (auto result = region.scan(entry.m_pattern))
|
if (auto result = region.scan(entry.m_pattern))
|
||||||
{
|
{
|
||||||
if (entry.m_callback)
|
if (entry.m_callback)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(s_entry_mutex); // Acquire a lock on the mutex to synchronize access.
|
||||||
|
|
||||||
std::invoke(std::move(entry.m_callback), result);
|
std::invoke(std::move(entry.m_callback), result);
|
||||||
std::stringstream file_out{}; //I hate this, but not logging it except on fail really helps on speed.
|
LOG(INFO) << "Found '" << entry.m_name << "' GTA5.exe+" << HEX_TO_UPPER(result.as<DWORD64>() - region.begin().as<DWORD64>());
|
||||||
file_out << "Found '" << entry.m_name << "' GTA5.exe+" << HEX_TO_UPPER(result.as<DWORD64>() - region.begin().as<DWORD64>());
|
|
||||||
big::g_log->file_out(file_out);
|
return true;
|
||||||
file_out.clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
all_found = false;
|
|
||||||
LOG(WARNING) << "Failed to find '" << entry.m_name << "'.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
all_found = false;
|
|
||||||
LOG(WARNING) << "Failed to find '" << entry.m_name << "'.";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_entries.clear();
|
LOG(WARNING) << "Failed to find '" << entry.m_name << "'.";
|
||||||
if (!all_found)
|
|
||||||
{
|
return false;
|
||||||
throw std::runtime_error("Failed to find some patterns.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool batch::run(range region)
|
||||||
|
{
|
||||||
|
for (auto& entry : m_entries)
|
||||||
|
{
|
||||||
|
g_futures.emplace_back(
|
||||||
|
std::async(&scan_pattern_and_execute_callback, region, entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found_all_patterns = true;
|
||||||
|
for (auto& future : g_futures)
|
||||||
|
{
|
||||||
|
future.wait();
|
||||||
|
|
||||||
|
if (!future.get())
|
||||||
|
found_all_patterns = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_entries.clear();
|
||||||
|
g_futures.clear();
|
||||||
|
|
||||||
|
return found_all_patterns;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ namespace memory
|
|||||||
~batch() noexcept = default;
|
~batch() noexcept = default;
|
||||||
|
|
||||||
void add(std::string name, pattern pattern, std::function<void(memory::handle)> callback);
|
void add(std::string name, pattern pattern, std::function<void(memory::handle)> callback);
|
||||||
void run(range region);
|
bool run(range region);
|
||||||
|
|
||||||
struct entry
|
struct entry
|
||||||
{
|
{
|
||||||
|
@ -79,6 +79,12 @@ namespace memory
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_bytes.push_back({});
|
m_bytes.push_back({});
|
||||||
|
|
||||||
|
// add support for double question mark sigs
|
||||||
|
if (ida_sig[i + 1] == '?')
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -811,7 +811,10 @@ namespace big
|
|||||||
});
|
});
|
||||||
|
|
||||||
auto mem_region = memory::module("GTA5.exe");
|
auto mem_region = memory::module("GTA5.exe");
|
||||||
main_batch.run(mem_region);
|
if (!main_batch.run(mem_region))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to find some patterns.");
|
||||||
|
}
|
||||||
|
|
||||||
memory::batch socialclub_batch;
|
memory::batch socialclub_batch;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user