diff --git a/hooks/sndbhook.cpp b/hooks/sndbhook.cpp index 114f0c3..694de9b 100644 --- a/hooks/sndbhook.cpp +++ b/hooks/sndbhook.cpp @@ -901,7 +901,7 @@ void init(HINSTANCE hmodule, const char *model, const char *ext) return; } - // Override .text .data per datacode (pattern match) + // Override .data (per datacode) long extl = strtol(ext, nullptr, 10); if (extl < 2019100800) { @@ -925,24 +925,20 @@ void init(HINSTANCE hmodule, const char *model, const char *ext) offset_.DAT_song_id = 0x67c; offset_.is_lstr_wchar = true; } - intptr_t beg, match; - offset_.TX_EnumValidSoundbanks = beg = match = find_asm_leacstr_from(hmodule, R8, "%05d/%05d.2dx"); - while (beg > sizeof(void *) && match >= offset_.TX_EnumValidSoundbanks) //_REV: probably should be sigscan helper due to find_pattern_from performance, unify with wmischook - { - beg -= sizeof(void *); - match = find_pattern_from(hmodule, "4057", "XX", 0, 0, beg - reinterpret_cast(hmodule)); - } + + // 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); snd_bank::resampler_ = avcodec::BmswTranscoderResampler() == avcodec::bmswac_resampler_none ? snd_bank::resampler_ : avcodec::BmswTranscoderResampler(); - offset_.TX_EnumValidSoundbanks = avcodec::BmswTranscoderEnumValidSoundbanksAddr() == 0x0 ? match : (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) { log_warning("hooks::soundbank", "Unsupported game version({}), skipping..", ext); return; } - log_info("hooks::soundbank", "Hooking EnumValidSoundbanks(0x{:x})", offset_.TX_EnumValidSoundbanks); log_info("hooks::soundbank", "Supported game version({})", ext); - // Override .rdata + // Override .rdata (pattern match) offset_.RD_05d_s3p = replace_pattern(hmodule, "253035642f253035642e73337000", "003035642f253035642e73337000", 0, 0); offset_.RD_05d_c_s3p = replace_pattern(hmodule, "253035642f2530356425632e73337000", "003035642f2530356425632e73337000", 0, 0); offset_.RD_05d_2dx = replace_pattern(hmodule, "253035642F253035642E32647800", "73797374656D2F30302E32647800", 0, 0); @@ -954,6 +950,7 @@ void init(HINSTANCE hmodule, const char *model, const char *ext) } // Setup on_enum_valid_ksbd and optional tests + log_info("hooks::soundbank", "Hooking EnumValidSoundbanks(0x{:x})", offset_.TX_EnumValidSoundbanks); offset_.guard = new memutils::VProtectGuard((void *) offset_.RD_05d_2dx, SNDPATHFMTMAX); detour::trampoline(reinterpret_cast(offset_.TX_EnumValidSoundbanks), reinterpret_cast(on_enum_valid_soundbanks), reinterpret_cast(&EnumValidSoundbanks)); hooks::devel::bind_routine(&tests_); diff --git a/hooks/wmischook.cpp b/hooks/wmischook.cpp index 25436dc..45f9a55 100644 --- a/hooks/wmischook.cpp +++ b/hooks/wmischook.cpp @@ -92,14 +92,8 @@ 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 beg, match, TX_ThumExists; - TX_ThumExists = beg = match = find_pattern_from(hmodule, "83f801750c4084ff750732c0", "XXXXXXXXXXXX", 0, 0, 0); - while (beg > sizeof(void *) && match >= TX_ThumExists) - { - beg -= sizeof(void *); - match = find_pattern_from(hmodule, "4057", "XX", 0, 0, beg - reinterpret_cast(hmodule)); - } - TX_ThumExists = match; + 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); 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 9870d1e..c7f85f6 100644 --- a/util/sigscan.cpp +++ b/util/sigscan.cpp @@ -10,29 +10,30 @@ #include "util/utils.h" intptr_t find_pattern(std::vector &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 &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> pattern_vector; @@ -40,40 +41,71 @@ intptr_t find_pattern_from(std::vector &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 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 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(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) { diff --git a/util/sigscan.h b/util/sigscan.h index 9ef7072..fa85739 100644 --- a/util/sigscan.h +++ b/util/sigscan.h @@ -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 &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);