diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 478d7826a..5966bb9df 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,8 @@ set(MODS_SRC FirstPerson.cpp FreeCam.hpp FreeCam.cpp + IntegrityCheckBypass.hpp + IntegrityCheckBypass.cpp ManualFlashlight.hpp ManualFlashlight.cpp ObjectExplorer.hpp diff --git a/src/IntegrityCheckBypass.cpp b/src/IntegrityCheckBypass.cpp new file mode 100644 index 000000000..cfd2a157f --- /dev/null +++ b/src/IntegrityCheckBypass.cpp @@ -0,0 +1,46 @@ +#include "utility/Scan.hpp" + +#include "IntegrityCheckBypass.hpp" + +struct IntegrityCheckPattern { + std::string pat{}; + uint32_t offset{}; +}; + +std::optional IntegrityCheckBypass::on_initialize() { + // Patterns for assigning or accessing of the integrity check boolean + std::vector possible_patterns{ + /* + cmp qword ptr [rax+18h], 0 + cmovz ecx, r15d + mov cs:bypass_integrity_checks, cl*/ + // Referenced above "steam_api64.dll" + {"48 ? ? 18 00 41 ? ? ? 88 0D ? ? ? ?", 11}, + {"48 ? ? 18 00 0F ? ? 88 0D ? ? ? ? 49 ? ? ? 48", 10}, + }; + + for (auto& possible_pattern : possible_patterns) { + auto integrity_check_ref = utility::scan(g_framework->get_module().as(), possible_pattern.pat); + + if (!integrity_check_ref) { + continue; + } + + m_bypass_integrity_checks = (bool*)utility::calculate_absolute(*integrity_check_ref + possible_pattern.offset); + } + + // These may be removed, so don't fail altogether + /*if (m_bypass_integrity_checks == nullptr) { + return "Failed to find IntegrityCheckBypass pattern"; + }*/ + + spdlog::info("[{:s}]: bypass_integrity_checks: {:x}", get_name().data(), (uintptr_t)m_bypass_integrity_checks); + + return Mod::on_initialize(); +} + +void IntegrityCheckBypass::on_frame() { + if (m_bypass_integrity_checks != nullptr) { + *m_bypass_integrity_checks = true; + } +} diff --git a/src/IntegrityCheckBypass.hpp b/src/IntegrityCheckBypass.hpp new file mode 100644 index 000000000..ee7a8f1b5 --- /dev/null +++ b/src/IntegrityCheckBypass.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "Mod.hpp" + +// Always on for RE3 +// Because we use hooks that modify the integrity of the executable +// And RE3 has unfortunately decided to implement an integrity check on the executable code of the process +class IntegrityCheckBypass : public Mod { +public: + std::string_view get_name() const override { return "IntegrityCheckBypass"; }; + std::optional on_initialize() override; + + void on_frame() override; + +private: + // This is what the game uses to bypass its integrity checks altogether or something + bool* m_bypass_integrity_checks{ nullptr }; +}; \ No newline at end of file diff --git a/src/Mods.cpp b/src/Mods.cpp index 73c7e604f..5d7acc73e 100644 --- a/src/Mods.cpp +++ b/src/Mods.cpp @@ -1,5 +1,6 @@ #include +#include "IntegrityCheckBypass.hpp" #include "PositionHooks.hpp" #include "FirstPerson.hpp" #include "DeveloperTools.hpp" @@ -10,6 +11,10 @@ Mods::Mods() { +#ifdef RE3 + m_mods.emplace_back(std::make_unique()); +#endif + m_mods.emplace_back(std::make_unique()); m_mods.emplace_back(std::make_unique()); m_mods.emplace_back(std::make_unique());