refactor/feat: Further signature scan changes

> funcionality cleanup, API compatibility should be the same
> improve patching performance by skipping vector copy (replaced with span)
> chain call wrapper (fixes soudbank hook breaking 32-bit styles)
This commit is contained in:
[ ]
2026-02-20 18:36:42 +09:00
parent a7723148bc
commit ce0344742e
4 changed files with 91 additions and 48 deletions
+5 -2
View File
@@ -927,8 +927,11 @@ void init(HINSTANCE hmodule, const char *model, const char *ext)
}
// Override .text (pattern match)
offset_.TX_EnumValidSoundbanks = find_pattern_from(hmodule, "CCCCCCCCCCCCCCCC", "XXXXXXXX", 8, 0,
find_asm_leacstr_from(hmodule, R8, "%05d/%05d.2dx") - reinterpret_cast<intptr_t>(hmodule), true);
offset_.TX_EnumValidSoundbanks = patch_pipeline(
hmodule,
[](HMODULE hmodule, intptr_t addr) { return find_asm_leacstr_from(hmodule, R8, "%05d/%05d.2dx"); },
[](HMODULE hmodule, intptr_t addr) { return find_pattern_from(hmodule, "CCCCCCCCCCCCCCCC", "XXXXXXXX", 8, 0, addr, true); }
);
snd_bank::resampler_ = avcodec::BmswTranscoderResampler() == avcodec::bmswac_resampler_none ? snd_bank::resampler_ : avcodec::BmswTranscoderResampler();
offset_.TX_EnumValidSoundbanks = avcodec::BmswTranscoderEnumValidSoundbanksAddr() == 0x0 ? offset_.TX_EnumValidSoundbanks : (intptr_t) hmodule + (int64_t) avcodec::BmswTranscoderEnumValidSoundbanksAddr();
if (!offset_.TX_EnumValidSoundbanks)
+5 -2
View File
@@ -92,8 +92,11 @@ bool on_thum_exists_(void *titleUTF_getter, int32_t id, char flag)
void attach(HINSTANCE hmodule)
{
// Reverse lookup function head (PUSH RDI) for ThumExists() specific signature, quietly fail if invalid
intptr_t TX_ThumExists = find_pattern_from(hmodule, "4057", "XX", 0, 0,
find_pattern_from(hmodule, "83f801750c4084ff750732c0", "XXXXXXXXXXXX", 0, 0, 0) - reinterpret_cast<intptr_t>(hmodule), true);
intptr_t TX_ThumExists = patch_pipeline(
hmodule,
[](HMODULE hmodule, intptr_t addr) { return find_pattern_from(hmodule, "83f801750c4084ff750732c0", "XXXXXXXXXXXX", 0, 0, 0); },
[](HMODULE hmodule, intptr_t addr) { return find_pattern_from(hmodule, "4057", "XX", 0, 0, addr, true); }
);
log_info("hooks::wmisc::thumbnail", "Hooking ThumExists({})", reinterpret_cast<void *>(TX_ThumExists));
detour::trampoline_try(reinterpret_cast<void *>(TX_ThumExists), reinterpret_cast<void *>(on_thum_exists_), reinterpret_cast<void **>(&ThumExists));
}
+39 -33
View File
@@ -9,12 +9,18 @@
#include "util/memutils.h"
#include "util/utils.h"
intptr_t find_pattern(std::vector<uint8_t> &data, intptr_t base, const uint8_t *pattern,
intptr_t find_pattern(std::span<const unsigned char> data, intptr_t base, const uint8_t *pattern,
const char *mask, intptr_t offset, intptr_t usage, bool reverse)
{
return find_pattern_from(data, base, pattern, mask, offset, usage, 0, reverse);
}
intptr_t find_pattern(const std::vector<uint8_t> &data, intptr_t base, const uint8_t *pattern,
const char *mask, intptr_t offset, intptr_t usage, bool reverse)
{
return find_pattern_from(std::span<const unsigned char>(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, bool reverse)
{
@@ -29,12 +35,9 @@ intptr_t find_pattern(HMODULE module, const std::string &pattern, const char *ma
///
intptr_t find_pattern_from(std::vector<uint8_t> &data, intptr_t base, const uint8_t *pattern,
intptr_t find_pattern_from(std::span<const unsigned char> data, intptr_t base, const uint8_t *pattern,
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;
size_t mask_size = strlen(mask);
@@ -104,37 +107,26 @@ intptr_t find_pattern_from(std::vector<uint8_t> &data, intptr_t base, const uint
return 0;
}
intptr_t find_pattern_from(const 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, bool reverse)
{
return find_pattern_from(std::span<const unsigned char>(data), base, pattern, mask, offset, usage, start_from, reverse);
}
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, bool reverse)
{
// get module information
MODULEINFO module_info {};
if (!GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(module_info))) {
return 0;
}
auto size = static_cast<size_t>(module_info.SizeOfImage);
try {
// copy data
std::vector<uint8_t> data(size);
memcpy(data.data(), module_info.lpBaseOfDll, size);
// find pattern
intptr_t base;
auto data = get_module_data(module, &base);
return find_pattern_from(
data,
reinterpret_cast<intptr_t>(module_info.lpBaseOfDll),
base,
pattern,
mask,
offset,
result_usage,
start_from,
reverse);
} catch (const std::bad_alloc &e) {
log_warning("sigscan", "failed to allocate buffer of size {} for image data", size);
return false;
}
}
intptr_t find_pattern_from(HMODULE module, const std::string &pattern, const char *mask,
@@ -286,13 +278,10 @@ bool get_pe_identifier(const std::filesystem::path& dll_path, uint32_t* time_dat
intptr_t find_asm_leacstr_from(HMODULE module, reg_t reg, const char *cstr)
{
// get module information
MODULEINFO module_info{};
if (!GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(module_info)))
{
return 0;
}
const unsigned char *modbegp = reinterpret_cast<unsigned char *>(module);
const unsigned char *modendp = reinterpret_cast<unsigned char *>(module) + static_cast<size_t>(module_info.SizeOfImage);
intptr_t base;
auto data = get_module_data(module, &base);
const unsigned char *modbegp = data.data();
const unsigned char *modendp = data.data() + data.size();
// search cstr
const unsigned char *cstr_addr = std::search(
@@ -308,6 +297,7 @@ intptr_t find_asm_leacstr_from(HMODULE module, reg_t reg, const char *cstr)
#if defined(__i386__)
// find LEA REG, [abs32]
if (reg.t != GPR_32) return 0;
unsigned char asmop[6] = { 0x8D, reg.v, 0x00, 0x00, 0x00, 0x00};
int32_t dist32 = reinterpret_cast<int32_t>(cstr_addr);
memcpy(asmop + (sizeof(asmop) - 4), &dist32, 4);
@@ -316,7 +306,7 @@ intptr_t find_asm_leacstr_from(HMODULE module, reg_t reg, const char *cstr)
modendp,
asmop,
asmop + sizeof(asmop)
));
)) % reinterpret_cast<intptr_t>(modendp);
#elif defined(__x86_64__)
// find LEA REG, [RIP + rel32]
unsigned char rex = reg.t == GPR_EXT ? 0x4C : 0x48;
@@ -331,3 +321,19 @@ intptr_t find_asm_leacstr_from(HMODULE module, reg_t reg, const char *cstr)
return 0;
}
std::span<const unsigned char> get_module_data(HMODULE module, intptr_t *base)
{
// get module information
size_t sz = 0;
MODULEINFO module_info {};
if (GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(module_info))) {
sz = static_cast<size_t>(module_info.SizeOfImage);
}
// wrap data
std::span<const unsigned char> data(static_cast<const unsigned char*>(module_info.lpBaseOfDll), sz);
*base = reinterpret_cast<intptr_t>(module_info.lpBaseOfDll);
return data;
}
+33 -2
View File
@@ -5,11 +5,21 @@
#include <cstdint>
#include <vector>
#include <filesystem>
#include <span>
#include "windows.h"
#include "psapi.h"
intptr_t find_pattern(
std::vector<unsigned char> &data,
std::span<const unsigned char> data,
intptr_t base,
const unsigned char *pattern,
const char *mask,
intptr_t offset,
intptr_t usage,
bool reverse = false);
intptr_t find_pattern(
const std::vector<unsigned char> &data,
intptr_t base,
const unsigned char *pattern,
const char *mask,
@@ -34,7 +44,17 @@ intptr_t find_pattern(
bool reverse = false);
intptr_t find_pattern_from(
std::vector<unsigned char> &data,
std::span<const unsigned char> data,
intptr_t base,
const unsigned char *pattern,
const char *mask,
intptr_t offset,
intptr_t usage,
intptr_t start_from,
bool reverse = false);
intptr_t find_pattern_from(
const std::vector<unsigned char> &data,
intptr_t base,
const unsigned char *pattern,
const char *mask,
@@ -150,3 +170,14 @@ intptr_t find_asm_leacstr_from(
HMODULE module,
reg_t reg,
const char *cstr);
std::span<const unsigned char> get_module_data(HMODULE hmodule, intptr_t *base);
template <typename... Funcs>
intptr_t patch_pipeline(HMODULE module, Funcs&&... cbs) {
intptr_t base;
if(!get_module_data(module, &base).size()) return 0;
intptr_t addr = base; //_REV: needs implementing module updating logic in case of traversing between libraries
((addr && (addr = std::forward<Funcs>(cbs)(module, addr - base))), ...); // stop on first mismatch
return addr;
}