diff --git a/CMakeLists.txt b/CMakeLists.txt index b6c5081d..a82278ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,13 +135,13 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(bddisasm) -message(STATUS "Fetching kananlib (8b29e1694dbf4ad4c878ff54bcbcabf280b37168)...") +message(STATUS "Fetching kananlib (d659e3b8312e26ba19329f96b73ba88d1211bfdb)...") FetchContent_Declare( kananlib GIT_REPOSITORY https://github.com/cursey/kananlib GIT_TAG - 8b29e1694dbf4ad4c878ff54bcbcabf280b37168 + d659e3b8312e26ba19329f96b73ba88d1211bfdb ) FetchContent_MakeAvailable(kananlib) diff --git a/cmake.toml b/cmake.toml index 999d9081..cb4233e1 100644 --- a/cmake.toml +++ b/cmake.toml @@ -177,7 +177,7 @@ tag = "v1.34.10" [fetch-content.kananlib] git = "https://github.com/cursey/kananlib" -tag = "8b29e1694dbf4ad4c878ff54bcbcabf280b37168" +tag = "d659e3b8312e26ba19329f96b73ba88d1211bfdb" [target.utility] type = "static" diff --git a/shared/sdk/RETypeDefinition.hpp b/shared/sdk/RETypeDefinition.hpp index ae819c51..3406f68a 100644 --- a/shared/sdk/RETypeDefinition.hpp +++ b/shared/sdk/RETypeDefinition.hpp @@ -43,7 +43,7 @@ struct RETypeDefVersion74 { uint32_t type_crc; uint64_t default_ctor : 22; uint64_t member_method : 22; - uint64_t member_field : TYPE_INDEX_BITS; + uint64_t member_field : FIELD_BITS; uint32_t num_member_prop : 12; uint32_t member_prop : TYPE_INDEX_BITS; diff --git a/shared/sdk/TDBVer.hpp b/shared/sdk/TDBVer.hpp index baafca6a..ecec2f44 100644 --- a/shared/sdk/TDBVer.hpp +++ b/shared/sdk/TDBVer.hpp @@ -53,48 +53,61 @@ struct RETypeDefinition; #if defined(MHWILDS) #define TYPE_INDEX_BITS 19 +#define FIELD_BITS 20 using RETypeDefinition_ = sdk::RETypeDefVersion74; #elif defined(DD2) #define TYPE_INDEX_BITS 19 +#define FIELD_BITS 19 using RETypeDefinition_ = sdk::RETypeDefVersion71; // same thing for now #elif defined(SF6) #define TYPE_INDEX_BITS 19 +#define FIELD_BITS 19 using RETypeDefinition_ = sdk::RETypeDefVersion71; #elif defined(RE4) #define TYPE_INDEX_BITS 19 +#define FIELD_BITS 19 using RETypeDefinition_ = sdk::RETypeDefVersion71; #elif defined(MHRISE) #ifdef MHRISE_TDB70 // it's version 70 but looks the same for now i guess #define TYPE_INDEX_BITS 18 +#define FIELD_BITS 18 using RETypeDefinition_ = sdk::RETypeDefVersion69; #else #define TYPE_INDEX_BITS 19 +#define FIELD_BITS 19 using RETypeDefinition_ = sdk::RETypeDefVersion71; #endif #elif defined(RE8) #define TYPE_INDEX_BITS 18 +#define FIELD_BITS 18 using RETypeDefinition_ = sdk::RETypeDefVersion69; #elif defined(DMC5) #define TYPE_INDEX_BITS 17 +#define FIELD_BITS 17 using RETypeDefinition_ = sdk::RETypeDefVersion67; #elif defined(RE2) || defined(RE3) #ifdef RE2_TDB66 #define TYPE_INDEX_BITS 16 +#define FIELD_BITS 16 using RETypeDefinition_ = sdk::RETypeDefVersion66; #elif defined(RE3_TDB67) #define TYPE_INDEX_BITS 17 +#define FIELD_BITS 17 using RETypeDefinition_ = sdk::RETypeDefVersion67; #else #define TYPE_INDEX_BITS 18 +#define FIELD_BITS 18 using RETypeDefinition_ = sdk::RETypeDefVersion69; #endif #elif RE7 #ifdef RE7_TDB49 #define TYPE_INDEX_BITS 16 +#define FIELD_BITS 16 using RETypeDefinition_ = sdk::RETypeDefVersion49; #else #define TYPE_INDEX_BITS 18 +#define FIELD_BITS 18 using RETypeDefinition_ = sdk::RETypeDefVersion69; #endif #endif diff --git a/src/mods/IntegrityCheckBypass.cpp b/src/mods/IntegrityCheckBypass.cpp index 9ac33761..afc2f1e2 100644 --- a/src/mods/IntegrityCheckBypass.cpp +++ b/src/mods/IntegrityCheckBypass.cpp @@ -506,6 +506,19 @@ void IntegrityCheckBypass::immediate_patch_re4() { spdlog::info("[IntegrityCheckBypass]: Patched conditional_jmp!"); } +void* IntegrityCheckBypass::renderer_create_blas_hook(void* a1, void* a2, void* a3, void* a4, void* a5) { + if (s_corruption_when_zero != nullptr) { + if (*s_corruption_when_zero == 0) { + *s_corruption_when_zero = s_last_non_zero_corruption; + spdlog::info("[IntegrityCheckBypass]: Fixed corruption_when_zero!"); + } + + s_last_non_zero_corruption = *s_corruption_when_zero; + } + + return s_renderer_create_blas_hook->get_original()(a1, a2, a3, a4, a5); +} + void IntegrityCheckBypass::immediate_patch_dd2() { // Just like RE4, this deals with the scans that are done every frame on the game's memory. // The scans are still performed, but the crash will be avoided. @@ -518,6 +531,71 @@ void IntegrityCheckBypass::immediate_patch_dd2() { spdlog::info("[IntegrityCheckBypass]: Scanning DD2..."); const auto game = utility::get_executable(); + +#if TDB_VER >= 74 + const auto query_performance_frequency = &QueryPerformanceFrequency; + const auto query_performance_counter = &QueryPerformanceCounter; + + if (query_performance_frequency != nullptr && query_performance_counter != nullptr) { + const auto qpf_import = utility::scan_ptr(game, (uintptr_t)query_performance_frequency); + const auto qpc_import = utility::scan_ptr(game, (uintptr_t)query_performance_counter); + + if (qpf_import && qpc_import) { + const auto crasher_fn = utility::find_function_with_refs(game, { *qpf_import, *qpc_import }); + + if (crasher_fn) { + spdlog::info("[IntegrityCheckBypass]: Found crasher_fn!"); + + // Make function just ret + //static auto patch = Patch::create(*crasher_fn, { 0xC3 }, true); + + const auto cmp_jz = utility::find_pattern_in_path((uint8_t*)*crasher_fn, 1000, false, "39 0C 82 74 ?"); + + if (cmp_jz) { + static auto patch = Patch::create(cmp_jz->addr + 3, { 0xEB }, true); + spdlog::info("[IntegrityCheckBypass]: Patched crasher_fn!"); + } else { + spdlog::error("[IntegrityCheckBypass]: Could not find cmp_jz!"); + } + } else { + spdlog::error("[IntegrityCheckBypass]: Could not find crasher_fn!"); + } + } else { + spdlog::error("[IntegrityCheckBypass]: Could not find QueryPerformanceFrequency/Counter imports!"); + } + } + + if (const auto create_blas_fn = utility::find_function_from_string_ref(game, "createBLAS"); create_blas_fn.has_value()) { + const auto create_blas_fn_unwind = utility::find_function_start_unwind(*create_blas_fn); + + if (create_blas_fn_unwind) { + spdlog::info("[IntegrityCheckBypass]: Found createBLAS!"); + + // Look for first lea rcx, [mem] + const auto lea_rcx = utility::find_pattern_in_path((uint8_t*)*create_blas_fn_unwind, 1000, false, "48 8D 0D ? ? ? ?"); + + if (lea_rcx) { + s_corruption_when_zero = (uint32_t*)utility::calculate_absolute(lea_rcx->addr + 3); + spdlog::info("[IntegrityCheckBypass]: Found corruption_when_zero!"); + } else { + spdlog::error("[IntegrityCheckBypass]: Could not find lea_rcx!"); + } + + s_renderer_create_blas_hook = std::make_unique(*create_blas_fn, &renderer_create_blas_hook); + + if (!s_renderer_create_blas_hook->create()) { + spdlog::error("[IntegrityCheckBypass]: Failed to hook createBLAS!"); + } else { + spdlog::info("[IntegrityCheckBypass]: Hooked createBLAS!"); + } + } else { + spdlog::error("[IntegrityCheckBypass]: Could not find unwound createBLAS!"); + } + } else { + spdlog::error("[IntegrityCheckBypass]: Could not find createBLAS!"); + } +#endif + const auto conditional_jmp_block = utility::scan(game, "41 8B ? ? 78 83 ? 07 ? ? 75 ?"); if (conditional_jmp_block) { diff --git a/src/mods/IntegrityCheckBypass.hpp b/src/mods/IntegrityCheckBypass.hpp index 27be8687..7952a481 100644 --- a/src/mods/IntegrityCheckBypass.hpp +++ b/src/mods/IntegrityCheckBypass.hpp @@ -38,6 +38,11 @@ class IntegrityCheckBypass : public Mod { } private: + static void* renderer_create_blas_hook(void* a1, void* a2, void* a3, void* a4, void* a5); + static inline std::unique_ptr s_renderer_create_blas_hook{}; + static inline uint32_t* s_corruption_when_zero{ nullptr }; + static inline uint32_t s_last_non_zero_corruption{ 8 }; // What I've seen it default to + static BOOL WINAPI virtual_protect_impl(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); static BOOL WINAPI virtual_protect_hook(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);