fix(anticheat): fix anticheat bypass (#843)

This commit is contained in:
Mr-X-GTA
2026-01-04 11:23:35 +01:00
committed by GitHub
parent dbfd43639d
commit 8acef742f2
14 changed files with 104 additions and 68 deletions
+1
View File
@@ -17,6 +17,7 @@ namespace YimMenu
BaseHook::Add<Hooks::SwapChain::ResizeBuffers>(new DetourHook("ResizeBuffers", swapchain_vft[Hooks::SwapChain::VMTResizeBuffersIdx], Hooks::SwapChain::ResizeBuffers));
// BaseHook::Add<Hooks::Anticheat::QueueDependency>(new DetourHook("QueueDependency", Pointers.QueueDependency, Hooks::Anticheat::QueueDependency));
BaseHook::Add<Hooks::Anticheat::GameSkeletonUpdate>(new DetourHook("GameSkeletonUpdate", Pointers.GameSkeletonUpdate, Hooks::Anticheat::GameSkeletonUpdate));
BaseHook::Add<Hooks::Anticheat::PrepareMetricForSending>(new DetourHook("PrepareMetricForSending", Pointers.PrepareMetricForSending, Hooks::Anticheat::PrepareMetricForSending));
BaseHook::Add<Hooks::Anticheat::GetThreadContext>(new DetourHook("GetThreadContext", reinterpret_cast<void*>(GetProcAddress(LoadLibraryA("kernel32.dll"), "GetThreadContext")), Hooks::Anticheat::GetThreadContext));
BaseHook::Add<Hooks::Anticheat::HttpStartRequest>(new DetourHook("HttpStartRequest", Pointers.HttpStartRequest, Hooks::Anticheat::HttpStartRequest));
+1 -1
View File
@@ -190,7 +190,7 @@ namespace YimMenu
m_HeapAllocator.Create(m_Device.Get(), m_DescriptorHeap.Get());
// never returns false, useless to check return
ImGui::CreateContext(&GetInstance().m_FontAtlas);
ImGui::CreateContext();
ImGui_ImplWin32_Init(*Pointers.Hwnd);
ImGui_ImplDX12_InitInfo init_info = {};
-54
View File
@@ -5,7 +5,6 @@
#include "game/pointers/Pointers.hpp"
#include "game/backend/NativeHooks.hpp"
#include "game/gta/Natives.hpp"
#include "types/rage/gameSkeleton.hpp"
#include "types/anticheat/CAnticheatContext.hpp"
using FnGetVersion = int (*)();
@@ -33,57 +32,6 @@ namespace YimMenu
return NativeInvoker::GetNativeHandler(NativeIndex::NET_GAMESERVER_BEGIN_SERVICE)(ctx);
}
static void NopGameSkeletonElement(rage::gameSkeletonUpdateElement* element)
{
// TODO: small memory leak
// Hey rockstar if you keep up with this I'll make you integrity check everything until you can't anymore, please grow a brain and realize that this is futile
// and kills performance if you're the host
auto vtable = *reinterpret_cast<void***>(element);
if (vtable[1] == Pointers.Nullsub)
return; // already nopped
auto new_vtable = new void*[3];
memcpy(new_vtable, vtable, sizeof(void*) * 3);
new_vtable[1] = Pointers.Nullsub;
*reinterpret_cast<void***>(element) = new_vtable;
}
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<rage::gameSkeletonUpdateGroup*>(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;
NopGameSkeletonElement(reinterpret_cast<rage::gameSkeletonUpdateElement*>(group_child_node));
}
break;
}
}
if (patched)
{
LOGF(VERBOSE, "DefuseSigscanner: Patched out the sigscanner");
}
else
{
LOGF(WARNING, "DefuseSigscanner: Failed to patch the sigscanner");
}
}
void AnticheatBypass::RunOnStartupImpl()
{
bool loaded_late = false;
@@ -102,8 +50,6 @@ namespace YimMenu
void AnticheatBypass::RunScriptImpl()
{
DefuseSigscanner();
NativeHooks::AddHook("shop_controller"_J, NativeIndex::NET_GAMESERVER_BEGIN_SERVICE, &TransactionHook);
m_IsFSLLoaded = CheckForFSL();
-1
View File
@@ -3,7 +3,6 @@
#include "game/gta/invoker/Invoker.hpp"
#include "types/script/scrProgram.hpp"
#include "types/script/scrThread.hpp"
namespace YimMenu
@@ -27,7 +27,7 @@ namespace YimMenu::Submenus
static bool ShouldRenderPlayer(std::string_view name, std::string_view search)
{
if (!search[0])
if (search.empty())
return true;
if (name.size() < search.size())
+33 -2
View File
@@ -65,6 +65,37 @@ namespace YimMenu::Submenus
ImGui::SetClipboardText(std::to_string(rid1).c_str());
}
auto& platformAccountId = Players::GetSelected().GetHandle()->m_PlatformAccountId;
switch (platformAccountId.m_Platform)
{
case PlatformAccountId::PLATFORM_XBOX:
ImGui::Text("Xbox User ID:");
ImGui::SameLine();
if (ImGui::SmallButton(std::to_string(platformAccountId.m_XboxUserId).c_str()))
{
ImGui::SetClipboardText(std::to_string(platformAccountId.m_XboxUserId).c_str());
}
break;
case PlatformAccountId::PLATFORM_STEAM:
ImGui::Text("Steam ID:");
ImGui::SameLine();
if (ImGui::SmallButton(std::to_string(platformAccountId.m_SteamId).c_str()))
{
ImGui::SetClipboardText(std::to_string(platformAccountId.m_SteamId).c_str());
}
break;
case PlatformAccountId::PLATFORM_EPIC:
ImGui::Text("Epic Account ID:");
ImGui::SameLine();
if (ImGui::SmallButton(platformAccountId.m_EpicAccountId))
{
ImGui::SetClipboardText(platformAccountId.m_EpicAccountId);
}
break;
default:
break;
}
auto ip = Players::GetSelected().GetExternalAddress();
@@ -83,14 +114,14 @@ namespace YimMenu::Submenus
if (ImGui::Button("View SC Profile"))
FiberPool::Push([] {
uint64_t handle[13];
NETWORK::NETWORK_HANDLE_FROM_PLAYER(Players::GetSelected().GetId(), handle, sizeof(handle));
NETWORK::NETWORK_HANDLE_FROM_PLAYER(Players::GetSelected().GetId(), handle, std::size(handle));
NETWORK::NETWORK_SHOW_PROFILE_UI(handle);
});
ImGui::SameLine();
if (ImGui::Button("Add Friend"))
FiberPool::Push([] {
uint64_t handle[13];
NETWORK::NETWORK_HANDLE_FROM_PLAYER(Players::GetSelected().GetId(), handle, sizeof(handle));
NETWORK::NETWORK_HANDLE_FROM_PLAYER(Players::GetSelected().GetId(), handle, std::size(handle));
NETWORK::NETWORK_ADD_FRIEND(handle, "");
});
@@ -2,7 +2,6 @@
#include "core/frontend/manager/Category.hpp"
#include "game/frontend/items/Items.hpp"
#include <memory>
namespace YimMenu
{
@@ -0,0 +1,34 @@
#include "game/hooks/Hooks.hpp"
#include "core/util/Joaat.hpp"
#include "types/rage/gameSkeleton.hpp"
namespace YimMenu::Hooks
{
void Anticheat::GameSkeletonUpdate(rage::gameSkeleton* skeleton, int type)
{
for (auto mode = skeleton->m_UpdateModes; mode; mode = mode->m_Next)
{
if (mode->m_Type != type)
continue;
for (auto group = mode->m_Head; group; group = group->m_Next)
{
if (group->m_Hash != "Common Main"_J)
{
group->Run();
continue;
}
for (auto item = static_cast<rage::gameSkeletonUpdateGroup*>(group)->m_Head; item; item = item->m_Next)
{
if (item->m_Hash != 0xA0F39FB6 && item->m_Hash != "TamperActions"_J)
{
item->Run();
}
}
}
break;
}
}
}
+2
View File
@@ -21,6 +21,7 @@ namespace rage
class rlSessionDetailMsg;
class rlSessionInfo;
struct rlTaskStatus;
struct gameSkeleton;
}
class MatchmakingAttributes;
@@ -44,6 +45,7 @@ namespace YimMenu::Hooks
namespace Anticheat
{
extern void QueueDependency(__int64 a1);
extern void GameSkeletonUpdate(rage::gameSkeleton* skeleton, int type);
extern bool PrepareMetricForSending(rage::JsonSerializer* ser, void* a2, void* a3, rage::rlMetric* metric);
extern BOOL GetThreadContext(HANDLE hThread, LPCONTEXT lpContext);
extern void HttpStartRequest(void* request);
+5 -5
View File
@@ -411,11 +411,6 @@ namespace YimMenu
AssistedAimFindNewTarget = ptr.Sub(0x33).As<Functions::AssistedAimFindNewTarget>();
});
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<rage::gameSkeleton*>();
});
constexpr auto anticheatInitializedHashPtrn = Pattern<"89 9E C8 00 00 00 48 8B 0D ? ? ? ? 48 85 C9 74 46">("AnticheatInitializedHash&GetAnticheatInitializedHash");
scanner.Add(anticheatInitializedHashPtrn, [this](PointerCalculator ptr) {
AnticheatInitializedHash = ptr.Add(9).Rip().As<rage::Obf32**>();
@@ -457,6 +452,11 @@ namespace YimMenu
MatchmakingSessionDetailSendResponse = addr.Add(0x2F).Rip().As<PVOID>();
});
static constexpr auto gameSkeletonUpdatePtrn = Pattern<"56 48 83 EC 20 48 8B 81 40 01 00 00 48 85 C0">("GameSkeletonUpdate");
scanner.Add(gameSkeletonUpdatePtrn, [this](PointerCalculator addr) {
GameSkeletonUpdate = addr.As<PVOID>();
});
if (!scanner.Scan())
{
LOG(FATAL) << "Some patterns could not be found, unloading.";
+1 -1
View File
@@ -160,7 +160,6 @@ namespace YimMenu
PVOID GetDLCHash;
PVOID AssistedAimShouldReleaseEntity;
Functions::AssistedAimFindNewTarget AssistedAimFindNewTarget;
rage::gameSkeleton* GameSkeleton;
PVOID Nullsub;
rage::Obf32** AnticheatInitializedHash;
PVOID GetAnticheatInitializedHash;
@@ -171,6 +170,7 @@ namespace YimMenu
PVOID MatchmakingUpdate;
PVOID MatchmakingUnadvertise;
PVOID MatchmakingSessionDetailSendResponse;
PVOID GameSkeletonUpdate;
};
struct Pointers : PointerData
+2 -1
View File
@@ -8,6 +8,7 @@ class CGameDataHash
public:
bool m_IsJapaneseVersion;
std::array<rage::Obf32, 16> m_Data;
char m_GameSkeletonHash[0x18]; // Obf64
};
static_assert(sizeof(CGameDataHash) == 0x104);
static_assert(sizeof(CGameDataHash) == 0x11C);
#pragma pack(pop)
+21
View File
@@ -0,0 +1,21 @@
#pragma once
struct PlatformAccountId
{
enum Platform : uint8_t
{
PLATFORM_INVALID = 0,
PLATFORM_XBOX = 1,
PLATFORM_STEAM = 10,
PLATFORM_EPIC = 15
};
union {
uint64_t m_XboxUserId; //0x0000
uint64_t m_SteamId;
char m_EpicAccountId[32 + 1];
char m_Pad[40];
};
Platform m_Platform; //0x0028
};
static_assert(sizeof(PlatformAccountId) == 0x30);
+3 -1
View File
@@ -1,5 +1,6 @@
#pragma once
#include "types/rage/RTTI.hpp"
#include "PlatformAccountId.hpp"
namespace rage
{
@@ -31,7 +32,8 @@ namespace rage
int m_AccountId; //0x0008
int64_t m_RockstarId; //0x0010
char pad_0018[0x38]; //0x0018 voice chat stuff
PlatformAccountId m_PlatformAccountId; //0x0018
uint32_t unk_0048; //0x0048
CNonPhysicalPlayerData* m_NonPhysicalPlayer; //0x0050
uint32_t m_MessageId; //0x0058
char pad_005C[4]; //0x005C