implemented proper savegame CRC check bypass, added byte patching and fixed a few bugs

This commit is contained in:
EricPlayZ
2024-05-03 17:16:07 +03:00
parent f4699cdd30
commit e2be96af15
7 changed files with 120 additions and 24 deletions
+2 -2
View File
@@ -227,8 +227,8 @@ namespace Core {
for (auto& hook : *Utils::Hook::HookBase::GetInstances()) {
spdlog::warn("Hooking \"{}\"", hook->name.data());
std::thread([&hook]() {
hook->HookLoop();
spdlog::info("Hooked \"{}\"!", hook->name.data());
if (hook->HookLoop())
spdlog::info("Hooked \"{}\"!", hook->name.data());
}).detach();
}
@@ -204,14 +204,17 @@ namespace Engine {
Utils::Hook::MHook<LPVOID, DWORD64(*)(DWORD64, UINT, UINT, DWORD64*, DWORD64(*)(DWORD64, DWORD, DWORD64, char*, int), INT16, DWORD64, UINT)> MountDataPaksHook{ "MountDataPaks", &Offsets::Get_MountDataPaks, &detourMountDataPaks };
static DWORD64 detourMountDataPaks(DWORD64 a1, UINT a2, UINT a3, DWORD64* a4, DWORD64(*a5)(DWORD64, DWORD, DWORD64, char*, int), INT16 a6, DWORD64 a7, UINT a8) {
static int i = 0;
if (a8 == 8)
i++;
else if (i < 3)
spdlog::error("MountDataPaks hook ran less than 3 times with the data PAKs limit set to 8. This means the increased data PAKs limit might not work correctly! If this error message appears and your data PAKs past \"data7.pak\" have not loaded, please contact author.");
if (Menu::Misc::increaseDataPAKsLimit.GetValue()) {
static int i = 0;
if (a8 == 8)
i++;
else if (i < 3) {
i++;
spdlog::error("MountDataPaks hook ran less than 3 times with the data PAKs limit set to 8. This means the increased data PAKs limit might not work correctly! If this error message appears and your data PAKs past \"data7.pak\" have not loaded, please contact author.");
}
if (Menu::Misc::increaseDataPAKsLimit.GetValue())
a8 = 200;
}
return MountDataPaksHook.pOriginal(a1, a2, a3, a4, a5, a6, a7, a8);
}
#pragma endregion
@@ -16,6 +16,7 @@ namespace GamePH {
return pPlayerHealthModule;
} __except (EXCEPTION_EXECUTE_HANDLER) {
pPlayerHealthModule = nullptr;
playerHealthModulePtrList.clear();
return nullptr;
}
}
@@ -244,5 +244,10 @@ namespace GamePH {
funcHandlePlayerImmunityRunning = false;
}
#pragma endregion
#pragma region ByteHooks
static unsigned char SaveGameCRCBoolCheckBytes[3] = { 0xB3, 0x01, 0x90 }; // mov bl, 01
Utils::Hook::BytesHook<LPVOID> SaveGameCRCBoolCheckHook{ "SaveGameCRCBoolCheck", &Offsets::Get_SaveGameCRCBoolCheck, SaveGameCRCBoolCheckBytes, sizeof(SaveGameCRCBoolCheckBytes), &Menu::Misc::disableSavegameCRCCheck }; // and bl, dil
#pragma endregion
}
}
+6 -1
View File
@@ -3,6 +3,10 @@
#include "..\game\GamePH\LevelDI.h"
#include "misc.h"
namespace GamePH::Hooks {
extern Utils::Hook::BytesHook<LPVOID> SaveGameCRCBoolCheckHook;
}
namespace Menu {
namespace Misc {
KeyBindOption disableGamePauseWhileAFK{ VK_NONE };
@@ -47,7 +51,8 @@ namespace Menu {
ImGui::CheckboxHotkey("Disable HUD", &disableHUD);
ImGui::EndDisabled();
}
ImGui::Checkbox("Disable Savegame CRC Check *", &disableSavegameCRCCheck);
if (ImGui::Checkbox("Disable Savegame CRC Check *", &disableSavegameCRCCheck))
GamePH::Hooks::SaveGameCRCBoolCheckHook.Toggle();
ImGui::Checkbox("Disable Data PAKs CRC Check *", &disableDataPAKsCRCCheck);
ImGui::Checkbox("Increase Data PAKs Limit *", &increaseDataPAKsLimit);
ImGui::Separator();
+7 -6
View File
@@ -23,16 +23,16 @@ static DWORD64 Get_## name () {\
struct Offsets {
// ntdll.dll
//AddOffset(LdrpCallInitRoutine, "ntdll.dll", "[48 89 5C 24 08 44 89 44 24 18 48", PatternType::Address, PDWORD64)
//AddOffset(LdrpRunInitializeRoutines, "ntdll.dll", "[48 89 4C 24 08 53 56 57 41 54 41 55 41 56 41 57 48 81 EC 90", PatternType::Address, PDWORD64) // for win7
//AddOffset(LdrpCallInitRoutine, "ntdll.dll", "[48 89 5C 24 08 44 89 44 24 18 48", PatternType::Address, DWORD64*)
//AddOffset(LdrpRunInitializeRoutines, "ntdll.dll", "[48 89 4C 24 08 53 56 57 41 54 41 55 41 56 41 57 48 81 EC 90", PatternType::Address, DWORD64*) // for win7
// Input related
AddOffset(g_CInput, "engine_x64_rwdi.dll", "48 8B 0D [?? ?? ?? ?? 48 85 C9 74 ?? 48 8B 01 84 D2", Utils::SigScan::PatternType::RelativePointer, PDWORD64*)
AddOffset(g_CInput, "engine_x64_rwdi.dll", "48 8B 0D [?? ?? ?? ?? 48 85 C9 74 ?? 48 8B 01 84 D2", Utils::SigScan::PatternType::RelativePointer, DWORD64**)
//AddOffset(WndProc, "engine_x64_rwdi.dll", "40 55 56 57 41 54 41 56 48 83 EC ?? 49 8B E9", PatternType::Address, LPVOID)
// Player vars related
AddStaticOffset(LoadPlayerVariableFunc_size, 0x14E)
//AddOffset(LoadPlayerFloatVariable, "gamedll_ph_x64_rwdi.dll", "E8 [?? ?? ?? ?? 48 8B D0 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 94 24 ?? ?? ?? ?? 48 8B 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 84 24 ?? ?? ?? ??", PatternType::RelativePointer, PDWORD64);
//AddOffset(LoadPlayerFloatVariable, "gamedll_ph_x64_rwdi.dll", "E8 [?? ?? ?? ?? 48 8B D0 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 94 24 ?? ?? ?? ?? 48 8B 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 84 24 ?? ?? ?? ??", PatternType::RelativePointer, DWORD64*);
AddOffset(InitializePlayerVariables, "gamedll_ph_x64_rwdi.dll", "E8 [?? ?? ?? ?? 48 8B F0 48 8B CF", Utils::SigScan::PatternType::RelativePointer, DWORD64)
AddStaticOffset(initPlayerFloatVarsInstr_offset, 0x99);
AddStaticOffset(initPlayerBoolVarsInstr_offset, 0x2E7);
@@ -43,9 +43,10 @@ struct Offsets {
AddOffset(CLobbySteam, "engine_x64_rwdi.dll", "48 8B 05 [?? ?? ?? ?? 48 85 C0 74 ?? 48 83 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID)
AddOffset(g_PlayerObjProperties, "gamedll_ph_x64_rwdi.dll", "48 89 0D [?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID)
AddOffset(g_DayNightCycle, "gamedll_ph_x64_rwdi.dll", "48 8B 0D [?? ?? ?? ?? 48 85 C9 74 ?? E8 ?? ?? ?? ?? 84 C0 74 ?? B0 ?? 48 83 C4 ?? C3 32 C0", Utils::SigScan::PatternType::RelativePointer, LPVOID)
//AddOffset(g_CameraFPPDI, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 40 84 FF", PatternType::RelativePointer, PDWORD64)
AddOffset(g_FreeCamera, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 48 89 4C 24", Utils::SigScan::PatternType::RelativePointer, PDWORD64)
//AddOffset(g_CameraFPPDI, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 40 84 FF", PatternType::RelativePointer, DWORD64*)
AddOffset(g_FreeCamera, "gamedll_ph_x64_rwdi.dll", "48 89 05 [?? ?? ?? ?? 48 89 4C 24", Utils::SigScan::PatternType::RelativePointer, DWORD64*)
//AddOffset(CameraFPPDI_VT, "gamedll_ph_x64_rwdi.dll", "48 8D 05 [?? ?? ?? ?? 48 89 07 48 8D 4F 60", PatternType::RelativePointer, DWORD64)
AddOffset(SaveGameCRCBoolCheck, "gamedll_ph_x64_rwdi.dll", "FF 50 ?? [40 22 DF 0F 85 ?? ?? ?? ?? 0F B6 05 ?? ?? ?? ?? 48 8D 3D", Utils::SigScan::PatternType::Address, LPVOID)
// Functions
AddOffset(ReadVideoSettings, "engine_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8B FA 48 8B D9 45 84 C0", Utils::SigScan::PatternType::Address, LPVOID)
+90 -9
View File
@@ -28,24 +28,105 @@ namespace Utils {
~HookBase();
static std::set<HookBase*>* GetInstances();
virtual void HookLoop() {};
virtual bool HookLoop() { return false; };
const std::string_view name;
};
template <typename GetTargetOffsetRetType>
class BytesHook : HookBase {
public:
BytesHook(const std::string_view& name, GetTargetOffsetRetType(*pGetOffsetFunc)(), unsigned char* patchBytes, size_t bytesAmount, Option* optionRef = nullptr) : HookBase(name), pGetOffsetFunc(pGetOffsetFunc), patchBytes(patchBytes), bytesAmount(bytesAmount), optionRef(optionRef) {}
bool HookLoop() override {
if (hooked || (optionRef && !optionRef->GetValue()))
return true;
timeSpentHooking = Utils::Time::Timer(60000);
while (true) {
if (timeSpentHooking.DidTimePass()) {
spdlog::error("Failed hooking \"{}\" after 60 seconds", name);
return false;
}
if (!pGetOffsetFunc || !pGetOffsetFunc())
continue;
DWORD originalProtection = 0;
DWORD oldProtection = 0;
VirtualProtect(pGetOffsetFunc(), bytesAmount, PAGE_EXECUTE_READWRITE, &originalProtection);
if (!origBytes) {
origBytes = new unsigned char[bytesAmount];
memcpy_s(origBytes, bytesAmount, pGetOffsetFunc(), bytesAmount);
}
memcpy_s(pGetOffsetFunc(), bytesAmount, patchBytes, bytesAmount);
VirtualProtect(pGetOffsetFunc(), bytesAmount, originalProtection, &oldProtection);
hooked = true;
return true;
}
}
void Enable() {
if (hooked)
return;
DWORD originalProtection = 0;
DWORD oldProtection = 0;
VirtualProtect(pGetOffsetFunc(), bytesAmount, PAGE_EXECUTE_READWRITE, &originalProtection);
if (!origBytes) {
origBytes = new unsigned char[bytesAmount];
memcpy_s(origBytes, bytesAmount, pGetOffsetFunc(), bytesAmount);
}
memcpy_s(pGetOffsetFunc(), bytesAmount, patchBytes, bytesAmount);
VirtualProtect(pGetOffsetFunc(), bytesAmount, originalProtection, &oldProtection);
hooked = true;
}
void Disable() {
if (!hooked)
return;
DWORD originalProtection = 0;
DWORD oldProtection = 0;
VirtualProtect(pGetOffsetFunc(), bytesAmount, PAGE_EXECUTE_READWRITE, &originalProtection);
memcpy_s(pGetOffsetFunc(), bytesAmount, origBytes, bytesAmount);
VirtualProtect(pGetOffsetFunc(), bytesAmount, originalProtection, &oldProtection);
hooked = false;
}
void Toggle() {
if (!optionRef) {
hooked ? Disable() : Enable();
return;
}
optionRef->GetValue() ? Enable() : Disable();
}
Option* optionRef = nullptr;
private:
GetTargetOffsetRetType(*pGetOffsetFunc)() = nullptr;
unsigned char* origBytes = nullptr;
unsigned char* patchBytes = nullptr;
size_t bytesAmount = 0;
bool hooked = false;
Utils::Time::Timer timeSpentHooking{ 60000 };
};
template <typename GetTargetOffsetRetType, typename OrigType>
class MHook : HookBase {
public:
MHook(const std::string_view& name, GetTargetOffsetRetType(*pGetOffsetFunc)(), OrigType pDetour) : HookBase(name), pGetOffsetFunc(pGetOffsetFunc), pDetour(pDetour) {}
void HookLoop() override {
bool HookLoop() override {
if (pOriginal)
return;
return true;
timeSpentHooking = Utils::Time::Timer(60000);
while (true) {
if (timeSpentHooking.DidTimePass()) {
spdlog::error("Failed hooking function \"{}\" after 60 seconds", name);
break;
return false;
}
if (!pGetOffsetFunc)
continue;
@@ -54,7 +135,7 @@ namespace Utils {
pTarget = reinterpret_cast<OrigType>(pGetOffsetFunc());
else if (!pOriginal && MH_CreateHook(pTarget, pDetour, reinterpret_cast<LPVOID*>(&pOriginal)) == MH_OK) {
MH_EnableHook(pTarget);
break;
return true;
}
}
}
@@ -72,15 +153,15 @@ namespace Utils {
public:
VTHook(const std::string_view& name, GetTargetOffsetRetType(*pGetOffsetFunc)(), OrigType pDetour, DWORD offset) : HookBase(name), pGetOffsetFunc(pGetOffsetFunc), pDetour(pDetour), offset(offset) {}
void HookLoop() override {
bool HookLoop() override {
if (pOriginal)
return;
return true;
timeSpentHooking = Utils::Time::Timer(60000);
while (true) {
if (timeSpentHooking.DidTimePass()) {
spdlog::error("Failed hooking function \"{}\" after 60 seconds", name);
break;
return false;
}
if (!pGetOffsetFunc)
continue;
@@ -89,7 +170,7 @@ namespace Utils {
pInstance = pGetOffsetFunc();
else if (!pOriginal) {
HookVT(pInstance, pDetour, reinterpret_cast<LPVOID*>(&pOriginal), offset);
break;
return true;
}
}
}