diff --git a/src/core/hooking/Hooking.cpp b/src/core/hooking/Hooking.cpp index 4f9f7b3..48f512c 100644 --- a/src/core/hooking/Hooking.cpp +++ b/src/core/hooking/Hooking.cpp @@ -18,6 +18,7 @@ namespace YimMenu BaseHook::Add(new DetourHook("QueueDependency", Pointers.QueueDependency, Hooks::Anticheat::QueueDependency)); BaseHook::Add(new DetourHook("PrepareMetricForSending", Pointers.PrepareMetricForSending, Hooks::Anticheat::PrepareMetricForSending)); + BaseHook::Add(new DetourHook("GetThreadContext", reinterpret_cast(GetProcAddress(LoadLibraryA("kernel32.dll"), "GetThreadContext")), Hooks::Anticheat::GetThreadContext)); BaseHook::Add(new DetourHook("RunScriptThreads", Pointers.RunScriptThreads, Hooks::Script::RunScriptThreads)); BaseHook::Add(new DetourHook("InitNativeTables", Pointers.InitNativeTables, Hooks::Script::InitNativeTables)); diff --git a/src/game/hooks/Anticheat/GetThreadContext.cpp b/src/game/hooks/Anticheat/GetThreadContext.cpp new file mode 100644 index 0000000..67f01a8 --- /dev/null +++ b/src/game/hooks/Anticheat/GetThreadContext.cpp @@ -0,0 +1,15 @@ +#include "core/hooking/DetourHook.hpp" +#include "game/hooks/Hooks.hpp" + +namespace YimMenu::Hooks +{ + BOOL Anticheat::GetThreadContext(HANDLE hThread, LPCONTEXT lpContext) + { + auto ret = BaseHook::Get>()->Original()(hThread, lpContext); + lpContext->Dr0 = 0; + lpContext->Dr1 = 0; + lpContext->Dr2 = 0; + lpContext->Dr3 = 0; + return ret; + } +} \ No newline at end of file diff --git a/src/game/hooks/Anticheat/QueueDependency.cpp b/src/game/hooks/Anticheat/QueueDependency.cpp index bda4460..a9c81be 100644 --- a/src/game/hooks/Anticheat/QueueDependency.cpp +++ b/src/game/hooks/Anticheat/QueueDependency.cpp @@ -39,10 +39,10 @@ namespace YimMenu::Hooks { auto f1 = *reinterpret_cast(a1 + 0x60); auto f2 = *reinterpret_cast(a1 + 0x100); - auto f3 = *reinterpret_cast(a1 + 0x1D0); + auto f3 = *reinterpret_cast(a1 + 0x1A0); if (!f1) - BaseHook::Get>()->Original()(a1); + return BaseHook::Get>()->Original()(a1); if (f1 == Pointers.SigScanMemory) { diff --git a/src/game/hooks/Hooks.hpp b/src/game/hooks/Hooks.hpp index 76ca93a..4c2dd21 100644 --- a/src/game/hooks/Hooks.hpp +++ b/src/game/hooks/Hooks.hpp @@ -35,6 +35,7 @@ namespace YimMenu::Hooks { extern void QueueDependency(__int64 a1); extern bool PrepareMetricForSending(rage::JsonSerializer* ser, void* a2, void* a3, rage::rlMetric* metric); + extern BOOL GetThreadContext(HANDLE hThread, LPCONTEXT lpContext); } namespace Info diff --git a/src/game/hooks/Network/HandleNetGameEvent.cpp b/src/game/hooks/Network/HandleNetGameEvent.cpp index 90d978a..215f236 100644 --- a/src/game/hooks/Network/HandleNetGameEvent.cpp +++ b/src/game/hooks/Network/HandleNetGameEvent.cpp @@ -22,7 +22,7 @@ namespace YimMenu::Hooks } // Returns true if bad event - bool ScanExplosionEvent(CExplosionEvent& event, Player player) + static bool ScanExplosionEvent(CExplosionEvent& event, Player player) { if (*(int16_t*)&event.m_InteriorIndex < -1) { @@ -51,7 +51,7 @@ namespace YimMenu::Hooks return false; } - bool ScanPlaySoundEvent(CPlaySoundEvent& event, Player player) + static bool ScanPlaySoundEvent(CPlaySoundEvent& event, Player player) { static constexpr std::array blocked_ref_hashes = {"Arena_Vehicle_Mod_Shop_Sounds"_J, "CELEBRATION_SOUNDSET"_J, "DLC_AW_Arena_Office_Planning_Wall_Sounds"_J, "DLC_AW_Arena_Spin_Wheel_Game_Frontend_Sounds"_J, "DLC_Biker_SYG_Sounds"_J, "DLC_BTL_SECURITY_VANS_RADAR_PING_SOUNDS"_J, "DLC_BTL_Target_Pursuit_Sounds"_J, "DLC_GR_Bunker_Door_Sounds"_J, "DLC_GR_CS2_Sounds"_J, "DLC_IO_Warehouse_Mod_Garage_Sounds"_J, "DLC_MPSUM2_HSW_Up_Sounds"_J, "DLC_sum20_Business_Battle_AC_Sounds"_J, "DLC_TG_Running_Back_Sounds"_J, "dlc_vw_table_games_frontend_sounds"_J, "dlc_xm_facility_entry_exit_sounds"_J, "Frontend"_J, "GTAO_Boss_Goons_FM_Soundset"_J, "GTAO_Exec_SecuroServ_Computer_Sounds"_J, "GTAO_Exec_SecuroServ_Warehouse_PC_Sounds"_J, "GTAO_Script_Doors_Faded_Screen_Sounds"_J, "GTAO_SMG_Hangar_Computer_Sounds"_J, "HUD_AMMO_SHOP_SOUNDSET"_J, "HUD_FRONTEND_CUSTOM_SOUNDSET"_J, "HUD_FRONTEND_DEFAULT_SOUNDSET"_J, "HUD_FRONTEND_MP_SOUNDSET"_J, "HUD_FRONTEND_MP_COLLECTABLE_SOUNDS"_J, "HUD_FRONTEND_TATTOO_SHOP_SOUNDSET"_J, "HUD_FRONTEND_CLOTHESSHOP_SOUNDSET"_J, "HUD_FRONTEND_STANDARD_PICKUPS_NPC_SOUNDSET"_J, "HUD_FRONTEND_VEHICLE_PICKUPS_NPC_SOUNDSET"_J, "HUD_FRONTEND_WEAPONS_PICKUPS_NPC_SOUNDSET"_J, "HUD_FREEMODE_SOUNDSET"_J, "HUD_MINI_GAME_SOUNDSET"_J, "HUD_AWARDS"_J, "JA16_Super_Mod_Garage_Sounds"_J, "Low2_Super_Mod_Garage_Sounds"_J, "MissionFailedSounds"_J, "MP_CCTV_SOUNDSET"_J, "MP_LOBBY_SOUNDS"_J, "MP_MISSION_COUNTDOWN_SOUNDSET"_J, "Phone_SoundSet_Default"_J, "Phone_SoundSet_Glasses_Cam"_J, "Phone_SoundSet_Prologue"_J, "Phone_SoundSet_Franklin"_J, "Phone_SoundSet_Michael"_J, "Phone_SoundSet_Trevor"_J, "PLAYER_SWITCH_CUSTOM_SOUNDSET"_J, "RESPAWN_ONLINE_SOUNDSET"_J, "TATTOOIST_SOUNDS"_J, "WastedSounds"_J, "WEB_NAVIGATION_SOUNDS_PHONE"_J}; static constexpr std::array blocked_sound_hashes = {"Remote_Ring"_J, "COP_HELI_CAM_ZOOM"_J, "Object_Dropped_Remote"_J}; @@ -258,6 +258,7 @@ namespace YimMenu::Hooks if (self_veh && self_veh.GetNetworkObjectId() == entity) { // Vehicle kick + LOGF(WARNING, "Blocked SCRIPT_ENTITY_STATE_CHANGE_EVENT of type SetVehicleExclusiveDriver from {} on our local vehicle", player.GetName()); return false; } } @@ -315,6 +316,19 @@ namespace YimMenu::Hooks break; } + case rage::netGameEvent::Type::RAGDOLL_REQUEST_EVENT: + { + CRagdollRequestEvent event; + event.Deserialize(buffer); + + if (Self::GetPed().GetNetworkObjectId() == event.m_PedToRagdoll) + { + // is sometimes used legit, beware + return false; + } + + break; + } default: break; } diff --git a/src/game/hooks/Network/ReceiveNetMessage.cpp b/src/game/hooks/Network/ReceiveNetMessage.cpp index 3ec6d2d..23de359 100644 --- a/src/game/hooks/Network/ReceiveNetMessage.cpp +++ b/src/game/hooks/Network/ReceiveNetMessage.cpp @@ -4,6 +4,7 @@ #include "game/frontend/ChatDisplay.hpp" #include "game/hooks/Hooks.hpp" #include "game/gta/Packet.hpp" +#include "game/backend/Self.hpp" #include "types/network/netEvent.hpp" #include "types/network/netMessage.hpp" #include "types/rage/datBitBuffer.hpp" @@ -66,10 +67,10 @@ namespace YimMenu::Hooks { int bits_read = buffer.m_BitsRead; - uint16_t event_id = buffer.Read(7); - uint32_t event_index = buffer.Read(9); + uint16_t event_id = buffer.Read(7); + uint32_t event_index = buffer.Read(9); uint32_t event_handled_bits = buffer.Read(8); - uint32_t event_data_size = buffer.Read(15); + uint32_t event_data_size = buffer.Read(15); if (buffer.Read(1)) buffer.Read(16); @@ -90,6 +91,63 @@ namespace YimMenu::Hooks break; } + case rage::netMessage::Type::PackedReliables: + { + auto player = Players::GetByMessageId(fr_evt->m_MsgId); + + auto flags = buffer.Read(4); + + if ((flags & 1) != 0) + { + auto timestamp = buffer.Read(32); + if (auto num_msgs = buffer.Read(5)) + buffer.Seek(buffer.Read(13)); + } + + if ((flags & 2) != 0) + { + if (auto num_msgs = buffer.Read(5)) + buffer.Seek(buffer.Read(13)); + } + + if ((flags & 4) != 0) + { + if (auto num_msgs = buffer.Read(5)) + { + auto sz = buffer.Read(13); + auto pos_now = buffer.m_BitsRead; + while (pos_now + sz > buffer.m_BitsRead) + { + auto id = buffer.Read(13); + auto token = buffer.Read(5); + bool reject = false; + + if (Self::GetPed().GetPointer() && Self::GetPed().GetNetworkObjectId() == id) + { + if (player) + LOGF(WARNING, "Blocked player deletion crash from {}", player.GetName()); + reject = true; + } + + if (Self::GetVehicle() && Self::GetVehicle().HasControl() && Self::GetVehicle().GetNetworkObjectId() == id) + { + if (player) + LOGF(WARNING, "Blocked vehicle deletion from {}", player.GetName()); + reject = true; + } + + if (reject) + { + rage::datBitBuffer write_buf(fr_evt->m_Data, fr_evt->m_Length); + write_buf.Seek(buffer.m_BitsRead - 5 - 13); + write_buf.Write(0xFFFF, 16); + } + } + } + } + + break; + } case rage::netMessage::Type::KickPlayer: { if (!AnticheatBypass::IsFSLLoaded()) @@ -103,7 +161,7 @@ namespace YimMenu::Hooks char data[1028]{}; int size = buffer.Read(11); bool from_client = buffer.Read(1); - buffer.Seek(4, true); // normalize before we read + buffer.Seek(4); // normalize before we read buffer.ReadArrayBytes(&data, size); if (from_client) @@ -136,7 +194,7 @@ namespace YimMenu::Hooks reply.WriteMessageHeader(rage::netMessage::Type::BattlEyeCmd); reply.GetBuffer().Write(reply_sz, 11); reply.GetBuffer().Write(true, 1); - reply.GetBuffer().Seek(4, false); + reply.GetBuffer().Seek(4); reply.GetBuffer().WriteArrayBytes(reply_buf, reply_sz); reply.Send(fr_evt->m_MsgId); return; diff --git a/src/main.cpp b/src/main.cpp index 9564047..cb2bb53 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,7 @@ #include "core/renderer/Renderer.hpp" #include "game/backend/AnticheatBypass.hpp" #include "game/backend/Players.hpp" +#include "game/backend/SavedLocations.hpp" #include "game/backend/Self.hpp" #include "game/backend/NativeHooks.hpp" #include "game/frontend/GUI.hpp" @@ -26,6 +27,7 @@ namespace YimMenu LogHelper::Init("YimMenuV2", FileMgr::GetProjectFile("./cout.log")); g_HotkeySystem.RegisterCommands(); + SavedLocations::FetchSavedLocations(); Settings::Initialize(FileMgr::GetProjectFile("./settings.json")); if (!ModuleMgr.LoadModules()) diff --git a/src/types/network/netGameEvent.cpp b/src/types/network/netGameEvent.cpp index fbaf743..a2ac3f9 100644 --- a/src/types/network/netGameEvent.cpp +++ b/src/types/network/netGameEvent.cpp @@ -227,4 +227,9 @@ void CUpdateFxnEvent::Deserialize(rage::datBitBuffer& buffer) { m_0x30 = buffer.Read(32); m_0x34 = buffer.Read(32); -} \ No newline at end of file +} + +void CRagdollRequestEvent::Deserialize(rage::datBitBuffer& buffer) +{ + m_PedToRagdoll = buffer.Read(13); +} diff --git a/src/types/network/netGameEvent.hpp b/src/types/network/netGameEvent.hpp index eb18b78..7241d33 100644 --- a/src/types/network/netGameEvent.hpp +++ b/src/types/network/netGameEvent.hpp @@ -102,15 +102,15 @@ namespace rage NETWORK_CHECK_CATALOG_CRC }; - virtual ~netGameEvent() = default; + virtual ~netGameEvent() {}; - virtual const char* GetName() = 0; - virtual bool IsInScope(netPlayer* player) = 0; - virtual bool TimeToResend(uint32_t time) = 0; - virtual bool CanChangeScope() = 0; + virtual const char* GetName() { return nullptr; }; + virtual bool IsInScope(netPlayer* player) { return {}; }; + virtual bool TimeToResend(uint32_t time) { return {}; }; + virtual bool CanChangeScope() { return {}; }; virtual void PrepareData(datBitBuffer* buffer, netPlayer* source_player, netPlayer* target_player) {}; virtual void HandleData(datBitBuffer* buffer, netPlayer* source_player, netPlayer* target_player) {}; - virtual bool Decide(netPlayer* source_player, netPlayer* target_player) = 0; + virtual bool Decide(netPlayer* source_player, netPlayer* target_player) { return false; }; virtual void PrepareReply(datBitBuffer* buffer, netPlayer* reply_player) {}; virtual void HandleReply(datBitBuffer* buffer, netPlayer* souce_player) {}; virtual void PrepareExtraData(datBitBuffer* buffer, bool is_reply, netPlayer* player, netPlayer* player2) {}; @@ -123,12 +123,12 @@ namespace rage virtual void unk_0x78() {}; public: - virtual bool operator==(netGameEvent const& other) = 0; - virtual bool operator!=(netGameEvent const& other) = 0; + virtual bool operator==(netGameEvent const& other) { return {}; }; + virtual bool operator!=(netGameEvent const& other) { return {}; }; - virtual bool MustPersist() = 0; - virtual bool MustPersistWhenOutOfScope() = 0; - virtual bool HasTimedOut() = 0; + virtual bool MustPersist() { return {}; }; + virtual bool MustPersistWhenOutOfScope() { return {}; }; + virtual bool HasTimedOut() { return {}; }; public: Type m_Type; // 0x08 @@ -148,7 +148,7 @@ namespace rage static_assert(sizeof(rage::netGameEvent) == 0x30); } -class CScriptedGameEvent // : public rage::netGameEvent +class CScriptedGameEvent : public rage::netGameEvent { public: bool Deserialize(rage::datBitBuffer& buffer); @@ -159,7 +159,7 @@ public: uint32_t m_ArgsSize; // 0x224 }; -class CNetworkIncrementStatEvent +class CNetworkIncrementStatEvent : public rage::netGameEvent { public: void Deserialize(rage::datBitBuffer& buffer); @@ -168,7 +168,7 @@ public: uint32_t m_Amount; // 0x34 }; -class CDoorBreakEvent +class CDoorBreakEvent : public rage::netGameEvent { public: void Deserialize(rage::datBitBuffer& buffer); @@ -177,7 +177,7 @@ public: uint8_t m_DoorId; // 0x32 }; -class CPlaySoundEvent +class CPlaySoundEvent : public rage::netGameEvent { public: void Deserialize(rage::datBitBuffer& buffer); @@ -192,7 +192,7 @@ public: int m_0xA0; // 0xA0 }; -class CWeaponDamageEvent +class CWeaponDamageEvent : public rage::netGameEvent { public: void Deserialize(rage::datBitBuffer& buffer); @@ -232,7 +232,7 @@ public: uint8_t m_0x94; // 0x94 }; -class CActivateVehicleSpecialAbilityEvent +class CActivateVehicleSpecialAbilityEvent : public rage::netGameEvent { public: void Deserialize(rage::datBitBuffer& buffer); @@ -243,7 +243,7 @@ public: }; enum class ExplosionType; -class CExplosionEvent +class CExplosionEvent : public rage::netGameEvent { public: void Deserialize(rage::datBitBuffer& buffer); @@ -333,11 +333,19 @@ public: }; }; -class CUpdateFxnEvent +class CUpdateFxnEvent : public rage::netGameEvent { public: void Deserialize(rage::datBitBuffer& buffer); uint32_t m_0x30; // 0x30 uint32_t m_0x34; // 0x34 +}; + +class CRagdollRequestEvent : public rage::netGameEvent +{ +public: + void Deserialize(rage::datBitBuffer& buffer); + + uint16_t m_PedToRagdoll; // 0x30 }; \ No newline at end of file diff --git a/src/types/rage/datBitBuffer.hpp b/src/types/rage/datBitBuffer.hpp index f7386bc..85f6aa6 100644 --- a/src/types/rage/datBitBuffer.hpp +++ b/src/types/rage/datBitBuffer.hpp @@ -274,21 +274,21 @@ namespace rage return true; } - inline bool IsReadBuffer() + inline bool IsReadBuffer() const { return m_FlagBits & 1; } - inline bool IsSizeCalculator() + inline bool IsSizeCalculator() const { return m_FlagBits & 2; } - void Seek(int bits, bool read) + void Seek(int bits) { m_BitsRead += bits; - if (read) + if (IsReadBuffer()) { if (m_HighestBitsRead > m_CurBit) m_CurBit = m_HighestBitsRead; @@ -309,7 +309,7 @@ namespace rage return false; ReadBitsSingle(static_cast(m_Data), out, size, m_BitsRead + m_BitOffset); - Seek(size, true); + Seek(size); return true; } @@ -323,7 +323,7 @@ namespace rage if (!IsSizeCalculator()) WriteBitsSingle(static_cast(m_Data), val, size, m_BitsRead + m_BitOffset); - Seek(size, false); + Seek(size); return true; } @@ -406,7 +406,7 @@ namespace rage { if (!IsSizeCalculator()) CopyBits(reinterpret_cast(reinterpret_cast(m_Data) + (m_BitOffset >> 3)), array, bits, m_BitsRead + (m_BitOffset & 7), 0); - Seek(bits, false); + Seek(bits); } } @@ -422,7 +422,7 @@ namespace rage if (!IsSizeCalculator()) CopyBits(array, reinterpret_cast(reinterpret_cast(m_Data) + (m_BitOffset >> 3)), bits, 0, m_BitsRead + (m_BitOffset & 7)); - Seek(bits, true); + Seek(bits); } void ReadArrayBytes(void* array, int bytes) @@ -519,6 +519,11 @@ namespace rage WriteSignedFloat(size, divisor, vec.z); } + void AlignToByteBoundary() + { + Seek(((m_BitsRead + 7) >> 3) - m_BitsRead); + } + public: void* m_Data; //0x0000 uint32_t m_BitOffset; //0x0008