From 9c6f9752b69d2b6b26b04f48a8f739c5704404a8 Mon Sep 17 00:00:00 2001 From: maybegreat48 <96936658+maybegreat48@users.noreply.github.com> Date: Sun, 8 Jun 2025 12:12:19 -0400 Subject: [PATCH] fix(anticheat): fix potential memory leak --- src/game/backend/AnticheatBypass.cpp | 45 ++++++++++++++++ src/game/pointers/Pointers.cpp | 8 ++- src/game/pointers/Pointers.hpp | 3 ++ src/types/rage/gameSkeleton.hpp | 80 ++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/types/rage/gameSkeleton.hpp diff --git a/src/game/backend/AnticheatBypass.cpp b/src/game/backend/AnticheatBypass.cpp index 03824b3..80c3bd1 100644 --- a/src/game/backend/AnticheatBypass.cpp +++ b/src/game/backend/AnticheatBypass.cpp @@ -5,6 +5,7 @@ #include "game/pointers/Pointers.hpp" #include "game/backend/NativeHooks.hpp" #include "game/gta/Natives.hpp" +#include "types/rage/gameSkeleton.hpp" using FnGetVersion = int(*)(); @@ -32,8 +33,52 @@ namespace YimMenu return NativeInvoker::GetNativeHandler(NativeIndex::NET_GAMESERVER_BEGIN_SERVICE)(ctx); } + static void DefuseSigscanner() + { + bool patched = false; + for (auto mode = Pointers.GameSkeleton->m_UpdateModes; mode; mode = mode->m_Next) + { + for (auto update_node = mode->m_Head; update_node; update_node = update_node->m_Next) + { + if (update_node->m_Hash != "Common Main"_J) + continue; + + auto group = reinterpret_cast(update_node); + + for (auto group_child_node = group->m_Head; group_child_node; group_child_node = group_child_node->m_Next) + { + // TamperActions is a leftover from the old AC, but still useful to block anyway + if (group_child_node->m_Hash != 0xA0F39FB6 && group_child_node->m_Hash != "TamperActions"_J) + continue; + patched = true; + + reinterpret_cast(group_child_node)->m_Function = reinterpret_cast(Pointers.Nullsub); + } + break; + } + } + + for (rage::gameSkeletonData& i : Pointers.GameSkeleton->m_SysData) + { + if (i.m_Hash != 0xA0F39FB6 && i.m_Hash != "TamperActions"_J) + continue; + i.m_InitFunc = Pointers.Nullsub; + i.m_ShutdownFunc = Pointers.Nullsub; + } + + if (patched) + { + LOGF(VERBOSE, "DefuseSigscanner: Patched out the sigscanner"); + } + else + { + LOGF(WARNING, "DefuseSigscanner: Failed to patch the sigscanner"); + } + } + void AnticheatBypass::RunScriptImpl() { + DefuseSigscanner(); NativeHooks::AddHook("shop_controller"_J, NativeIndex::NET_GAMESERVER_BEGIN_SERVICE, &TransactionHook); m_IsFSLLoaded = CheckForFSL(); diff --git a/src/game/pointers/Pointers.cpp b/src/game/pointers/Pointers.cpp index 77deeeb..b397472 100644 --- a/src/game/pointers/Pointers.cpp +++ b/src/game/pointers/Pointers.cpp @@ -132,9 +132,10 @@ namespace YimMenu WriteNodeData = ptr.As(); }); - constexpr auto shouldUseNodeCachePtrn = Pattern<"83 FA 20 74 1D 48 89 CE">("ShouldUseNodeCache"); + constexpr auto shouldUseNodeCachePtrn = Pattern<"83 FA 20 74 1D 48 89 CE">("ShouldUseNodeCache&Nullsub"); scanner.Add(shouldUseNodeCachePtrn, [this](PointerCalculator ptr) { ShouldUseNodeCache = ptr.Sub(5).As(); + Nullsub = ptr.Add(0x29).As(); }); constexpr auto isNodeInScopePtrn = Pattern<"41 83 F9 02 74 22 48 8B 06">("IsNodeInScope"); @@ -389,6 +390,11 @@ namespace YimMenu AssistedAimFindNewTarget = ptr.Sub(0x33).As(); }); + constexpr auto gameSkeletonPtrn = Pattern<"0F B6 C0 8D 14 00 83 C2 02">("GameSkeleton"); + scanner.Add(gameSkeletonPtrn, [this](PointerCalculator ptr) { + GameSkeleton = ptr.Add(0x9).Add(3).Rip().As(); + }); + if (!scanner.Scan()) { LOG(FATAL) << "Some patterns could not be found, unloading."; diff --git a/src/game/pointers/Pointers.hpp b/src/game/pointers/Pointers.hpp index 0fd8d90..0b1695f 100644 --- a/src/game/pointers/Pointers.hpp +++ b/src/game/pointers/Pointers.hpp @@ -30,6 +30,7 @@ namespace rage class rlQueryAccountsResult; class rlGetAvatarsContext; class rlGetAvatarsPlayerList; + struct gameSkeleton; } class CPedFactory; class CNetGamePlayer; @@ -153,6 +154,8 @@ namespace YimMenu PVOID BattlEyeServerProcessPlayerJoin; PVOID AssistedAimShouldReleaseEntity; Functions::AssistedAimFindNewTarget AssistedAimFindNewTarget; + rage::gameSkeleton* GameSkeleton; + PVOID Nullsub; }; struct Pointers : PointerData diff --git a/src/types/rage/gameSkeleton.hpp b/src/types/rage/gameSkeleton.hpp new file mode 100644 index 0000000..8b0befe --- /dev/null +++ b/src/types/rage/gameSkeleton.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include "atArray.hpp" +#include + +namespace rage +{ + struct gameSkeletonData + { + void* m_InitFunc; // 0x0 + void* m_ShutdownFunc; // 0x8 + uint32_t m_unk1; // 0x10 + uint32_t m_unk2; // 0x14 + uint32_t m_unk3; // 0x18 + uint32_t m_unk4; // 0x1C + uint32_t m_Hash; // 0x20 + }; + static_assert(sizeof(gameSkeletonData) == 0x28); + + struct gameSkeletonUpdateBase + { + virtual ~gameSkeletonUpdateBase() = default; + virtual void Run() = 0; + uint64_t m_Pad; // 0x08 + uint32_t m_Hash; // 0x10 + gameSkeletonUpdateBase* m_Next; // 0x18 + }; + static_assert(sizeof(gameSkeletonUpdateBase) == 0x20); + + struct gameSkeletonUpdateGroup : gameSkeletonUpdateBase + { + gameSkeletonUpdateBase* m_Head; // 0x20 + }; + static_assert(sizeof(gameSkeletonUpdateGroup) == 0x28); + + struct gameSkeletonUpdateElement : gameSkeletonUpdateBase + { + void (*m_Function)(); // 0x20 + }; + static_assert(sizeof(gameSkeletonUpdateElement) == 0x28); + + struct gameSkeletonUpdateMode + { + int m_Type; // 0x00 + gameSkeletonUpdateBase* m_Head; // 0x08 + gameSkeletonUpdateMode* m_Next; // 0x10 + }; + static_assert(sizeof(gameSkeletonUpdateMode) == 0x18); + + struct gameSkeletonInitDependency + { + int m_Level; // 0x00 + atArray m_Data; // 0x08 + gameSkeletonInitDependency* m_Next; // 0x10 + }; + + struct gameSkeletonMode + { + int m_Type; // 0x00 + gameSkeletonInitDependency* m_Head; // 0x08 + gameSkeletonMode* m_Next; // 0x10 + }; + static_assert(sizeof(gameSkeletonMode) == 0x18); + + struct gameSkeleton + { + virtual ~gameSkeleton() = 0; + uint32_t m_unk1; // 0x08 + uint32_t m_unk2; // 0x0C + uint32_t m_unk3; // 0x10 + uint32_t m_unk4; // 0x14 + atArray m_SysData; // 0x18 + uint32_t m_unk5; // 0x28 + void* m_unk6[32]; // 0x30 + gameSkeletonMode* m_InitModes; // 0x130 + gameSkeletonMode* m_ShutdownModes; // 0x138 + gameSkeletonUpdateMode* m_UpdateModes; // 0x140 + }; + static_assert(sizeof(gameSkeleton) == 0x148); +} \ No newline at end of file