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()
|
||||
{
|
||||
if (!m_target) return;
|
||||
|
||||
fix_hook_address();
|
||||
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)));
|
||||
@ -36,18 +38,24 @@ namespace big
|
||||
|
||||
detour_hook::~detour_hook() noexcept
|
||||
{
|
||||
if (!m_target) return;
|
||||
|
||||
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 << ")";
|
||||
}
|
||||
|
||||
void detour_hook::enable()
|
||||
{
|
||||
if (!m_target) return;
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
void detour_hook::disable()
|
||||
{
|
||||
if (!m_target) return;
|
||||
|
||||
if (auto status = MH_QueueDisableHook(m_target); status != MH_OK)
|
||||
LOG(WARNING) << "Failed to disable hook '" << m_name << "'.";
|
||||
}
|
||||
|
@ -3,6 +3,11 @@
|
||||
#include "batch.hpp"
|
||||
#include "range.hpp"
|
||||
|
||||
#include <future> //std::async
|
||||
|
||||
static std::mutex s_entry_mutex;
|
||||
static std::vector<std::future<bool>> g_futures;
|
||||
|
||||
namespace memory
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
void batch::run(range region)
|
||||
bool scan_pattern_and_execute_callback(range region, memory::batch::entry entry)
|
||||
{
|
||||
if (auto result = region.scan(entry.m_pattern))
|
||||
{
|
||||
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);
|
||||
LOG(INFO) << "Found '" << entry.m_name << "' GTA5.exe+" << HEX_TO_UPPER(result.as<DWORD64>() - region.begin().as<DWORD64>());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(WARNING) << "Failed to find '" << entry.m_name << "'.";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool batch::run(range region)
|
||||
{
|
||||
bool all_found = true;
|
||||
for (auto& entry : m_entries)
|
||||
{
|
||||
if (auto result = region.scan(entry.m_pattern))
|
||||
{
|
||||
if (entry.m_callback)
|
||||
{
|
||||
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.
|
||||
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);
|
||||
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 << "'.";
|
||||
}
|
||||
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();
|
||||
if (!all_found)
|
||||
{
|
||||
throw std::runtime_error("Failed to find some patterns.");
|
||||
}
|
||||
g_futures.clear();
|
||||
|
||||
return found_all_patterns;
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ namespace memory
|
||||
~batch() noexcept = default;
|
||||
|
||||
void add(std::string name, pattern pattern, std::function<void(memory::handle)> callback);
|
||||
void run(range region);
|
||||
bool run(range region);
|
||||
|
||||
struct entry
|
||||
{
|
||||
|
@ -79,6 +79,12 @@ namespace memory
|
||||
else
|
||||
{
|
||||
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");
|
||||
main_batch.run(mem_region);
|
||||
if (!main_batch.run(mem_region))
|
||||
{
|
||||
throw std::runtime_error("Failed to find some patterns.");
|
||||
}
|
||||
|
||||
memory::batch socialclub_batch;
|
||||
|
||||
|
Reference in New Issue
Block a user