mirror of
https://github.com/EricPlayZ/EGameTools.git
synced 2026-10-10 12:53:04 +08:00
implemented proper savegame CRC check bypass, added byte patching and fixed a few bugs
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user