diff --git a/src/core/hooking/Hooking.cpp b/src/core/hooking/Hooking.cpp index 1a24f85..4f9f7b3 100644 --- a/src/core/hooking/Hooking.cpp +++ b/src/core/hooking/Hooking.cpp @@ -17,6 +17,7 @@ namespace YimMenu BaseHook::Add(new DetourHook("ResizeBuffers", swapchain_vft[Hooks::SwapChain::VMTResizeBuffersIdx], Hooks::SwapChain::ResizeBuffers)); BaseHook::Add(new DetourHook("QueueDependency", Pointers.QueueDependency, Hooks::Anticheat::QueueDependency)); + BaseHook::Add(new DetourHook("PrepareMetricForSending", Pointers.PrepareMetricForSending, Hooks::Anticheat::PrepareMetricForSending)); BaseHook::Add(new DetourHook("RunScriptThreads", Pointers.RunScriptThreads, Hooks::Script::RunScriptThreads)); BaseHook::Add(new DetourHook("InitNativeTables", Pointers.InitNativeTables, Hooks::Script::InitNativeTables)); diff --git a/src/core/memory/ModuleMgr.cpp b/src/core/memory/ModuleMgr.cpp index 4bfb663..bc54f5d 100644 --- a/src/core/memory/ModuleMgr.cpp +++ b/src/core/memory/ModuleMgr.cpp @@ -46,4 +46,9 @@ namespace YimMenu return true; } + + std::unordered_multimap>& ModuleMgr::GetModules() + { + return m_CachedModules; + } } \ No newline at end of file diff --git a/src/core/memory/ModuleMgr.hpp b/src/core/memory/ModuleMgr.hpp index 076707d..1edef53 100644 --- a/src/core/memory/ModuleMgr.hpp +++ b/src/core/memory/ModuleMgr.hpp @@ -26,9 +26,10 @@ namespace YimMenu * @return false If the peb or peb->Ldr pointer were invalid. */ bool LoadModules(); + std::unordered_multimap>& GetModules(); private: - std::unordered_map> m_CachedModules; + std::unordered_multimap> m_CachedModules; }; inline YimMenu::ModuleMgr ModuleMgr; diff --git a/src/game/backend/AnticheatBypass.cpp b/src/game/backend/AnticheatBypass.cpp new file mode 100644 index 0000000..553207f --- /dev/null +++ b/src/game/backend/AnticheatBypass.cpp @@ -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(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(0), ctx->GetArg(1), ctx->GetArg(2), ctx->GetArg(3), ctx->GetArg(4), ctx->GetArg(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(); + } + } +} \ No newline at end of file diff --git a/src/game/backend/AnticheatBypass.hpp b/src/game/backend/AnticheatBypass.hpp new file mode 100644 index 0000000..9b1c0a4 --- /dev/null +++ b/src/game/backend/AnticheatBypass.hpp @@ -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; + } + }; +} \ No newline at end of file diff --git a/src/game/hooks/Anticheat/PrepareMetricForSending.cpp b/src/game/hooks/Anticheat/PrepareMetricForSending.cpp new file mode 100644 index 0000000..2e13d81 --- /dev/null +++ b/src/game/hooks/Anticheat/PrepareMetricForSending.cpp @@ -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 + } +} \ No newline at end of file diff --git a/src/game/hooks/Hooks.hpp b/src/game/hooks/Hooks.hpp index 7a8de5d..1916eb6 100644 --- a/src/game/hooks/Hooks.hpp +++ b/src/game/hooks/Hooks.hpp @@ -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 diff --git a/src/game/hooks/Network/ReceiveNetMessage.cpp b/src/game/hooks/Network/ReceiveNetMessage.cpp index 9c79004..49e47df 100644 --- a/src/game/hooks/Network/ReceiveNetMessage.cpp +++ b/src/game/hooks/Network/ReceiveNetMessage.cpp @@ -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(11); + bool from_client = buffer.Read(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(reply_sz, 11); + reply.GetBuffer().Write(true, 1); + reply.GetBuffer().Seek(4, false); + reply.GetBuffer().WriteArrayBytes(reply_buf, reply_sz); + reply.Send(fr_evt->m_MsgId); + return; + } + break; + } default: break; } diff --git a/src/game/pointers/Pointers.cpp b/src/game/pointers/Pointers.cpp index 0e79c81..78af218 100644 --- a/src/game/pointers/Pointers.cpp +++ b/src/game/pointers/Pointers.cpp @@ -207,6 +207,23 @@ namespace YimMenu ScriptVM = ptr.Sub(0x24).As(); }); + 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(); + }); + + 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(); + NeedsBERestart = ptr.Add(3).Rip().Add(8).Add(4).Add(8).As(); + IsBEBanned = ptr.Add(3).Rip().Add(8).Add(4).Add(8).Add(4).As(); + }); + + 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(), 0xC3); + }); + 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 e761327..21780c2 100644 --- a/src/game/pointers/Pointers.hpp +++ b/src/game/pointers/Pointers.hpp @@ -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 diff --git a/src/main.cpp b/src/main.cpp index cdd34b6..9564047 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,7 @@ #include "core/hooking/Hooking.hpp" #include "core/memory/ModuleMgr.hpp" #include "core/renderer/Renderer.hpp" +#include "game/backend/AnticheatBypass.hpp" #include "game/backend/Players.hpp" #include "game/backend/Self.hpp" #include "game/backend/NativeHooks.hpp" @@ -46,6 +47,7 @@ namespace YimMenu GUI::Init(); ScriptMgr::AddScript(std::make_unique