refactor/feat: Signature scan improvements

> use reverse pattern search instead, fixes performance issue for some hooks
> sigscan still requires overhead of module copy for each operation
This commit is contained in:
[ ]
2026-02-18 07:42:11 +09:00
parent 82439962d6
commit 0834646097
4 changed files with 104 additions and 70 deletions
+74 -41
View File
@@ -10,29 +10,30 @@
#include "util/utils.h"
intptr_t find_pattern(std::vector<uint8_t> &data, intptr_t base, const uint8_t *pattern,
const char *mask, intptr_t offset, intptr_t usage)
const char *mask, intptr_t offset, intptr_t usage, bool reverse)
{
return find_pattern_from(data, base, pattern, mask, offset, usage, 0);
return find_pattern_from(data, base, pattern, mask, offset, usage, 0, reverse);
}
intptr_t find_pattern(HMODULE module, const uint8_t *pattern, const char *mask,
intptr_t offset, intptr_t result_usage)
intptr_t offset, intptr_t result_usage, bool reverse)
{
return find_pattern_from(module, pattern, mask, offset, result_usage, 0);
return find_pattern_from(module, pattern, mask, offset, result_usage, 0, reverse);
}
intptr_t find_pattern(HMODULE module, const std::string &pattern, const char *mask,
intptr_t offset, intptr_t result_usage)
intptr_t offset, intptr_t result_usage, bool reverse)
{
return find_pattern_from(module, pattern, mask, offset, result_usage, 0);
return find_pattern_from(module, pattern, mask, offset, result_usage, 0, reverse);
}
///
intptr_t find_pattern_from(std::vector<uint8_t> &data, intptr_t base, const uint8_t *pattern,
const char *mask, intptr_t offset, intptr_t usage, intptr_t start_from)
const char *mask, intptr_t offset, intptr_t usage, intptr_t start_from, bool reverse)
{
// boundary check (mainly for result passthrough without validating)
if (start_from < 0 || usage < 0 || base < 0) return 0;
// build pattern
std::vector<std::pair<uint8_t, bool>> pattern_vector;
@@ -40,40 +41,71 @@ intptr_t find_pattern_from(std::vector<uint8_t> &data, intptr_t base, const uint
for (size_t i = 0; i < mask_size; i++) {
pattern_vector.emplace_back(pattern[i], mask[i] == 'X');
}
if (reverse) std::reverse(pattern_vector.begin(), pattern_vector.end());
// the scan loop
auto data_begin = data.begin();
std::advance(data_begin, start_from);
auto on_search = [&](uint8_t c, std::pair<uint8_t, bool> pat)
{
return (!pat.second) || c == pat.first;
};
auto cur_usage = 0;
while (true) {
if (!reverse)
{
auto data_begin = data.begin() + start_from;
while (true)
{
// search for the pattern
auto search_result = std::search(data_begin, data.end(), pattern_vector.begin(), pattern_vector.end(), on_search);
// search for the pattern
auto search_result = std::search(data_begin, data.end(), pattern_vector.begin(), pattern_vector.end(),
[&](uint8_t c, std::pair<uint8_t, bool> pat) {
return (!pat.second) || c == pat.first;
});
// check for a match
if (search_result != data.end())
{
// check for a match
if (search_result != data.end()) {
// return the result if we hit the usage count
if (cur_usage == usage)
{
return (std::distance(data.begin(), search_result) + base) + offset;
}
// return the result if we hit the usage count
if (cur_usage == usage) {
return (std::distance(data.begin(), search_result) + base) + offset;
// increment the found count
++cur_usage;
data_begin = ++search_result;
}
// increment the found count
++cur_usage;
data_begin = ++search_result;
} else {
break;
else break;
}
}
else
{
auto data_begin = std::make_reverse_iterator(start_from ? data.begin() + start_from + 1 : data.end());
while(true)
{
// search for the pattern
auto search_result = std::search(data_begin, data.rend(), pattern_vector.begin(), pattern_vector.end(), on_search);
// check for a match
if (search_result != data.rend())
{
// return the result if we hit the usage count
if (cur_usage == usage)
{
return (std::distance(data.begin(), search_result.base()) - pattern_vector.size() + base) + offset;
}
// increment the found count
++cur_usage;
data_begin = ++search_result;
}
else break;
}
}
return 0;
}
intptr_t find_pattern_from(HMODULE module, const uint8_t *pattern, const char *mask,
intptr_t offset, intptr_t result_usage, intptr_t start_from)
intptr_t offset, intptr_t result_usage, intptr_t start_from, bool reverse)
{
// get module information
MODULEINFO module_info {};
@@ -97,7 +129,8 @@ intptr_t find_pattern_from(HMODULE module, const uint8_t *pattern, const char *m
mask,
offset,
result_usage,
start_from);
start_from,
reverse);
} catch (const std::bad_alloc &e) {
log_warning("sigscan", "failed to allocate buffer of size {} for image data", size);
return false;
@@ -105,25 +138,24 @@ intptr_t find_pattern_from(HMODULE module, const uint8_t *pattern, const char *m
}
intptr_t find_pattern_from(HMODULE module, const std::string &pattern, const char *mask,
intptr_t offset, intptr_t result_usage, intptr_t start_from)
intptr_t offset, intptr_t result_usage, intptr_t start_from, bool reverse)
{
std::string pattern_str(pattern);
auto pattern_bin = std::make_unique<uint8_t[]>(pattern.length() / 2);
if (!hex2bin(pattern_str.c_str(), pattern_bin.get())) {
if (!hex2bin(pattern.c_str(), pattern_bin.get())) {
log_warning("sigscan", "hex2bin failed");
return false;
}
return find_pattern_from(module, pattern_bin.get(), mask, offset, result_usage, start_from);
return find_pattern_from(module, pattern_bin.get(), mask, offset, result_usage, start_from, reverse);
}
intptr_t replace_pattern_from(HMODULE module, const uint8_t *pattern, const char *mask, intptr_t offset,
intptr_t usage, intptr_t start_from, const uint8_t *replace_data, const char *replace_mask)
intptr_t usage, intptr_t start_from, const uint8_t *replace_data, const char *replace_mask, bool reverse)
{
// find result
auto result = find_pattern_from(module, pattern, mask, offset, usage, start_from);
auto result = find_pattern_from(module, pattern, mask, offset, usage, start_from, reverse);
// check result
if (!result) {
@@ -146,7 +178,7 @@ intptr_t replace_pattern_from(HMODULE module, const uint8_t *pattern, const char
}
intptr_t replace_pattern_from(HMODULE module, const std::string &signature,
const std::string &replacement, intptr_t offset, intptr_t usage, intptr_t start_from)
const std::string &replacement, intptr_t offset, intptr_t usage, intptr_t start_from, bool reverse)
{
// build pattern
std::string pattern_str(signature);
@@ -201,20 +233,21 @@ intptr_t replace_pattern_from(HMODULE module, const std::string &signature,
usage,
start_from,
replace_data_bin.get(),
replace_mask.str().c_str()
replace_mask.str().c_str(),
reverse
);
}
intptr_t replace_pattern(HMODULE module, const std::string &signature,
const std::string &replacement, intptr_t offset, intptr_t usage)
const std::string &replacement, intptr_t offset, intptr_t usage, bool reverse)
{
return replace_pattern_from(module, signature, replacement, offset, usage, 0);
return replace_pattern_from(module, signature, replacement, offset, usage, 0, reverse);
}
intptr_t replace_pattern(HMODULE module, const uint8_t *pattern, const char *mask, intptr_t offset,
intptr_t usage, const uint8_t *replace_data, const char *replace_mask)
intptr_t usage, const uint8_t *replace_data, const char *replace_mask, bool reverse)
{
return replace_pattern_from(module, pattern, mask, offset, usage, 0, replace_data, replace_mask);
return replace_pattern_from(module, pattern, mask, offset, usage, 0, replace_data, replace_mask, reverse);
}
bool get_pe_identifier(const std::filesystem::path& dll_path, uint32_t* time_date_stamp, uint32_t* address_of_entry_point) {
+20 -10
View File
@@ -14,21 +14,24 @@ intptr_t find_pattern(
const unsigned char *pattern,
const char *mask,
intptr_t offset,
intptr_t usage);
intptr_t usage,
bool reverse = false);
intptr_t find_pattern(
HMODULE module,
const unsigned char *pattern,
const char *mask,
intptr_t offset,
intptr_t usage);
intptr_t usage,
bool reverse = false);
intptr_t find_pattern(
HMODULE module,
const std::string &pattern,
const char *mask,
intptr_t offset,
intptr_t result_usage);
intptr_t result_usage,
bool reverse = false);
intptr_t find_pattern_from(
std::vector<unsigned char> &data,
@@ -37,7 +40,8 @@ intptr_t find_pattern_from(
const char *mask,
intptr_t offset,
intptr_t usage,
intptr_t start_from);
intptr_t start_from,
bool reverse = false);
intptr_t find_pattern_from(
HMODULE module,
@@ -45,7 +49,8 @@ intptr_t find_pattern_from(
const char *mask,
intptr_t offset,
intptr_t usage,
intptr_t start_from);
intptr_t start_from,
bool reverse = false);
intptr_t find_pattern_from(
HMODULE module,
@@ -53,7 +58,8 @@ intptr_t find_pattern_from(
const char *mask,
intptr_t offset,
intptr_t result_usage,
intptr_t start_from);
intptr_t start_from,
bool reverse = false);
intptr_t replace_pattern(
HMODULE module,
@@ -62,14 +68,16 @@ intptr_t replace_pattern(
intptr_t offset,
intptr_t usage,
const unsigned char *replace_data,
const char *replace_mask);
const char *replace_mask,
bool reverse = false);
intptr_t replace_pattern(
HMODULE module,
const std::string &signature,
const std::string &replacement,
intptr_t offset,
intptr_t usage);
intptr_t usage,
bool reverse = false);
intptr_t replace_pattern_from(
HMODULE module,
@@ -79,7 +87,8 @@ intptr_t replace_pattern_from(
intptr_t usage,
intptr_t start_from,
const unsigned char *replace_data,
const char *replace_mask);
const char *replace_mask,
bool reverse = false);
intptr_t replace_pattern_from(
HMODULE module,
@@ -87,7 +96,8 @@ intptr_t replace_pattern_from(
const std::string &replacement,
intptr_t offset,
intptr_t usage,
intptr_t start_from);
intptr_t start_from,
bool reverse = false);
bool get_pe_identifier(const std::filesystem::path& dll_path, uint32_t* time_date_stamp, uint32_t* address_of_entry_point);