feat: add experimental standalone bypass

This commit is contained in:
maybegreat48 committed 2025-03-26 19:25:47 -04:00
1 parent b13352897e
commit 1bfdf2d8f4
11 files changed
+183 -2

No files matched your search

+53
View File
@@ -0,0 +1,53 @@
#include "AnticheatBypass.hpp"
#include "core/backend/ScriptMgr.hpp"
#include "core/memory/ModuleMgr.hpp"
#include "core/util/Joaat.hpp"
#include "game/pointers/Pointers.hpp"
#include "game/backend/NativeHooks.hpp"
#include "game/gta/Natives.hpp"
namespace YimMenu
{
static bool CheckForFSL()
{
int num_versions = 0;
for (auto& module : ModuleMgr.GetModules())
if (module.first == "version.dll"_J)
num_versions++;
return num_versions > 1;
}
static void TransactionHook(rage::scrNativeCallContext* ctx)
{
if (ctx->GetArg<int>(3) == -50712147)
{
LOG(WARNING) << "NET_GAMESERVER_BEGIN_SERVICE: blocked shop_controller report";
return ctx->SetReturnValue(FALSE);
}
return ctx->SetReturnValue(NETSHOPPING::NET_GAMESERVER_BEGIN_SERVICE(ctx->GetArg<int*>(0), ctx->GetArg<Hash>(1), ctx->GetArg<Hash>(2), ctx->GetArg<Hash>(3), ctx->GetArg<int>(4), ctx->GetArg<int>(5)));
}
void AnticheatBypass::RunScriptImpl()
{
NativeHooks::AddHook("shop_controller"_J, NativeIndex::NET_GAMESERVER_BEGIN_SERVICE, &TransactionHook);
m_IsFSLLoaded = CheckForFSL();
LOG(INFO) << (m_IsFSLLoaded ? "FSL is loaded" : "FSL is NOT loaded");
if (!m_IsFSLLoaded)
Pointers.BattlEyeStatusUpdatePatch->Apply();
while (true)
{
if (!m_IsFSLLoaded)
{
*Pointers.BERestartStatus = 0;
*Pointers.NeedsBERestart = false;
*Pointers.IsBEBanned = false;
}
ScriptMgr::Yield();
}
}
}
+29
View File
@@ -0,0 +1,29 @@
#pragma once
namespace YimMenu
{
class AnticheatBypass
{
private:
static AnticheatBypass& GetInstance()
{
static AnticheatBypass instance;
return instance;
}
void RunScriptImpl();
bool m_IsFSLLoaded = false;
public:
static void RunScript()
{
GetInstance().RunScriptImpl();
}
static bool IsFSLLoaded()
{
return GetInstance().m_IsFSLLoaded;
}
};
}
@@ -0,0 +1,10 @@
#include "core/hooking/DetourHook.hpp"
#include "game/hooks/Hooks.hpp"
namespace YimMenu::Hooks
{
bool Anticheat::PrepareMetricForSending(rage::JsonSerializer* ser, void* a2, void* a3, rage::rlMetric* metric)
{
return false; // don't send any telemetry
}
}
+3
View File
@@ -11,6 +11,8 @@ namespace rage
class scrProgram;
class netObject;
class datBitBuffer;
class JsonSerializer;
class rlMetric;
}
namespace YimMenu
@@ -31,6 +33,7 @@ namespace YimMenu::Hooks
namespace Anticheat
{
extern void QueueDependency(__int64 a1);
extern bool PrepareMetricForSending(rage::JsonSerializer* ser, void* a2, void* a3, rage::rlMetric* metric);
}
namespace Info
+56 -1
View File
@@ -1,7 +1,9 @@
#include "core/hooking/DetourHook.hpp"
#include "game/backend/AnticheatBypass.hpp"
#include "game/backend/Players.hpp"
#include "game/frontend/ChatDisplay.hpp"
#include "game/hooks/Hooks.hpp"
#include "game/gta/Packet.hpp"
#include "types/network/netEvent.hpp"
#include "types/network/netMessage.hpp"
#include "types/rage/datBitBuffer.hpp"
@@ -43,7 +45,7 @@ namespace YimMenu::Hooks
buffer.ReadString(msg, sizeof(msg)); // we don't need the rest
ChatDisplay::Show(player.GetName(), msg, ImGui::Colors::LightBlue);
}
break;
return; // the game doesn't handle that anyway
}
case rage::netMessage::Type::PackedEvents:
{
@@ -88,6 +90,59 @@ namespace YimMenu::Hooks
break;
}
case rage::netMessage::Type::KickPlayer:
{
if (!AnticheatBypass::IsFSLLoaded())
return;
break;
}
case rage::netMessage::Type::BattlEyeCmd:
{
if (!AnticheatBypass::IsFSLLoaded())
{
char data[1028]{};
int size = buffer.Read<int>(11);
bool from_client = buffer.Read<bool>(1);
buffer.Seek(4, true); // normalize before we read
buffer.ReadArrayBytes(&data, size);
if (from_client)
break;
Packet reply;
char reply_buf[1028]{};
int reply_sz = 0;
auto op = data[0];
if (op == 0)
{
char payload[] = {0x0, 0x5};
reply_sz = sizeof(payload);
memcpy(reply_buf, payload, reply_sz);
}
else if (op == 2 || op == 4)
{
char payload[] = {op, data[1]};
reply_sz = sizeof(payload);
memcpy(reply_buf, payload, reply_sz);
}
else if (op == 9)
{
reply_sz = size;
memcpy(reply_buf, data, reply_sz);
}
reply.WriteMessageHeader(rage::netMessage::Type::BattlEyeCmd);
reply.GetBuffer().Write<int>(reply_sz, 11);
reply.GetBuffer().Write<bool>(true, 1);
reply.GetBuffer().Seek(4, false);
reply.GetBuffer().WriteArrayBytes(reply_buf, reply_sz);
reply.Send(fr_evt->m_MsgId);
return;
}
break;
}
default:
break;
}
+17
View File
@@ -207,6 +207,23 @@ namespace YimMenu
ScriptVM = ptr.Sub(0x24).As<PVOID>();
});
constexpr auto prepareMetricForSendingPtrn = Pattern<"48 89 F9 FF 50 20 48 8D 15">("PrepareMetricForSending");
scanner.Add(prepareMetricForSendingPtrn, [this](PointerCalculator ptr) {
PrepareMetricForSending = ptr.Sub(0x26).As<PVOID>();
});
constexpr auto beDataPtrn = Pattern<"48 C7 05 ? ? ? ? 00 00 00 00 E8 ? ? ? ? 48 89 C1 E8 ? ? ? ? E8 ? ? ? ? BD 0A 00 00 00">("BEData");
scanner.Add(beDataPtrn, [this](PointerCalculator ptr) {
BERestartStatus = ptr.Add(3).Rip().Add(8).Add(4).As<int*>();
NeedsBERestart = ptr.Add(3).Rip().Add(8).Add(4).Add(8).As<bool*>();
IsBEBanned = ptr.Add(3).Rip().Add(8).Add(4).Add(8).Add(4).As<bool*>();
});
constexpr auto battlEyeStatusUpdatePatchPtrn = Pattern<"80 B9 92 0A 00 00 01">("BattlEyeStatusUpdatePatch");
scanner.Add(battlEyeStatusUpdatePatchPtrn, [this](PointerCalculator ptr) {
BattlEyeStatusUpdatePatch = BytePatches::Add(ptr.Sub(0x26).As<std::uint8_t*>(), 0xC3);
});
if (!scanner.Scan())
{
LOG(FATAL) << "Some patterns could not be found, unloading.";
+5
View File
@@ -84,6 +84,11 @@ namespace YimMenu
PVOID QueueDependency;
PVOID SigScanMemory;
PVOID ScriptVM;
PVOID PrepareMetricForSending;
int* BERestartStatus;
bool* NeedsBERestart;
bool* IsBEBanned;
BytePatch BattlEyeStatusUpdatePatch;
};
struct Pointers : PointerData