diff --git a/hooks/sndbhook.cpp b/hooks/sndbhook.cpp index 694de9b..028c55e 100644 --- a/hooks/sndbhook.cpp +++ b/hooks/sndbhook.cpp @@ -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(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) diff --git a/hooks/wmischook.cpp b/hooks/wmischook.cpp index 45f9a55..f18ef69 100644 --- a/hooks/wmischook.cpp +++ b/hooks/wmischook.cpp @@ -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(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(TX_ThumExists)); detour::trampoline_try(reinterpret_cast(TX_ThumExists), reinterpret_cast(on_thum_exists_), reinterpret_cast(&ThumExists)); } diff --git a/util/sigscan.cpp b/util/sigscan.cpp index c7f85f6..2bed0d1 100644 --- a/util/sigscan.cpp +++ b/util/sigscan.cpp @@ -9,12 +9,18 @@ #include "util/memutils.h" #include "util/utils.h" -intptr_t find_pattern(std::vector &data, intptr_t base, const uint8_t *pattern, +intptr_t find_pattern(std::span 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 &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(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 &data, intptr_t base, const uint8_t *pattern, +intptr_t find_pattern_from(std::span 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> pattern_vector; size_t mask_size = strlen(mask); @@ -104,37 +107,26 @@ intptr_t find_pattern_from(std::vector &data, intptr_t base, const uint return 0; } +intptr_t find_pattern_from(const std::vector &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(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(module_info.SizeOfImage); - - try { - - // copy data - std::vector data(size); - memcpy(data.data(), module_info.lpBaseOfDll, size); - - // find pattern - return find_pattern_from( - data, - reinterpret_cast(module_info.lpBaseOfDll), - 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 base; + auto data = get_module_data(module, &base); + return find_pattern_from( + data, + base, + pattern, + mask, + offset, + result_usage, + start_from, + reverse); } 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(module); - const unsigned char *modendp = reinterpret_cast(module) + static_cast(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(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(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 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(module_info.SizeOfImage); + } + + // wrap data + std::span data(static_cast(module_info.lpBaseOfDll), sz); + *base = reinterpret_cast(module_info.lpBaseOfDll); + + return data; +} diff --git a/util/sigscan.h b/util/sigscan.h index fa85739..db08bb7 100644 --- a/util/sigscan.h +++ b/util/sigscan.h @@ -5,11 +5,21 @@ #include #include #include +#include #include "windows.h" #include "psapi.h" intptr_t find_pattern( - std::vector &data, + std::span 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 &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 &data, + std::span 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 &data, intptr_t base, const unsigned char *pattern, const char *mask, @@ -149,4 +169,15 @@ enum REG : unsigned short intptr_t find_asm_leacstr_from( HMODULE module, reg_t reg, - const char *cstr); \ No newline at end of file + const char *cstr); + +std::span get_module_data(HMODULE hmodule, intptr_t *base); + +template +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(cbs)(module, addr - base))), ...); // stop on first mismatch + return addr; +} \ No newline at end of file