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:
+5
-2
@@ -927,8 +927,11 @@ void init(HINSTANCE hmodule, const char *model, const char *ext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Override .text (pattern match)
|
// Override .text (pattern match)
|
||||||
offset_.TX_EnumValidSoundbanks = find_pattern_from(hmodule, "CCCCCCCCCCCCCCCC", "XXXXXXXX", 8, 0,
|
offset_.TX_EnumValidSoundbanks = patch_pipeline(
|
||||||
find_asm_leacstr_from(hmodule, R8, "%05d/%05d.2dx") - reinterpret_cast<intptr_t>(hmodule), true);
|
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();
|
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();
|
offset_.TX_EnumValidSoundbanks = avcodec::BmswTranscoderEnumValidSoundbanksAddr() == 0x0 ? offset_.TX_EnumValidSoundbanks : (intptr_t) hmodule + (int64_t) avcodec::BmswTranscoderEnumValidSoundbanksAddr();
|
||||||
if (!offset_.TX_EnumValidSoundbanks)
|
if (!offset_.TX_EnumValidSoundbanks)
|
||||||
|
|||||||
+5
-2
@@ -92,8 +92,11 @@ bool on_thum_exists_(void *titleUTF_getter, int32_t id, char flag)
|
|||||||
void attach(HINSTANCE hmodule)
|
void attach(HINSTANCE hmodule)
|
||||||
{
|
{
|
||||||
// Reverse lookup function head (PUSH RDI) for ThumExists() specific signature, quietly fail if invalid
|
// 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,
|
intptr_t TX_ThumExists = patch_pipeline(
|
||||||
find_pattern_from(hmodule, "83f801750c4084ff750732c0", "XXXXXXXXXXXX", 0, 0, 0) - reinterpret_cast<intptr_t>(hmodule), true);
|
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));
|
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));
|
detour::trampoline_try(reinterpret_cast<void *>(TX_ThumExists), reinterpret_cast<void *>(on_thum_exists_), reinterpret_cast<void **>(&ThumExists));
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-33
@@ -9,12 +9,18 @@
|
|||||||
#include "util/memutils.h"
|
#include "util/memutils.h"
|
||||||
#include "util/utils.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)
|
const char *mask, intptr_t offset, intptr_t usage, bool reverse)
|
||||||
{
|
{
|
||||||
return find_pattern_from(data, base, pattern, mask, offset, usage, 0, 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 find_pattern(HMODULE module, const uint8_t *pattern, const char *mask,
|
||||||
intptr_t offset, intptr_t result_usage, bool reverse)
|
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)
|
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
|
// build pattern
|
||||||
std::vector<std::pair<uint8_t, bool>> pattern_vector;
|
std::vector<std::pair<uint8_t, bool>> pattern_vector;
|
||||||
size_t mask_size = strlen(mask);
|
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;
|
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 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)
|
intptr_t offset, intptr_t result_usage, intptr_t start_from, bool reverse)
|
||||||
{
|
{
|
||||||
// get module information
|
intptr_t base;
|
||||||
MODULEINFO module_info {};
|
auto data = get_module_data(module, &base);
|
||||||
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
|
|
||||||
return find_pattern_from(
|
return find_pattern_from(
|
||||||
data,
|
data,
|
||||||
reinterpret_cast<intptr_t>(module_info.lpBaseOfDll),
|
base,
|
||||||
pattern,
|
pattern,
|
||||||
mask,
|
mask,
|
||||||
offset,
|
offset,
|
||||||
result_usage,
|
result_usage,
|
||||||
start_from,
|
start_from,
|
||||||
reverse);
|
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,
|
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)
|
intptr_t find_asm_leacstr_from(HMODULE module, reg_t reg, const char *cstr)
|
||||||
{
|
{
|
||||||
// get module information
|
// get module information
|
||||||
MODULEINFO module_info{};
|
intptr_t base;
|
||||||
if (!GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(module_info)))
|
auto data = get_module_data(module, &base);
|
||||||
{
|
const unsigned char *modbegp = data.data();
|
||||||
return 0;
|
const unsigned char *modendp = data.data() + data.size();
|
||||||
}
|
|
||||||
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);
|
|
||||||
|
|
||||||
// search cstr
|
// search cstr
|
||||||
const unsigned char *cstr_addr = std::search(
|
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__)
|
#if defined(__i386__)
|
||||||
// find LEA REG, [abs32]
|
// find LEA REG, [abs32]
|
||||||
|
if (reg.t != GPR_32) return 0;
|
||||||
unsigned char asmop[6] = { 0x8D, reg.v, 0x00, 0x00, 0x00, 0x00};
|
unsigned char asmop[6] = { 0x8D, reg.v, 0x00, 0x00, 0x00, 0x00};
|
||||||
int32_t dist32 = reinterpret_cast<int32_t>(cstr_addr);
|
int32_t dist32 = reinterpret_cast<int32_t>(cstr_addr);
|
||||||
memcpy(asmop + (sizeof(asmop) - 4), &dist32, 4);
|
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,
|
modendp,
|
||||||
asmop,
|
asmop,
|
||||||
asmop + sizeof(asmop)
|
asmop + sizeof(asmop)
|
||||||
));
|
)) % reinterpret_cast<intptr_t>(modendp);
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
// find LEA REG, [RIP + rel32]
|
// find LEA REG, [RIP + rel32]
|
||||||
unsigned char rex = reg.t == GPR_EXT ? 0x4C : 0x48;
|
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;
|
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
@@ -5,11 +5,21 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <span>
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "psapi.h"
|
#include "psapi.h"
|
||||||
|
|
||||||
intptr_t find_pattern(
|
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,
|
intptr_t base,
|
||||||
const unsigned char *pattern,
|
const unsigned char *pattern,
|
||||||
const char *mask,
|
const char *mask,
|
||||||
@@ -34,7 +44,17 @@ intptr_t find_pattern(
|
|||||||
bool reverse = false);
|
bool reverse = false);
|
||||||
|
|
||||||
intptr_t find_pattern_from(
|
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,
|
intptr_t base,
|
||||||
const unsigned char *pattern,
|
const unsigned char *pattern,
|
||||||
const char *mask,
|
const char *mask,
|
||||||
@@ -150,3 +170,14 @@ intptr_t find_asm_leacstr_from(
|
|||||||
HMODULE module,
|
HMODULE module,
|
||||||
reg_t reg,
|
reg_t reg,
|
||||||
const char *cstr);
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user