From 2e18e1927f39c4b45ff0eb904e3ef94bd27b9715 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Wed, 22 Nov 2023 12:55:10 -0500 Subject: [PATCH 01/23] feat (anticheat): Anticheat Port --- .../characters/2023_11_12_00_characters.sql | 45 + sql/updates/world/2023_11_22_world.sql | 13 + src/server/game/Anticheat/AnticheatMgr.cpp | 1306 +++++++++++++++++ src/server/game/Anticheat/AnticheatMgr.h | 123 ++ src/server/game/CMakeLists.txt | 4 + src/server/game/Entities/Player/Player.cpp | 8 +- src/server/game/Entities/Player/Player.h | 4 +- src/server/game/Entities/Unit/Unit.cpp | 8 + src/server/game/Handlers/MovementHandler.cpp | 8 +- src/server/game/Handlers/TaxiHandler.cpp | 5 + src/server/game/Miscellaneous/Language.h | 1 + src/server/game/Movement/MotionMaster.cpp | 24 + src/server/game/Movement/MotionMaster.h | 2 +- src/server/game/Scripting/ScriptLoader.cpp | 2 + src/server/game/Server/WorldSession.cpp | 13 + src/server/game/Server/WorldSession.h | 4 + .../game/Spells/Auras/SpellAuraEffects.cpp | 5 + src/server/game/Spells/Spell.cpp | 6 + src/server/game/Spells/Spell.h | 1 + src/server/game/Spells/SpellEffects.cpp | 28 + src/server/game/World/World.cpp | 36 + src/server/game/World/World.h | 32 + src/server/scripts/Commands/cs_anticheat.cpp | 267 ++++ .../Implementation/CharacterDatabase.cpp | 4 + .../Implementation/CharacterDatabase.h | 4 + .../Database/Implementation/WorldDatabase.cpp | 2 + .../Database/Implementation/WorldDatabase.h | 2 +- src/server/worldserver/worldserver.conf.dist | 138 ++ 28 files changed, 2090 insertions(+), 5 deletions(-) create mode 100644 sql/updates/characters/2023_11_12_00_characters.sql create mode 100644 sql/updates/world/2023_11_22_world.sql create mode 100644 src/server/game/Anticheat/AnticheatMgr.cpp create mode 100644 src/server/game/Anticheat/AnticheatMgr.h create mode 100644 src/server/scripts/Commands/cs_anticheat.cpp diff --git a/sql/updates/characters/2023_11_12_00_characters.sql b/sql/updates/characters/2023_11_12_00_characters.sql new file mode 100644 index 00000000000..b10a4685d0a --- /dev/null +++ b/sql/updates/characters/2023_11_12_00_characters.sql @@ -0,0 +1,45 @@ +CREATE TABLE IF NOT EXISTS `lua_cheaters` ( + `guid` int unsigned NOT NULL DEFAULT 0, + `account` int unsigned NOT NULL DEFAULT 0, + `macro` varchar(255) NOT NULL DEFAULT '', + PRIMARY KEY (`guid`,`account`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +DROP TABLE `daily_players_reports`; +CREATE TABLE IF NOT EXISTS `daily_players_reports` ( + `guid` int unsigned NOT NULL DEFAULT 0, + `creation_time` int unsigned NOT NULL DEFAULT 0, + `average` float NOT NULL DEFAULT 0, + `total_reports` bigint unsigned NOT NULL DEFAULT 0, + `speed_reports` bigint unsigned NOT NULL DEFAULT 0, + `fly_reports` bigint unsigned NOT NULL DEFAULT 0, + `jump_reports` bigint unsigned NOT NULL DEFAULT 0, + `waterwalk_reports` bigint unsigned NOT NULL DEFAULT 0, + `teleportplane_reports` bigint unsigned NOT NULL DEFAULT 0, + `climb_reports` bigint unsigned NOT NULL DEFAULT 0, + `time_maniputation_reports` bigint unsigned NOT NULL DEFAULT 0, + `gravity_reports` bigint unsigned NOT NULL DEFAULT 0, + `teleport_reports` bigint unsigned NOT NULL DEFAULT 0, + `bg_start_reports` bigint unsigned NOT NULL DEFAULT 0, + PRIMARY KEY (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +DROP TABLE `players_reports_status`; +CREATE TABLE IF NOT EXISTS `players_reports_status` ( + `guid` int unsigned NOT NULL DEFAULT 0, + `creation_time` int unsigned NOT NULL DEFAULT 0, + `average` float NOT NULL DEFAULT 0, + `total_reports` bigint unsigned NOT NULL DEFAULT 0, + `speed_reports` bigint unsigned NOT NULL DEFAULT 0, + `fly_reports` bigint unsigned NOT NULL DEFAULT 0, + `jump_reports` bigint unsigned NOT NULL DEFAULT 0, + `waterwalk_reports` bigint unsigned NOT NULL DEFAULT 0, + `teleportplane_reports` bigint unsigned NOT NULL DEFAULT 0, + `climb_reports` bigint unsigned NOT NULL DEFAULT 0, + `time_maniputation_reports` bigint unsigned NOT NULL DEFAULT 0, + `gravity_reports` bigint unsigned NOT NULL DEFAULT 0, + `teleport_reports` bigint unsigned NOT NULL DEFAULT 0, + `bg_start_reports` bigint unsigned NOT NULL DEFAULT 0, + PRIMARY KEY (`guid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + diff --git a/sql/updates/world/2023_11_22_world.sql b/sql/updates/world/2023_11_22_world.sql new file mode 100644 index 00000000000..e142a5c8fe1 --- /dev/null +++ b/sql/updates/world/2023_11_22_world.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `lua_private_functions`; +CREATE TABLE IF NOT EXISTS `lua_private_functions` ( + `function_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, + `enabled` tinyint(4) NOT NULL DEFAULT '1' +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +DELETE FROM `lua_private_functions`; +INSERT INTO `lua_private_functions` (`function_name`, `enabled`) VALUES + ('CastSpellByName', 1), + ('RunMacroText', 1); + +DELETE FROM `skyfire_string` WHERE `entry`=11002; +INSERT INTO `skyfire_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`, `content_loc9`, `content_loc10`, `content_loc11`)VALUES +(11002, '|cFFFFBF00[%s]:|cFFFFFFFF|Hplayer:%s|h[%s]|h|cFF00FFFF potential |r|cFFFFFF00%s|r%s x %u|r', null, null, null, null, null, null, null, null, null, null, null); diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp new file mode 100644 index 00000000000..95d038c8e52 --- /dev/null +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -0,0 +1,1306 @@ +/* +* This file is part of Project SkyFire https://www.projectskyfire.org. +* See LICENSE.md file for Copyright information +*/ + +#include "AnticheatMgr.h" +#include "Battleground.h" +#include "Chat.h" +#include "Language.h" +#include "MapManager.h" +#include "Player.h" +#include "ScriptMgr.h" +#include "SpellAuras.h" +#include "World.h" +#include "WorldSession.h" + +enum Spells +{ + FREEZE = 9454, + LFG_SPELL_DUNGEON_DESERTER = 71041, + BG_SPELL_DESERTER = 26013, + SILENCED = 23207, + RESURRECTION_SICKNESS = 15007, + SLOWDOWN = 61458 +}; + +AnticheatData::AnticheatData() +{ + lastOpcode = 0; + totalReports = 0; + for (uint8 i = 0; i < MAX_REPORT_TYPES; i++) + { + typeReports[i] = 0; + tempReports[i] = 0; + tempReportsTimer[i] = 0; + reportAnnounceCount[i] = 0; + reportAnnounceCooldown[i] = 0; + } + average = 0; + creationTime = 0; + hasDailyReport = false; +} + +float AnticheatData::GetAverage() const +{ + return average; +} + +void AnticheatData::SetAverage(float _average) +{ + average = _average; +} + +uint32 AnticheatData::GetCreationTime() const +{ + return creationTime; +} + +void AnticheatData::SetCreationTime(uint32 _creationTime) +{ + creationTime = _creationTime; +} +void AnticheatData::SetDailyReportState(bool b) +{ + hasDailyReport = b; +} + +bool AnticheatData::GetDailyReportState() +{ + return hasDailyReport; +} + +void AnticheatData::Reset() +{ + totalReports = 0; + average = 0; + creationTime = 0; + for (uint8 i = 0; i < MAX_REPORT_TYPES; i++) + { + tempReports[i] = 0; + tempReportsTimer[i] = 0; + typeReports[i] = 0; + } +} + +void AnticheatData::SetPosition(float x, float y, float z, float o) +{ + lastMovementInfo.pos.m_positionX = x; + lastMovementInfo.pos.m_positionY = y; + lastMovementInfo.pos.m_positionZ = z; + lastMovementInfo.pos.m_orientation = o; +} + +class AnticheatScript : public PlayerScript +{ +public: + AnticheatScript() : PlayerScript("AnticheatScripts") { } + + void OnLogout(Player* player) override + { + sAnticheatMgr->HandlePlayerLogout(player); + } + + void OnLogin(Player* player, bool /*loginFirst*/ ) override + { + sAnticheatMgr->HandlePlayerLogin(player); + } +}; + +void AddSC_Anticheat() +{ + new AnticheatScript(); +} + +AnticheatMgr::AnticheatMgr() +{ +} + +AnticheatMgr::~AnticheatMgr() +{ +} + +void AnticheatMgr::LoadBlockedLuaFunctions() +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_LUABLOCKER_ENABLE)) + { + SF_LOG_INFO("server.loading", ">> Anticheat.LUAblocker conf is set to 0"); + return; + } + uint32 oldmsTime = getMSTime(); + auto pstmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_ANTICHEAT_FUNCTIONS); + auto result = WorldDatabase.Query(pstmt); + if (!result) + { + SF_LOG_INFO("server.loading", ">> Anticheat loaded 0 LUA blocked private functions"); + return; + } + uint32 count = 0; + do + { + auto fields = result->Fetch(); + _luaBlockedFunctions[fields[0].GetString()] = fields[1].GetBool(); + ++count; + } while (result->NextRow()); + + SF_LOG_INFO("server.loading", ">> Anticheat loaded %u LUA blocked private functions in %u ms", count, GetMSTimeDiffToNow(oldmsTime)); +} + +void AnticheatMgr::SaveLuaCheater(uint32 guid, uint32 accountId, std::string macro) +{ + auto pstmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ANTICHEAT_LUA_CHEATERS); + pstmt->setUInt32(0, guid); + pstmt->setUInt32(1, accountId); + pstmt->setString(2, macro); + CharacterDatabase.Execute(pstmt); +} + +bool AnticheatMgr::CheckIsLuaCheater(uint32 accountId) +{ + auto pstmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ANTICHEAT_LUA_CHEATERS); + pstmt->setUInt32(0, accountId); + auto result = CharacterDatabase.Query(pstmt); + if (result) + return true; + + return false; +} + +bool AnticheatMgr::CheckBlockedLuaFunctions(AccountData accountData[uint8(AccountDataType::NUM_ACCOUNT_DATA_TYPES)], Player* player) +{ + for (auto& kv : _luaBlockedFunctions) + { + for (uint8 i = 0; i < uint8(AccountDataType::NUM_ACCOUNT_DATA_TYPES); ++i) + { + std::string currentData = accountData[i].Data; + std::size_t pos = currentData.find(kv.first); + if (pos != std::string::npos) + { + // Code inside this if statement block will only execute if the variable 'pos' is not equal to std::string::npos. + // std::string::npos is a special value indicating the absence of a valid position. + // The following below is all done to capture the macro used and stored it in the SaveLuaCheater + + const static std::size_t defaultLength = 200; + // Declares a constant variable 'defaultLength' with a value of 200. + // This variable represents the default length of a substring to be extracted. + + std::size_t minPos = int64(int(pos) - 50) < 0 ? 0 : pos - 50; + + // Calculates the minimum position from where the substring will be extracted. + // It subtracts 50 from the 'pos' value, casts it to int64, and checks if it's less than 0. + // If it is less than 0, sets 'minPos' to 0, otherwise sets 'minPos' to 'pos - 50'. + // With out the - 50 we will get a crash on certain substrings + + std::size_t length = defaultLength + minPos > currentData.length() - 1 ? currentData.length() - minPos : defaultLength; + // Calculates the length of the substring to be extracted. + // It adds 'defaultLength' to 'minPos' and checks if it's greater than the length of 'currentData' minus 1. + // If it is greater, sets 'length' to 'currentData.length() - minPos', otherwise sets it to 'defaultLength'. + + std::string macro = currentData.substr(minPos, length); + // Extracts a substring from 'currentData' starting at 'minPos' with a length of 'length' and assigns it to the variable 'macro'. + + if (player) + { + // Checks if the 'player' pointer is not null (i.e., it points to a valid object, aka The NULL CHECK). + + SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE::Player %s has inaccessible LUA MACRO, placing on watch list", player->GetName().c_str()); + // Outputs a log message indicating that the player has an inaccessible Lua macro and is being placed on a watch list. + + SaveLuaCheater(player->GetGUID(), player->GetSession()->GetAccountId(), macro); + // Calls the 'SaveLuaCheater' function, passing in the player's GUID, session account ID, and the 'macro' string. + // This function saves information about the Lua cheater, such as the id of the player account, character, and macro used, for further analysis or enforcement actions. + } + + return true; + } + } + } + + return false; +} + +void AnticheatMgr::StartHackDetection(Player* player, MovementInfo& movementInfo, uint32 opcode) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE)) + return; + + if (player->IsGameMaster()) + return; + + AnticheatData* data = GetDataFor(player); + if (!data) + return; + + if (player->IsInFlight() || player->GetTransport() || player->GetVehicle()) + { + data->lastMovementInfo = movementInfo; + data->lastOpcode = opcode; + return; + } + + SpeedHackDetection(player, movementInfo, *data); + FlyHackDetection(player, movementInfo, *data); + TeleportHackDetection(player, movementInfo, *data); + if (movementInfo.HasMovementFlag(MOVEMENTFLAG_WATERWALKING)) + { + WalkOnWaterHackDetection(player, movementInfo, *data); + } + JumpHackDetection(player, movementInfo, *data, opcode); + TeleportPlaneHackDetection(player, movementInfo, *data, opcode); + ClimbHackDetection(player, movementInfo, *data, opcode); + GravityHackDetection(player, movementInfo, *data, opcode); + if (Battleground* bg = player->GetBattleground()) + { + if (bg->GetStatus() == STATUS_WAIT_JOIN) + { + BGStartExploit(player, movementInfo, *data, opcode); + } + } + data->lastMovementInfo = movementInfo; + data->lastOpcode = opcode; +} + +void AnticheatMgr::SpeedHackDetection(Player* player, MovementInfo& movementInfo, AnticheatData& data) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_SPEEDHACK_ENABLE)) + return; + + // We exempt all transports found in 548 to prevent false tele hack hits + if (player->GetMapId()) + { + switch (player->GetMapId()) + { + case 369: //Transport: Deeprun Tram + case 607: //Transport: Strands of the Ancients + case 582: //Transport: Rut'theran to Auberdine + case 584: //Transport: Menethil to Theramore + case 586: //Transport: Exodar to Auberdine + case 587: //Transport: Feathermoon Ferry + case 588: //Transport: Menethil to Auberdine + case 589: //Transport: Orgrimmar to Grom'Gol + case 590: //Transport: Grom'Gol to Undercity + case 591: //Transport: Undercity to Orgrimmar + case 592: //Transport: Borean Tundra Test + case 593: //Transport: Booty Bay to Ratchet + case 594: //Transport: Howling Fjord Sister Mercy (Quest) + case 596: //Transport: Naglfar + case 610: //Transport: Tirisfal to Vengeance Landing + case 612: //Transport: Menethil to Valgarde + case 613: //Transport: Orgrimmar to Warsong Hold + case 614: //Transport: Stormwind to Valiance Keep + case 620: //Transport: Moa'ki to Unu'pe + case 621: //Transport: Moa'ki to Kamagua + case 622: //Transport: Orgrim's Hammer + case 623: //Transport: The Skybreaker + case 641: //Transport: Alliance Airship BG + case 642: //Transport: Horde Airship BG + case 647: //Transport: Orgrimmar to Thunder Bluff + case 672: //Transport: The Skybreaker (Icecrown Citadel Raid) + case 673: //Transport: Orgrim's Hammer (Icecrown Citadel Raid) + case 712: //Transport: The Skybreaker (IC Dungeon) + case 713: //Transport: Orgrim's Hammer (IC Dungeon) + case 718: //Transport: The Mighty Wind (Icecrown Citadel Raid) + case 766: // Transport 2033864 + case 767: // Transport 2033865 + case 747: // Transport 203732 + case 762: // Transport 203861 + case 763: // Transport 203862 + case 1172: // Transport_Siege_of_Orgrimmar_Alliance + case 1173: // Transport_Siege_of_Orgrimmar_Horde + case 662: // Transport197195 + case 674: // Transport197349-2 + case 738: // Transport200100 + case 739: // Transport200101 + case 740: // Transport200102 + case 741: // Transport200103 + case 742: // Transport203729 + case 743: // Transport203730 + case 748: // Transport203858 + case 749: // Transport203859 + case 750: // Transport203860 + case 765: // Transport203863 + case 1132: // Transport218599 + case 1133: // Transport218600 + return; + } + } + if (player->HasAura(1850) /*Dash*/ || player->HasAuraType(SPELL_AURA_FEATHER_FALL) || player->HasAuraType(SPELL_AURA_SAFE_FALL)) + { + return; + } + + if (player->IsInWater() && player->HasAura(57856) /*Glyph of Aquatic Form*/) + { + return; + } + + float distance2D = movementInfo.pos.GetExactDist2d(&data.lastMovementInfo.pos); + uint8 moveType = 0; + + // we need to know HOW is the player moving + // TO-DO: Should we check the incoming movement flags? + if (player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING)) + moveType = MOVE_SWIM; + else if (player->IsFlying()) + moveType = MOVE_FLIGHT; + else if (player->HasUnitMovementFlag(MOVEMENTFLAG_WALKING)) + moveType = MOVE_WALK; + else + moveType = MOVE_RUN; + + // how many yards the player can do in one sec. + float speedRate = player->GetSpeed(UnitMoveType(moveType)) + movementInfo.jump.xyspeed; + + // how long the player took to move to here. + uint32 timeDiff = getMSTimeDiff(data.lastMovementInfo.time, movementInfo.time); + + if (int32(timeDiff) < 0) + { + uint32 latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Time Manipulation- Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress(), goXYZ.c_str()); + BuildReport(player, data, TIME_MANIPULATION_REPORT); + timeDiff = 1; + } + + if (!timeDiff) + timeDiff = 1; + + // this is the distance doable by the player in 1 sec, using the time done to move to this point. + float clientSpeedRate = distance2D * 1000 / timeDiff; + + // we create a diff speed in uint32 for further precision checking to avoid legit fall and slide + uint32 diffspeed = clientSpeedRate - speedRate; + + // create a conf to establish a speed limit tolerance over server rate set speed + // this is done so we can ignore minor violations that are not false positives such as going 1 or 2 over the speed limit + uint32 _assignedspeeddiff = sWorld->getIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_SPEED_LIMIT_TOLERANCE); + + // We did the (uint32) cast to accept a margin of tolerance for seasonal spells and buffs such as sugar rush + // We check the last MovementInfo for the falling flag since falling down a hill and sliding a bit triggered a false positive + if (!movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING)) + { + if (diffspeed >= _assignedspeeddiff) + { + // we did the (uint32) cast to accept a margin of tolerance + if (clientSpeedRate >= _assignedspeeddiff + speedRate) + { + uint32 _combined = _assignedspeeddiff + speedRate; + BuildReport(player, data, SPEED_HACK_REPORT); + uint32 latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Speed - Hack detected player %s - (GUID %u) - (Speed Movement at %u above allowed Server Set rate %u.)- Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), diffspeed, _combined, latency, player->GetSession()->GetRemoteAddress(), goXYZ.c_str()); + if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_SPEEDHACK)) + { + SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE:: %s SPEED HACK REVERTED", player->GetName().c_str()); + if (Aura* slowcheater = player->AddAura(SLOWDOWN, player))// SLOWDOWN + { + slowcheater->SetDuration(1000); + } + } + } + } + } +} + +void AnticheatMgr::FlyHackDetection(Player* player, MovementInfo& movementInfo, AnticheatData& data) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_FLYHACK_ENABLE)) + return; + + if (!data.lastMovementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING)) + return; + + if (player->HasAuraType(SPELL_AURA_FLY) || + player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || + player->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)) + return; + + /*Thanks to @LilleCarl for info to check extra flag*/ + bool stricterChecks = true; + stricterChecks = !(movementInfo.HasMovementFlag(MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING) && !player->IsInWater()); + + if (!movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY) && !movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING) && stricterChecks) + { + return; + } + + uint32 latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Fly - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, FLY_HACK_REPORT); + + if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_FLYHACK)) + { + SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE:: %s FLY HACK REVERTED", player->GetName().c_str()); + // Drop them with a op code set if they use a exploit or hack app + WorldPacket cheater(SMSG_MOVE_UNSET_CAN_FLY, 8 + 4); + cheater.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + + player->WriteMovementInfo(cheater); + player->SendMessageToSet(&cheater, true); + } +} + +void AnticheatMgr::TeleportHackDetection(Player* player, MovementInfo movementInfo, AnticheatData& data) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_TELEPORTHACK_ENABLE)) + return; + + float lastX = data.lastMovementInfo.pos.GetPositionX(); + float newX = movementInfo.pos.GetPositionX(); + + float lastY = data.lastMovementInfo.pos.GetPositionY(); + float newY = movementInfo.pos.GetPositionY(); + + float lastZ = data.lastMovementInfo.pos.GetPositionZ(); + float newZ = movementInfo.pos.GetPositionZ(); + + float xDiff = fabs(lastX - newX); + float yDiff = fabs(lastY - newY); + + if (player->IsFalling() || (player->IsFalling() && player->IsMounted())) + return; + + // We exempt all transports found in 548 to prevent false tele hack hits + if (player->GetMapId()) + { + switch (player->GetMapId()) + { + case 369: //Transport: Deeprun Tram + case 607: //Transport: Strands of the Ancients + case 582: //Transport: Rut'theran to Auberdine + case 584: //Transport: Menethil to Theramore + case 586: //Transport: Exodar to Auberdine + case 587: //Transport: Feathermoon Ferry + case 588: //Transport: Menethil to Auberdine + case 589: //Transport: Orgrimmar to Grom'Gol + case 590: //Transport: Grom'Gol to Undercity + case 591: //Transport: Undercity to Orgrimmar + case 592: //Transport: Borean Tundra Test + case 593: //Transport: Booty Bay to Ratchet + case 594: //Transport: Howling Fjord Sister Mercy (Quest) + case 596: //Transport: Naglfar + case 610: //Transport: Tirisfal to Vengeance Landing + case 612: //Transport: Menethil to Valgarde + case 613: //Transport: Orgrimmar to Warsong Hold + case 614: //Transport: Stormwind to Valiance Keep + case 620: //Transport: Moa'ki to Unu'pe + case 621: //Transport: Moa'ki to Kamagua + case 622: //Transport: Orgrim's Hammer + case 623: //Transport: The Skybreaker + case 641: //Transport: Alliance Airship BG + case 642: //Transport: Horde Airship BG + case 647: //Transport: Orgrimmar to Thunder Bluff + case 672: //Transport: The Skybreaker (Icecrown Citadel Raid) + case 673: //Transport: Orgrim's Hammer (Icecrown Citadel Raid) + case 712: //Transport: The Skybreaker (IC Dungeon) + case 713: //Transport: Orgrim's Hammer (IC Dungeon) + case 718: //Transport: The Mighty Wind (Icecrown Citadel Raid) + case 766: // Transport 2033864 + case 767: // Transport 2033865 + case 747: // Transport 203732 + case 762: // Transport 203861 + case 763: // Transport 203862 + case 1172: // Transport_Siege_of_Orgrimmar_Alliance + case 1173: // Transport_Siege_of_Orgrimmar_Horde + case 662: // Transport197195 + case 674: // Transport197349-2 + case 738: // Transport200100 + case 739: // Transport200101 + case 740: // Transport200102 + case 741: // Transport200103 + case 742: // Transport203729 + case 743: // Transport203730 + case 748: // Transport203858 + case 749: // Transport203859 + case 750: // Transport203860 + case 765: // Transport203863 + case 1132: // Transport218599 + case 1133: // Transport218600 + return; + } + } + + /* Please work */ + if ((xDiff >= 50.0f || yDiff >= 50.0f) && !player->CanTeleport() && !player->IsBeingTeleported())// teleport helpers in play + { + uint32 latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Teleport - Hack detected player %s - (GUID %u) - X-Diff: %f - Y-Diff: %f - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), xDiff, yDiff, latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, TELEPORT_HACK_REPORT); + if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_TELEPORT)) + { + player->TeleportTo(player->GetMapId(), lastX, lastY, lastZ, player->GetOrientation()); + SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE:: %s TELEPORT HACK REVERTED PLAYER BACK", player->GetName().c_str()); + } + } + else if (player->CanTeleport())// if we hit the teleport helpers in the source then we return it to false + player->SetCanTeleport(false); +} + +void AnticheatMgr::WalkOnWaterHackDetection(Player* player, MovementInfo& movementInfo, AnticheatData& data) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_WATERWALKHACK_ENABLE)) + return; + + if (!data.lastMovementInfo.HasMovementFlag(MOVEMENTFLAG_WATERWALKING)) + return; + + if (player->IsFlying()) + return; + + // ghost can water walk + if (player->HasAuraType(SPELL_AURA_GHOST)) + return; + + // if we are a ghost we can walk on water + if (!player->IsAlive()) + return; + + // if the player previous movement and current movement is water walking then we do a follow up check + if (data.lastMovementInfo.HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && movementInfo.HasMovementFlag(MOVEMENTFLAG_WATERWALKING)) + { // if player has the following auras then we return + if (player->HasAuraType(SPELL_AURA_WATER_WALK) || player->HasAuraType(SPELL_AURA_FEATHER_FALL) || + player->HasAuraType(SPELL_AURA_SAFE_FALL)) + { + return; + } + } + else if (!data.lastMovementInfo.HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !movementInfo.HasMovementFlag(MOVEMENTFLAG_WATERWALKING)) + { + //Boomer Review Time: + //Return stops code execution of the entire function + return; + } + + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Walk on Water - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, WALK_WATER_HACK_REPORT); + if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_WATERHACK)) + { + SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE:: %s WATER WALKING HACK REVERTED", player->GetName().c_str()); + player->GetMotionMaster()->MoveFallPlayer(); + } +} + +void AnticheatMgr::JumpHackDetection(Player* player, MovementInfo& movementInfo, AnticheatData& data, uint32 opcode) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_JUMPHACK_ENABLE)) + return; + + const float ground_Z = movementInfo.pos.GetPositionZ() - player->GetMap()->GetHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()); + + const bool no_fly_auras = !(player->HasAuraType(SPELL_AURA_FLY) || player->HasAuraType(SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED) + || player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || player->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) + || player->HasAuraType(SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS)); + const bool no_fly_flags = ((movementInfo.flags & (MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING)) == 0); + const bool no_swim_in_water = !player->IsInWater(); + const bool no_swim_above_water = movementInfo.pos.GetPositionZ() - 7.0f >= player->GetMap()->GetWaterLevel(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY()); + const bool no_swim_water = no_swim_in_water && no_swim_above_water; + + if (data.lastOpcode == MSG_MOVE_JUMP && opcode == MSG_MOVE_JUMP) + { + BuildReport(player, data, JUMP_HACK_REPORT); + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Jump-Hack detected player %s - Latency: %u ms - IP: %u - Cheat Flagged at: %s", player->GetName().c_str(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_JUMPHACK)) + { + SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE:: %s JUMP HACK REVERTED", player->GetName().c_str()); + player->GetMotionMaster()->MoveFallPlayer(); + } + } + else if (no_fly_auras && no_fly_flags && no_swim_water) + { + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ADV_JUMPHACK_ENABLE)) + return; + + if (data.lastOpcode == MSG_MOVE_JUMP && !player->IsFalling()) + return; + + float distance2D = movementInfo.pos.GetExactDist2d(&data.lastMovementInfo.pos); + + // This is necessary since MovementHandler fires if you rotate the camera in place + if (!distance2D) + return; + + if (!player->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY) && movementInfo.jump.zspeed < -10.0f) + return; + + if (player->HasAuraType(SPELL_AURA_WATER_WALK) || player->HasAuraType(SPELL_AURA_FEATHER_FALL) || + player->HasAuraType(SPELL_AURA_SAFE_FALL)) + { + return; + } + + // We exempt select areas found in 335 to prevent false hack hits + if (player->GetAreaId()) + { + switch (player->GetAreaId()) + { + case 4273: //Celestial Planetarium Observer Battle has a narrow path that false flags + case 6724: //Backbreaker Bay + case 6725: //Greymist Firth + return; + } + } + + if (ground_Z > 5.0f && movementInfo.pos.GetPositionZ() >= player->GetPositionZ()) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Advanced Jump-Hack detected player %s - Latency: %u ms - IP: %u - Cheat Flagged at: %s", player->GetName().c_str(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, JUMP_HACK_REPORT); + if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_ADVJUMPHACK)) + { + SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE:: %s ADVANCE JUMP HACK REVERTED", player->GetName().c_str()); + player->GetMotionMaster()->MoveFallPlayer(); + } + } + } +} + +void AnticheatMgr::TeleportPlaneHackDetection(Player* player, MovementInfo& movementInfo, AnticheatData& data, uint32 opcode) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_TELEPANEHACK_ENABLE)) + return; + + + if (player->HasAuraType(SPELL_AURA_WATER_WALK) || player->HasAuraType(SPELL_AURA_WATER_BREATHING) || player->HasAuraType(SPELL_AURA_GHOST)) + return; + + ZLiquidStatus result = LIQUID_MAP_ABOVE_WATER; + float distance2D = movementInfo.pos.GetExactDist2d(&data.lastMovementInfo.pos); + + // We don't need to check for a water walking hack if the player hasn't moved + // This is necessary since MovementHandler fires if you rotate the camera in place + if (!distance2D) + return; + + if (data.lastOpcode == MSG_MOVE_JUMP) + return; + + if (opcode == MSG_MOVE_FALL_LAND) + return; + + if (player && result == LIQUID_MAP_ABOVE_WATER) + return; + + if (movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_SWIMMING)) + return; + + // If he is flying we dont need to check + if (movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING)) + return; + + // We exempt select areas found in 335 to prevent false hack hits + if (player->GetAreaId()) + { + switch (player->GetAreaId()) + { + case 4273: //Celestial Planetarium Observer Battle has a narrow path that false flags + return; + } + } + + float pos_z = player->GetPositionZ(); + float groundZ = player->GetMap()->GetHeight(player->GetPositionX(), player->GetPositionY(), MAX_HEIGHT); + float floorZ = player->GetMap()->GetHeight(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); + + // we are not really walking there + if (groundZ == floorZ && (fabs(groundZ - pos_z) > 2.0f || fabs(groundZ - pos_z) < -1.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Teleport To Plane - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, TELEPORT_PLANE_HACK_REPORT); + } +} + +// basic detection +void AnticheatMgr::ClimbHackDetection(Player *player, MovementInfo &movementInfo, AnticheatData& data, uint32 opcode) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CLIMBHACK_ENABLE)) + return; + + // in this case we don't care if they are "legal" flags, they are handled in another parts of the Anticheat Manager. + if (player->IsInWater() || + player->IsFlying() || + player->IsFalling()) + return; + + // If the player jumped, we dont want to check for climb hack + // This can lead to false positives for climbing game objects legit + if (opcode == MSG_MOVE_JUMP) + return; + + if (player->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)) + return; + + Position playerPos; + player->GetPosition(&playerPos); + + float deltaZ = fabs(playerPos.GetPositionZ() - movementInfo.pos.GetPositionZ()); + float deltaXY = movementInfo.pos.GetExactDist2d(&playerPos); + + float tanangle = movementInfo.pos.GetExactDist2d(&playerPos) / deltaZ; + + if (!player->HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_SWIMMING)) + { + if (movementInfo.pos.GetPositionZ() > playerPos.GetPositionZ() && + deltaZ > 1.87f && tanangle < 0.57735026919f) // 30 degrees + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Climb - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, CLIMB_HACK_REPORT); + } + } +} + +void AnticheatMgr::GravityHackDetection(Player* player, MovementInfo& movementInfo, AnticheatData& data, uint32 opcode) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_GRAVITY_ENABLE)) + return; + + if (player->HasAuraType(SPELL_AURA_FEATHER_FALL)) + { + return; + } + + if (data.lastOpcode == MSG_MOVE_JUMP) + { + if (!player->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY) && movementInfo.jump.zspeed < -10.0f) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: Gravity - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, GRAVITY_HACK_REPORT); + } + } +} + +void AnticheatMgr::BGStartExploit(Player* player, MovementInfo movementInfo, AnticheatData& data, uint32 opcode) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_BG_START_HACK_ENABLE)) + return; + + switch (player->GetMapId()) + { + case 30: // Alterac Valley + { + if (Battleground* bg = player->GetBattleground()) + { + if (bg->GetStatus() == STATUS_WAIT_JOIN) + { + // Outside of starting area before BG has started. + if ((player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionX() < 770.0f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionX() > 940.31f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < -525.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + if ((player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > -535.0f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() > -1283.33f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() < -716.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + } + } + break; + } + case 489: // Warsong Gulch + { + // Only way to get this high is with engineering items malfunction. + if (!(movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING_FAR) || data.lastOpcode == MSG_MOVE_JUMP) && movementInfo.pos.GetPositionZ() > 380.0f) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + + if (Battleground* bg = player->GetBattleground()) + { + if (bg->GetStatus() == STATUS_WAIT_JOIN) + { + // Outside of starting area before BG has started. + if ((player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionX() < 1490.0f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() > 1500.0f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < 1450.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + if ((player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() > 957.0f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() < 1416.0f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > 1466.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + } + } + break; + } + case 529: // Arathi Basin + { + if (Battleground* bg = player->GetBattleground()) + { + if (bg->GetStatus() == STATUS_WAIT_JOIN) + { + // Outside of starting area before BG has started. + if ((player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionX() < 1270.0f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < 1258.0f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() > 1361.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + if ((player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() > 730.0f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > 724.8f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + } + } + break; + } + case 566: // Eye of the Storm + { + if (Battleground* bg = player->GetBattleground()) + { + if (bg->GetStatus() == STATUS_WAIT_JOIN) + { + // Outside of starting area before BG has started. + if ((player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionX() < 2512.0f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() > 1610.0f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < 1584.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + if ((player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() > 1816.0f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > 1554.0f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() < 1526.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + } + } + break; + } + case 628: // Island Of Conquest + { + if (Battleground* bg = player->GetBattleground()) + { + if (bg->GetStatus() == STATUS_WAIT_JOIN) + { + // Outside of starting area before BG has started. + if ((player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionX() > 412.0f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < -911.0f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() > -760.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + if ((player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() < 1147.8f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() < -855.0f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > -676.0f)) + { + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); + } + } + } + break; + } + return; + } +} + +void AnticheatMgr::SetAllowedMovement(Player* player, bool) +{ + player->SetCanTeleport(true); +} + +void AnticheatMgr::HandlePlayerLogin(Player* player) +{ + // we must delete this to prevent errors in case of crash + CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u",player->GetGUIDLow()); + // we initialize the pos of lastMovementPosition var. + _players[player->GetGUIDLow()].SetPosition(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation()); + QueryResult resultDB = CharacterDatabase.PQuery("SELECT * FROM daily_players_reports WHERE guid=%u;",player->GetGUIDLow()); + + if (resultDB) + _players[player->GetGUIDLow()].SetDailyReportState(true); +} + +void AnticheatMgr::HandlePlayerLogout(Player* player) +{ + // TO-DO Make a table that stores the cheaters of the day, with more detailed information. + + // We must also delete it at logout to prevent have data of offline players in the db when we query the database (IE: The GM Command) + CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u",player->GetGUIDLow()); + // Delete not needed data from the memory. + _players.erase(player->GetGUIDLow()); +} + +void AnticheatMgr::SavePlayerData(Player* player) +{ + CharacterDatabase.PExecute("REPLACE INTO players_reports_status (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,time_maniputation_reports, gravity_reports, teleport_reports, bg_start_reports, creation_time) VALUES (%u,%f,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u);",player->GetGUIDLow(),_players[player->GetGUIDLow()].GetAverage(),_players[player->GetGUIDLow()].GetTotalReports(), _players[player->GetGUIDLow()].GetTypeReports(SPEED_HACK_REPORT),_players[player->GetGUIDLow()].GetTypeReports(FLY_HACK_REPORT),_players[player->GetGUIDLow()].GetTypeReports(JUMP_HACK_REPORT),_players[player->GetGUIDLow()].GetTypeReports(WALK_WATER_HACK_REPORT),_players[player->GetGUIDLow()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT),_players[player->GetGUIDLow()].GetTypeReports(CLIMB_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(TIME_MANIPULATION_REPORT), _players[player->GetGUIDLow()].GetTypeReports(GRAVITY_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(TELEPORT_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(BG_START_HACK_REPORT), _players[player->GetGUIDLow()].GetCreationTime()); +} + +void AnticheatMgr::SavePlayerDataDaily(Player* player) +{ + CharacterDatabase.PExecute("REPLACE INTO players_reports_status (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,time_maniputation_reports, gravity_reports, teleport_reports, bg_start_reports, creation_time) VALUES (%u,%f,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u);", player->GetGUIDLow(), _players[player->GetGUIDLow()].GetAverage(), _players[player->GetGUIDLow()].GetTotalReports(), _players[player->GetGUIDLow()].GetTypeReports(SPEED_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(FLY_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(JUMP_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(WALK_WATER_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(CLIMB_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(TIME_MANIPULATION_REPORT), _players[player->GetGUIDLow()].GetTypeReports(GRAVITY_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(TELEPORT_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(BG_START_HACK_REPORT), _players[player->GetGUIDLow()].GetCreationTime()); +} + +void AnticheatMgr::OnPlayerMove(Player* player, MovementInfo &mi, uint32 opcode) +{ + if (!AccountMgr::IsAdminAccount(player->GetSession()->GetSecurity()) || sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE_ON_GM)) + sAnticheatMgr->StartHackDetection(player, mi, opcode); +} + +uint32 AnticheatMgr::GetTotalReports(uint32 lowGUID) +{ + AnticheatPlayersDataMap::iterator iter = _players.find(lowGUID); + if (iter == _players.end()) + return 0; + + return iter->second.totalReports; +} + +float AnticheatMgr::GetAverage(uint32 lowGUID) +{ + AnticheatPlayersDataMap::iterator iter = _players.find(lowGUID); + if (iter == _players.end()) + return 0.0f; + + return iter->second.average; +} + +uint32 AnticheatMgr::GetTypeReports(uint32 lowGUID, uint8 type) +{ + AnticheatPlayersDataMap::iterator iter = _players.find(lowGUID); + if (iter == _players.end()) + return 0; + + return iter->second.typeReports[type]; +} + +bool AnticheatMgr::MustCheckTempReports(uint8 type) +{ + if (type == JUMP_HACK_REPORT) + return false; + + if (type == GRAVITY_HACK_REPORT) + return false; + + if (type == TELEPORT_HACK_REPORT) + return false; + + if (type == BG_START_HACK_REPORT) + return false; + + return true; +} + +void AnticheatMgr::BuildReport(Player* player, AnticheatData& data, uint8 reportType) +{ + uint32 key = player->GetGUIDLow(); + + if (MustCheckTempReports(reportType)) + { + uint32 actualTime = getMSTime(); + + if (!data.tempReportsTimer[reportType]) + data.tempReportsTimer[reportType] = actualTime; + + if (getMSTimeDiff(data.tempReportsTimer[reportType], actualTime) < 3000) + { + data.tempReports[reportType] += 1; + + if (data.tempReports[reportType] < 3) + return; + } + else + { + data.tempReportsTimer[reportType] = actualTime; + data.tempReports[reportType] = 1; + return; + } + } + + // generating creationTime for average calculation + if (!data.totalReports) + data.creationTime = getMSTime(); + + // increasing total_reports + data.totalReports += 1; + // increasing specific cheat report + data.typeReports[reportType] += 1; + + // diff time for average calculation + uint32 diffTime = getMSTimeDiff(data.creationTime, getMSTime()) / IN_MILLISECONDS; + + if (diffTime > 0) + { + // Average == Reports per second + float average = float(data.totalReports) / float(diffTime); + data.average = average; + } + + if (sWorld->getIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_DAILY_REPORT) < data.GetTotalReports()) + { + if (!data.GetDailyReportState()) + { + CharacterDatabase.PExecute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,time_maniputation_reports, gravity_reports, teleport_reports, bg_start_reports, creation_time) VALUES (%u,%f,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u);", player->GetGUIDLow(), _players[player->GetGUIDLow()].GetAverage(), _players[player->GetGUIDLow()].GetTotalReports(), _players[player->GetGUIDLow()].GetTypeReports(SPEED_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(FLY_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(JUMP_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(WALK_WATER_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(CLIMB_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(TIME_MANIPULATION_REPORT), _players[player->GetGUIDLow()].GetTypeReports(GRAVITY_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(TELEPORT_HACK_REPORT), _players[player->GetGUIDLow()].GetTypeReports(BG_START_HACK_REPORT), _players[player->GetGUIDLow()].GetCreationTime()); + data.SetDailyReportState(true); + } + } + + // Send warning to ingame GMs + if (data.totalReports > sWorld->getIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_REPORTS_INGAME_NOTIFICATION)) + { + uint32& count = data.reportAnnounceCount[reportType]; + ++count; + time_t now = time(NULL); + if (data.reportAnnounceCooldown[reportType] < now) + data.reportAnnounceCooldown[reportType] = now + 3; + else + return; + + const char* reportTypeName; + switch (reportType) + { + case SPEED_HACK_REPORT: reportTypeName = "SpeedHack"; break; + case FLY_HACK_REPORT: reportTypeName = "FlyHack"; break; + case WALK_WATER_HACK_REPORT: reportTypeName = "WaterWalkHack"; break; + case JUMP_HACK_REPORT: reportTypeName = "JumpHack"; break; + case TELEPORT_PLANE_HACK_REPORT: reportTypeName = "TeleportPlaneHack"; break; + case CLIMB_HACK_REPORT: reportTypeName = "ClimbHack"; break; + case TIME_MANIPULATION_REPORT: reportTypeName = "TimeManipulation"; break; + case GRAVITY_HACK_REPORT: reportTypeName = "GravityHack"; break; + case TELEPORT_HACK_REPORT: reportTypeName = "TeleportHack"; break; + case BG_START_HACK_REPORT: reportTypeName = "BGStartHack"; break; + default: reportTypeName = "?"; break; + } + SF_LOG_DEBUG("network", "Anticheat Alert: %s detected as possible cheater. HackType: %u.", player->GetName().c_str(), reportType); + sWorld->SendGMText(LANG_CHEATER_CHATLOG, "Anticheat Alert", player->GetName().c_str(), player->GetName().c_str(), reportTypeName, count < 10 ? "|cFF00FF00" : count < 20 ? "|cFFFF8000" : "|cFFFF0000", count); + count = 0; + } + // Automatic Moderation, not recommended but not hated + // Auto Kick + if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_AUTOKICK_ENABLE)) + { + if (data.totalReports > sWorld->getIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_KICKS)) + { + SF_LOG_INFO("anticheat", "AnticheatMgr:: Reports reached assigned threshhold and counteracted by kicking player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); + // kick offender when reports are reached for automatic moderation + player->GetSession()->KickPlayer(); + } + } + // Auto Ban + if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_AUTOBAN_ENABLE)) + { + if (data.totalReports > sWorld->getIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_BANS)) + { + SF_LOG_INFO("anticheat", "AnticheatMgr:: Reports reached assigned threshhold and counteracted by banning player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); + //Auto Ban the Offender Indefinately their whole account. + std::string accountName; + AccountMgr::GetName(player->GetSession()->GetAccountId(), accountName); + sWorld->BanAccount(BAN_ACCOUNT, accountName, "0s", "Anticheat module Auto Banned Account for Reach Cheat Threshhold", "Server"); + } + } + //Auto Jail + if (sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_AUTOJAIL_ENABLE)) + { + if (data.totalReports > sWorld->getIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_JAILS)) + { + SF_LOG_INFO("anticheat", "AnticheatMgr:: Reports reached assigned threshhold and counteracted by jailing player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); + // This is where they end up going shaw shank redemption style + WorldLocation loc = WorldLocation(1, 16226.5f, 16403.6f, -64.5f, 3.2f);// GM Jail Location + player->TeleportTo(loc);// we defined loc as the jail location so we tele them there + player->SetHomebind(loc, 876);// GM Jail Homebind location + player->CastSpell(player, FREEZE);// freeze him in place to ensure no exploit happens for jail break attempt + + if (Aura* dungdesert = player->AddAura(LFG_SPELL_DUNGEON_DESERTER,player))// LFG_SPELL_DUNGEON_DESERTER + { + dungdesert->SetDuration(-1); + } + if (Aura* bgdesert = player->AddAura(BG_SPELL_DESERTER, player))// BG_SPELL_DESERTER + { + bgdesert->SetDuration(-1); + } + if (Aura* silent = player->AddAura(SILENCED, player))// SILENCED + { + silent->SetDuration(-1); + } + } + } +} + +void AnticheatMgr::AnticheatGlobalCommand(ChatHandler* handler) +{ + // MySQL will sort all for us, anyway this is not the best way we must only save the anticheat data not whole player's data!. + for (SessionMap::const_iterator itr = sWorld->GetAllSessions().begin(); itr != sWorld->GetAllSessions().end(); ++itr) + if (Player* plr = itr->second->GetPlayer()) + { + sAnticheatMgr->SavePlayerData(plr); + sAnticheatMgr->SavePlayerDataDaily(plr); + } + + QueryResult resultDB = CharacterDatabase.Query("SELECT guid,average,total_reports FROM players_reports_status WHERE total_reports != 0 ORDER BY average ASC LIMIT 3;"); + if (!resultDB) + { + handler->PSendSysMessage("No players found."); + return; + } + else + { + handler->SendSysMessage("============================="); + handler->PSendSysMessage("Players with the lowest averages:"); + do + { + Field *fieldsDB = resultDB->Fetch(); + + uint32 guid = fieldsDB[0].GetUInt32(); + float average = fieldsDB[1].GetFloat(); + uint32 total_reports = fieldsDB[2].GetUInt32(); + + if (Player* player = sObjectMgr->GetPlayerByLowGUID(guid)) + handler->PSendSysMessage("Player: %s Average: %f Total Reports: %u", player->GetName().c_str(),average,total_reports); + } while (resultDB->NextRow()); + } + + resultDB = CharacterDatabase.Query("SELECT guid,average,total_reports FROM players_reports_status WHERE total_reports != 0 ORDER BY total_reports DESC LIMIT 3;"); + // this should never happen + if (!resultDB) + { + handler->PSendSysMessage("No players found."); + return; + } + else + { + handler->SendSysMessage("============================="); + handler->PSendSysMessage("Players with the more reports:"); + do + { + Field *fieldsDB = resultDB->Fetch(); + + uint32 guid = fieldsDB[0].GetUInt32(); + float average = fieldsDB[1].GetFloat(); + uint32 total_reports = fieldsDB[2].GetUInt32(); + + if (Player* player = sObjectMgr->GetPlayerByLowGUID(guid)) + handler->PSendSysMessage("Player: %s Total Reports: %u Average: %f", player->GetName().c_str(),total_reports,average); + } while (resultDB->NextRow()); + } +} + +void AnticheatMgr::AnticheatDeleteCommand(uint32 guid) +{ + if (!guid) + { + for (AnticheatPlayersDataMap::iterator it = _players.begin(); it != _players.end(); ++it) + (*it).second.Reset(); + + CharacterDatabase.PExecute("DELETE FROM players_reports_status;"); + } + else + { + AnticheatPlayersDataMap::iterator iter = _players.find(guid); + if (iter == _players.end()) + return; + + iter->second.Reset(); + CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u;", guid); + } +} + +void AnticheatMgr::AnticheatPurgeCommand(ChatHandler* /*handler*/) +{ + CharacterDatabase.Execute("TRUNCATE TABLE daily_players_reports;"); +} + +void AnticheatMgr::ResetDailyReportStates() +{ + for (AnticheatPlayersDataMap::iterator it = _players.begin(); it != _players.end(); ++it) + it->second.hasDailyReport = false; +} + +uint32 AnticheatData::GetTotalReports() const +{ + return totalReports; +} + +void AnticheatData::SetTotalReports(uint32 _totalReports) +{ + totalReports = _totalReports; +} + +void AnticheatData::SetTypeReports(uint32 type, uint32 amount) +{ + typeReports[type] = amount; +} + +uint32 AnticheatData::GetTypeReports(uint32 type) const +{ + return typeReports[type]; +} + +AnticheatData* AnticheatMgr::GetDataFor(Player* player) +{ + AnticheatPlayersDataMap::iterator iter = _players.find(player->GetGUIDLow()); + if (iter == _players.end()) + { + return NULL; + } + + return &iter->second; +} diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h new file mode 100644 index 00000000000..6550ca92b74 --- /dev/null +++ b/src/server/game/Anticheat/AnticheatMgr.h @@ -0,0 +1,123 @@ +/* +* This file is part of Project SkyFire https://www.projectskyfire.org. +* See LICENSE.md file for Copyright information +*/ + +#ifndef SC_ACMGR_H +#define SC_ACMGR_H + +#include "Common.h" +#include "SharedDefines.h" +#include +#include "WorldSession.h" + +class Player; +class ChatHandler; + +enum ReportTypes +{ + SPEED_HACK_REPORT = 0, + FLY_HACK_REPORT = 1, + WALK_WATER_HACK_REPORT = 2, + JUMP_HACK_REPORT = 3, + TELEPORT_PLANE_HACK_REPORT = 4, + CLIMB_HACK_REPORT = 5, + TIME_MANIPULATION_REPORT = 6, + GRAVITY_HACK_REPORT = 7, + TELEPORT_HACK_REPORT = 8, + BG_START_HACK_REPORT = 9, + MAX_REPORT_TYPES +}; + +struct AnticheatData +{ + AnticheatData(); + + void SetPosition(float x, float y, float z, float o); + void Reset(); + + uint32 lastOpcode; + MovementInfo lastMovementInfo; + uint32 totalReports; + float average; + uint32 creationTime; + bool hasDailyReport; + + uint32 GetTotalReports() const; + void SetTotalReports(uint32 _totalReports); + + uint32 GetTypeReports(uint32 type) const; + void SetTypeReports(uint32 type, uint32 amount); + + float GetAverage() const; + void SetAverage(float _average); + + uint32 GetCreationTime() const; + void SetCreationTime(uint32 creationTime); + + uint32 typeReports[MAX_REPORT_TYPES]; + uint32 tempReports[MAX_REPORT_TYPES]; + uint32 tempReportsTimer[MAX_REPORT_TYPES]; + + uint32 reportAnnounceCount[MAX_REPORT_TYPES]; + time_t reportAnnounceCooldown[MAX_REPORT_TYPES]; + void SetDailyReportState(bool b); + bool GetDailyReportState(); +}; + +// GUIDLow is the key. +typedef std::unordered_map AnticheatPlayersDataMap; + +class AnticheatMgr +{ + AnticheatMgr(); + ~AnticheatMgr(); + + public: + static AnticheatMgr *instance() + { + static AnticheatMgr _instance; + return &_instance; + } + void SetAllowedMovement(Player* player, bool); + void StartHackDetection(Player* player, MovementInfo &movementInfo, uint32 opcode); + void SavePlayerData(Player* player); + void SavePlayerDataDaily(Player* player); + void HandlePlayerLogin(Player* player); + void HandlePlayerLogout(Player* player); + + void OnPlayerMove(Player* player, MovementInfo &mi, uint32 opcode); + uint32 GetTotalReports(uint32 lowGUID); + float GetAverage(uint32 lowGUID); + uint32 GetTypeReports(uint32 lowGUID, uint8 type); + AnticheatData* GetDataFor(Player* player); + + void AnticheatGlobalCommand(ChatHandler* handler); + void AnticheatDeleteCommand(uint32 guid); + void AnticheatPurgeCommand(ChatHandler* handler); + void ResetDailyReportStates(); + void LoadBlockedLuaFunctions(); + void SaveLuaCheater(uint32 guid, uint32 accountId, std::string macro); + bool CheckIsLuaCheater(uint32 accountId); + bool CheckBlockedLuaFunctions(AccountData accountData[uint8(AccountDataType::NUM_ACCOUNT_DATA_TYPES)], Player* player); + + private: + void SpeedHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data); + void FlyHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data); + void TeleportHackDetection(Player* player, MovementInfo movementInfo, AnticheatData& data); + void WalkOnWaterHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data); + void JumpHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data, uint32 opcode); + void TeleportPlaneHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data, uint32 opcode); + void ClimbHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data, uint32 opcode); + void GravityHackDetection(Player* player, MovementInfo& movementInfo, AnticheatData& data, uint32 opcode); + void BGStartExploit(Player* player, MovementInfo movementInfo, AnticheatData& data, uint32 opcode); + void BuildReport(Player* player, AnticheatData& data, uint8 reportType); + + bool MustCheckTempReports(uint8 type); + std::unordered_map _luaBlockedFunctions; + AnticheatPlayersDataMap _players; +}; + +#define sAnticheatMgr AnticheatMgr::instance() + +#endif diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index cf0ffdb456e..9ed7f7f6587 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -7,6 +7,7 @@ file(GLOB_RECURSE sources_Accounts Accounts/*.cpp Accounts/*.h) file(GLOB_RECURSE sources_Achievements Achievements/*.cpp Achievements/*.h) file(GLOB_RECURSE sources_Addons Addons/*.cpp Addons/*.h) file(GLOB_RECURSE sources_AI AI/*.cpp AI/*.h) +file(GLOB_RECURSE sources_Anticheat Anticheat/*.cpp Anticheat/*.h) file(GLOB_RECURSE sources_AuctionHouse AuctionHouse/*.cpp AuctionHouse/*.h) file(GLOB_RECURSE sources_Battlefield Battlefield/*.cpp Battlefield/*.h) file(GLOB_RECURSE sources_Battlegrounds Battlegrounds/*.cpp Battlegrounds/*.h) @@ -53,6 +54,7 @@ source_group(Accounts FILES ${sources_Accounts}) source_group(Achievements FILES ${sources_Achievements}) source_group(Addons FILES ${sources_Addons}) source_group(AI FILES ${sources_AI}) +source_group(Anticheat FILES ${sources_Anticheat}) source_group(AuctionHouse FILES ${sources_AuctionHouse}) source_group(Battlefield FILES ${sources_Battlefield}) source_group(Battlegrounds FILES ${sources_Battlegrounds}) @@ -106,6 +108,7 @@ set(game_STAT_SRCS ${sources_Achievements} ${sources_Addons} ${sources_AI} + ${sources_Anticheat} ${sources_AuctionHouse} ${sources_Battlefield} ${sources_Battlegrounds} @@ -180,6 +183,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/AI/CoreAI ${CMAKE_CURRENT_SOURCE_DIR}/AI/ScriptedAI ${CMAKE_CURRENT_SOURCE_DIR}/AI/SmartScripts + ${CMAKE_CURRENT_SOURCE_DIR}/Anticheat ${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouse ${CMAKE_CURRENT_SOURCE_DIR}/Battlefield ${CMAKE_CURRENT_SOURCE_DIR}/Battlefield/Zones diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index a799c234c98..e52f62f2633 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -6,6 +6,7 @@ #include "Player.h" #include "AccountMgr.h" #include "AchievementMgr.h" +#include "AnticheatMgr.h" #include "ArenaTeam.h" #include "ArenaTeamMgr.h" #include "Battlefield.h" @@ -570,7 +571,7 @@ Player::Player(WorldSession* session): Unit(true) m_bCanDelayTeleport = false; m_bHasDelayedTeleport = false; m_teleport_options = 0; - + m_canTeleport = false; m_trade = NULL; m_cinematic = 0; @@ -2151,6 +2152,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // near teleport, triggering send CMSG_MOVE_TELEPORT_ACK from client at landing if (!GetSession()->PlayerLogout()) { + SetCanTeleport(true); Position oldPos; GetPosition(&oldPos); Relocate(x, y, z, orientation); @@ -2266,6 +2268,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (!GetSession()->PlayerLogout()) { + SetCanTeleport(true); WorldPacket data(SMSG_NEW_WORLD, 4 + 4 + 4 + 4 + 4); data << float(m_teleport_dest.GetPositionX()); data << uint32(mapid); @@ -20154,6 +20157,9 @@ void Player::SaveToDB(bool create /*=false*/) if (m_session->isLogingOut() || !sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_STATS_SAVE_ONLY_ON_LOGOUT)) _SaveStats(trans); + // we save the data here to prevent spamming + sAnticheatMgr->SavePlayerData(this); + CharacterDatabase.CommitTransaction(trans); // save pet (hunter pet level and experience and all type pets health/mana). diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index bb53b1e8644..27e740d0993 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -3003,8 +3003,9 @@ class Player : public Unit, public GridObject // Set map to player and add reference void SetMap(Map* map) override; void ResetMap() override; - + bool CanTeleport() { return m_canTeleport; } bool isAllowedToLoot(const Creature* creature); + void SetCanTeleport(bool value) { m_canTeleport = value; } DeclinedName const* GetDeclinedNames() const { @@ -3526,6 +3527,7 @@ class Player : public Unit, public GridObject uint32 m_DelayedOperations; bool m_bCanDelayTeleport; bool m_bHasDelayedTeleport; + bool m_canTeleport; // Temporary removed pet cache uint32 m_temporaryUnsummonedPetNumber; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0c04d3ec923..bbf1a20ff4b 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -15850,6 +15850,10 @@ void Unit::ExitVehicle(Position const* /*exitPosition*/) return; GetVehicleBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, GetGUID()); + if (Player* player = ToPlayer()) + { + player->SetCanTeleport(true); + } //! The following call would not even be executed successfully as the //! SPELL_AURA_CONTROL_VEHICLE unapply handler already calls _ExitVehicle without //! specifying an exitposition. The subsequent call below would return on if (!m_vehicle). @@ -15908,7 +15912,10 @@ void Unit::_ExitVehicle(Position const* exitPosition) init.Launch(); if (player) + { + player->SetCanTeleport(true); player->ResummonPetTemporaryUnSummonedIfAny(); + } if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION) && vehicle->GetBase()->GetTypeId() == TypeID::TYPEID_UNIT) if (((Minion*) vehicle->GetBase())->GetOwner() == this) @@ -16220,6 +16227,7 @@ void Unit::SendTeleportPacket(Position& pos) if (GetTypeId() == TypeID::TYPEID_PLAYER) { + ToPlayer()->SetCanTeleport(true); WorldPacket data2(SMSG_MOVE_TELEPORT, 1 + 8 + 1 + 8 + 1 + 4 + 4 + 4 + 4); WriteMovementInfo(data2); ToPlayer()->SendDirectMessage(&data2); // Send the SMSG_MOVE_TELEPORT packet to self. diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index cd6c32fcefc..5e3ddc23d25 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -19,6 +19,7 @@ #include "ObjectMgr.h" #include "MovementStructures.h" #include "BattlePetMgr.h" +#include "AnticheatMgr.h" #define MOVEMENT_PACKET_TIME_DELAY 0 @@ -364,6 +365,11 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) if (m_clientTimeDelay == 0) m_clientTimeDelay = mstime - movementInfo.time; + if (plrMover) + { + sAnticheatMgr->StartHackDetection(plrMover, movementInfo, opcode); + } + /* process position-change */ movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY; @@ -576,7 +582,7 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData) return; _player->m_movementInfo = movementInfo; - + _player->SetCanTeleport(true); WorldPacket data(SMSG_MOVE_UPDATE_KNOCK_BACK, 66); _player->WriteMovementInfo(data); _player->SendMessageToSet(&data, false); diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp index f2cac49c952..27cc6702179 100644 --- a/src/server/game/Handlers/TaxiHandler.cpp +++ b/src/server/game/Handlers/TaxiHandler.cpp @@ -135,6 +135,9 @@ void WorldSession::SendTaxiMenu(Creature* unit) void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode) { + // add anticheat helper here to avoid false hits if relog during flight path travel + GetPlayer()->SetCanTeleport(true); + // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); @@ -309,6 +312,8 @@ void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recvData) recvData.ReadGuidMask(guid, 4, 0, 1, 2, 5, 6, 7, 3); recvData.ReadGuidBytes(guid, 1, 0, 6, 5, 2, 4, 3, 7); + GetPlayer()->SetCanTeleport(true); + SF_LOG_DEBUG("network", "WORLD: Received CMSG_ACTIVATE_TAXI from %d to %d", nodes[0], nodes[1]); Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER); if (!npc) diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index e754bfaeb36..4af0b7bb114 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1230,6 +1230,7 @@ enum SkyFireStrings // Use for custom patches 11000-11999 LANG_AUTO_BROADCAST = 11000, LANG_INVALID_REALMID = 11001, + LANG_CHEATER_CHATLOG = 11002, // NOT RESERVED IDS 12015-1999999999 LANG_BG_TP_START_TWO_MINUTES = 12000, diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 9b779a6b8a8..7f3001ed680 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -390,6 +390,30 @@ void MotionMaster::MoveFall(uint32 id /*=0*/) Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); } +void MotionMaster::MoveFallPlayer(uint32 id /*=0*/) +{ + // use larger distance for vmap height search than in most other cases + float tz = _owner->GetMap()->GetHeight(_owner->GetPhaseMask(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ(), true, MAX_FALL_DISTANCE); + if (tz <= INVALID_HEIGHT) + { + SF_LOG_DEBUG("misc", "MotionMaster::MoveFall: unable retrive a proper height at map %u (x: %f, y: %f, z: %f).", + _owner->GetMap()->GetId(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); + return; + } + // Abort too if the ground is very near + if (fabs(_owner->GetPositionZ() - tz) < 0.1f) + return; + if (_owner->GetTypeId() == TypeID::TYPEID_PLAYER) + { + _owner->ToPlayer()->SetFallInformation(0, _owner->GetPositionZ()); + } + Movement::MoveSplineInit init(_owner); + init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), tz, false); + init.SetFall(); + init.Launch(); + Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED); +} + void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id, bool generatePath) { if (Impl[MOTION_SLOT_CONTROLLED] && Impl[MOTION_SLOT_CONTROLLED]->GetMovementGeneratorType() != DISTRACT_MOTION_TYPE) diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 269a699ae52..7a28191f97a 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -149,7 +149,7 @@ class MotionMaster //: private std::stack { MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); }; void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = EVENT_JUMP); void MoveFall(uint32 id = 0); - + void MoveFallPlayer(uint32 id = 0); void MoveSeekAssistance(float x, float y, float z); void MoveSeekAssistanceDistract(uint32 timer); void MoveTaxiFlight(uint32 path, uint32 pathnode); diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 1c4744c26bb..5f94f5d9b57 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -28,6 +28,7 @@ void AddSC_SmartSCripts(); //Commands void AddSC_account_commandscript(); void AddSC_achievement_commandscript(); +void AddSC_anticheat_commandscript(); void AddSC_ban_commandscript(); void AddSC_bf_commandscript(); void AddSC_cast_commandscript(); @@ -681,6 +682,7 @@ void AddCommandScripts() { AddSC_account_commandscript(); AddSC_achievement_commandscript(); + AddSC_anticheat_commandscript(); AddSC_ban_commandscript(); AddSC_bf_commandscript(); AddSC_cast_commandscript(); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 6dac9cbfca0..67b9a2cc361 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -35,6 +35,7 @@ #include "WardenWin.h" #include "WardenMac.h" #include "CharacterBoost.h" +#include "AnticheatMgr.h" namespace { @@ -121,6 +122,8 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query } + _isLuaCheater = false; + InitializeQueryCallbackParameters(); _compressionStream = new z_stream(); @@ -770,6 +773,16 @@ void WorldSession::LoadAccountData(PreparedQueryResult result, uint32 mask) m_accountData[type].Data = fields[2].GetString(); } while (result->NextRow()); + + bool cheater = sAnticheatMgr->CheckIsLuaCheater(GetAccountId()); + if (!cheater) + { + cheater = sAnticheatMgr->CheckBlockedLuaFunctions(m_accountData, _player); + } + if (!_isLuaCheater) + { + _isLuaCheater = cheater; + } } void WorldSession::SetAccountData(AccountDataType type, time_t tm, std::string const& data) diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 2bbafb17b21..d84aa6d6a9c 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -520,6 +520,8 @@ class WorldSession z_stream_s* GetCompressionStream() { return _compressionStream; } + bool IsLuaCheater() const { return _isLuaCheater; } + public: // opcodes handlers void Handle_NULL(WorldPacket& recvPacket); // not used void Handle_EarlyProccess(WorldPacket& recvPacket); // just mark packets processed in WorldSocket::OnRead @@ -1198,6 +1200,8 @@ class WorldSession rbac::RBACData* _RBACData; WorldSession(WorldSession const& right) = delete; WorldSession & operator=(WorldSession const& right) = delete; + + bool _isLuaCheater; }; #endif /// @} diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 0a624130d10..c6e47e8859a 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1734,6 +1734,11 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo case FORM_FLIGHT: case FORM_MOONKIN: { + if (Player* player = target->ToPlayer()) + { + player->SetCanTeleport(true); + } + // remove movement affects target->RemoveMovementImpairingAuras(); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 48b2ce15180..9770c43d194 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -44,6 +44,7 @@ #include "DB2Stores.h" #include "Battlefield.h" #include "BattlefieldMgr.h" +#include "AnticheatMgr.h" extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; @@ -5947,6 +5948,11 @@ SpellCastResult Spell::CheckCast(bool strict) else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) return SpellCastResult::SPELL_FAILED_NOPATH; } + if (Player* player = m_caster->ToPlayer()) + { + // To prevent false positives in the Anticheat system + sAnticheatMgr->SetAllowedMovement(player, true); + } break; } case SPELL_EFFECT_SKINNING: diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index df9edc8d959..3b40300b00b 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -478,6 +478,7 @@ class Spell UsedSpellMods m_appliedMods; int32 GetCastTime() const { return m_casttime; } + int32 GetTimer() const { return m_timer; } bool IsAutoRepeat() const { return m_autoRepeat; } void SetAutoRepeat(bool rep) { m_autoRepeat = rep; } void ReSetTimer() { m_timer = m_casttime > 0 ? m_casttime : 0; } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 5b378f07bcb..23283139e73 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -921,6 +921,11 @@ void Spell::EffectJumpDest(SpellEffIndex effIndex) float speedXY, speedZ; CalculateJumpSpeeds(effIndex, m_caster->GetExactDist2d(x, y), speedXY, speedZ); m_caster->GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ); + + if (Player* player = m_caster->ToPlayer()) + { + player->SetCanTeleport(true); + } } void Spell::CalculateJumpSpeeds(uint8 i, float dist, float & speedXY, float & speedZ) @@ -949,6 +954,11 @@ void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/) return; } + if (Player* player = m_caster->ToPlayer()) + { + player->SetCanTeleport(true); + } + // Init dest coordinates uint32 mapid = destTarget->GetMapId(); if (mapid == MAPID_INVALID) @@ -3217,6 +3227,20 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex) { if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i))) { + // if player is lua cheater dont interrupt cast until timer reached 600ms + if (auto player = m_caster->ToPlayer()) + { + if (player->GetSession()->IsLuaCheater()) + { + if (spell->GetCastTime() - spell->GetTimer() < 600) + { + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE::Played %s attempted repeat LUA spell Casting - IP: %s - Flagged at: %s", player->GetName().c_str(), player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + return; + } + } + } + SpellInfo const* curSpellInfo = spell->m_spellInfo; // check if we can interrupt spell if ((spell->getState() == SPELL_STATE_CASTING @@ -5096,6 +5120,10 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) return; } } + if (Player* player = m_caster->ToPlayer()) + { + player->SetCanTeleport(true); + } } void Spell::EffectProspecting(SpellEffIndex /*effIndex*/) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 217b320c325..d12830b034e 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -72,6 +72,7 @@ #include "BattlefieldMgr.h" #include "TransportMgr.h" #include "BattlePetMgr.h" +#include "AnticheatMgr.h" ACE_Atomic_Op World::m_stopEvent = false; uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE; @@ -1346,6 +1347,36 @@ void World::LoadConfigSettings(bool reload) setIntConfig(WorldIntConfigs::CONFIG_PACKET_SPOOF_BANDURATION, sConfigMgr->GetIntDefault("PacketSpoof.BanDuration", 86400)); + // Anticheat Stuff + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.Enable", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE_ON_GM, sConfigMgr->GetBoolDefault("Anticheat.EnabledOnGmAccounts", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_LUABLOCKER_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.LUAblocker", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_SPEEDHACK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.DetectSpeedHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_FLYHACK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.DetectFlyHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_WATERWALKHACK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.DetectWaterWalkHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_JUMPHACK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.DetectJumpHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ADV_JUMPHACK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.StricterDetectJumpHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_TELEPANEHACK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.DetectTelePlaneHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CLIMBHACK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.DetectClimbHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_GRAVITY_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.DetectGravityHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_TELEPORTHACK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.DetectTelePortHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_BG_START_HACK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.DetectBGStartHack", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_FLYHACK, sConfigMgr->GetBoolDefault("Anticheat.CM.FLYHACK", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_WATERHACK, sConfigMgr->GetBoolDefault("Anticheat.CM.WATERHACK", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_SPEEDHACK, sConfigMgr->GetBoolDefault("Anticheat.CM.SPEEDHACK", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_JUMPHACK, sConfigMgr->GetBoolDefault("Anticheat.CM.JUMPHACK", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_ADVJUMPHACK, sConfigMgr->GetBoolDefault("Anticheat.CM.ADVJUMPHACK", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_CM_TELEPORT, sConfigMgr->GetBoolDefault("Anticheat.CM.Teleport", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_AUTOKICK_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.KickPlayer", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_AUTOBAN_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.BanPlayer", false)); + SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_AUTOJAIL_ENABLE, sConfigMgr->GetBoolDefault("Anticheat.JailPlayer", false)); + setIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_REPORTS_INGAME_NOTIFICATION, sConfigMgr->GetIntDefault("Anticheat.Reports.InGame", 70)); + setIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_DAILY_REPORT, sConfigMgr->GetIntDefault("Anticheat.Reports.InGame.Max", 70)); + setIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_SPEED_LIMIT_TOLERANCE, sConfigMgr->GetIntDefault("Anticheat.SpeedLimitTolerance", 10)); + setIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_BANS, sConfigMgr->GetIntDefault("Anticheat.ReportsForBan", 70)); + setIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_KICKS, sConfigMgr->GetIntDefault("Anticheat.ReportsForKick", 70)); + setIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_JAILS, sConfigMgr->GetIntDefault("Anticheat.ReportsForJail", 70)); + // call ScriptMgr if we're reloading the configuration if (reload) sScriptMgr->OnConfigLoad(reload); @@ -1962,6 +1993,9 @@ void World::SetInitialWorldSettings() SF_LOG_INFO("server.loading", "Calculate random battleground reset time..."); InitRandomBGResetTime(); + SF_LOG_INFO("server.loading", "Loading Anticheat LUA blocked data..."); + sAnticheatMgr->LoadBlockedLuaFunctions(); + SF_LOG_INFO("server.loading", "Calculate guild limitation(s) reset time..."); InitGuildResetTime(); @@ -3046,6 +3080,8 @@ void World::ResetDailyQuests() // change available dailies sPoolMgr->ChangeDailyQuests(); + + sAnticheatMgr->ResetDailyReportStates(); } void World::ResetCurrencyWeekCap() diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index d42b4bba7cb..d5d5b7a18e7 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -165,6 +165,30 @@ enum class WorldBoolConfigs CONFIG_TICKETS_GM_ENABLED, CONFIG_TICKETS_FEEDBACK_SYSTEM_ENABLED, CONFIG_BOOST_NEW_ACCOUNT, + // Anticheat + CONFIG_ANTICHEAT_ENABLE, + CONFIG_ANTICHEAT_ENABLE_ON_GM, + CONFIG_LUABLOCKER_ENABLE, + CONFIG_ANTICHEAT_SPEEDHACK_ENABLE, + CONFIG_ANTICHEAT_FLYHACK_ENABLE, + CONFIG_ANTICHEAT_WATERWALKHACK_ENABLE, + CONFIG_ANTICHEAT_JUMPHACK_ENABLE, + CONFIG_ANTICHEAT_ADV_JUMPHACK_ENABLE, + CONFIG_ANTICHEAT_TELEPANEHACK_ENABLE, + CONFIG_ANTICHEAT_GRAVITY_ENABLE, + CONFIG_ANTICHEAT_TELEPORTHACK_ENABLE, + CONFIG_ANTICHEAT_CLIMBHACK_ENABLE, + CONFIG_ANTICHEAT_BG_START_HACK_ENABLE, + CONFIG_ANTICHEAT_CM_SPEEDHACK, + CONFIG_ANTICHEAT_CM_FLYHACK, + CONFIG_ANTICHEAT_CM_WATERHACK, + CONFIG_ANTICHEAT_CM_JUMPHACK, + CONFIG_ANTICHEAT_CM_ADVJUMPHACK, + CONFIG_ANTICHEAT_CM_TELEPORT, + CONFIG_ANTICHEAT_AUTOKICK_ENABLE, + CONFIG_ANTICHEAT_AUTOBAN_ENABLE, + CONFIG_ANTICHEAT_AUTOJAIL_ENABLE, + BOOL_CONFIG_VALUE_COUNT }; @@ -359,6 +383,14 @@ enum class WorldIntConfigs CONFIG_BLACK_MARKET_AUCTION_DELAY_MOD, CONFIG_BOOST_START_MONEY, CONFIG_BOOST_START_LEVEL, + // Anticheat + CONFIG_ANTICHEAT_REPORTS_INGAME_NOTIFICATION, + CONFIG_ANTICHEAT_MAX_REPORTS_FOR_DAILY_REPORT, + CONFIG_ANTICHEAT_SPEED_LIMIT_TOLERANCE, + CONFIG_ANTICHEAT_MAX_REPORTS_FOR_BANS, + CONFIG_ANTICHEAT_MAX_REPORTS_FOR_KICKS, + CONFIG_ANTICHEAT_MAX_REPORTS_FOR_JAILS, + INT_CONFIG_VALUE_COUNT }; diff --git a/src/server/scripts/Commands/cs_anticheat.cpp b/src/server/scripts/Commands/cs_anticheat.cpp new file mode 100644 index 00000000000..66a584863bc --- /dev/null +++ b/src/server/scripts/Commands/cs_anticheat.cpp @@ -0,0 +1,267 @@ +/* +* This file is part of Project SkyFire https://www.projectskyfire.org. +* See LICENSE.md file for Copyright information +*/ + +#include "Chat.h" +#include "Language.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "ScriptMgr.h" +#include "SpellAuras.h" +#include "../../game/Anticheat/AnticheatMgr.h" + +enum Spells +{ + FREEZE = 9454, + LFG_SPELL_DUNGEON_DESERTER = 71041, + BG_SPELL_DESERTER = 26013, + SILENCED = 23207 +}; + +class anticheat_commandscript : public CommandScript +{ +public: + anticheat_commandscript() : CommandScript("anticheat_commandscript") { } + + std::vector GetCommands() const override + { + static std::vector anticheatCommandTable = + { + { "global", rbac::RBAC_PERM_COMMAND_GM, true, &HandleAntiCheatGlobalCommand, "", }, + { "player", rbac::RBAC_PERM_COMMAND_GM, true, &HandleAntiCheatPlayerCommand, "", }, + { "delete", rbac::RBAC_PERM_COMMAND_GM, true, &HandleAntiCheatDeleteCommand, "", }, + { "purge", rbac::RBAC_PERM_COMMAND_GM, true, &HandleAntiCheatPurgeCommand, "", }, + { "handle", rbac::RBAC_PERM_COMMAND_GM, true, &HandleAntiCheatHandleCommand, "", }, + { "jail", rbac::RBAC_PERM_COMMAND_GM, true, &HandleAnticheatJailCommand, "", }, + { "parole", rbac::RBAC_PERM_COMMAND_GM, true, &HandleAnticheatParoleCommand, "", }, + }; + + static std::vector commandTable = + { + { "anticheat", rbac::RBAC_PERM_COMMAND_GM, true, NULL, "", anticheatCommandTable }, + }; + return commandTable; + } + static bool HandleAntiCheatGlobalCommand(ChatHandler* handler, const char* args) + { + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE)) + { + handler->PSendSysMessage("The Anticheat System is disabled."); + return true; + } + + sAnticheatMgr->AnticheatGlobalCommand(handler); + + return true; + } + static bool HandleAntiCheatPlayerCommand(ChatHandler* handler, char const* args) + { + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE)) + return false; + + Player* target = NULL; + std::string playerName; + if (!handler->extractPlayerTarget((char*)args, &target, NULL, &playerName)) + return false; + + uint32 guid = target->GetGUIDLow(); + + float average = sAnticheatMgr->GetAverage(guid); + uint32 total_reports = sAnticheatMgr->GetTotalReports(guid); + uint32 speed_reports = sAnticheatMgr->GetTypeReports(guid, 0); + uint32 fly_reports = sAnticheatMgr->GetTypeReports(guid, 1); + uint32 waterwalk_reports = sAnticheatMgr->GetTypeReports(guid, 2); + uint32 jump_reports = sAnticheatMgr->GetTypeReports(guid, 3); + uint32 teleportplane_reports = sAnticheatMgr->GetTypeReports(guid, 4); + uint32 climb_reports = sAnticheatMgr->GetTypeReports(guid, 5); + uint32 time_reports = sAnticheatMgr->GetTypeReports(guid, 6); + uint32 gravity_reports = sAnticheatMgr->GetTypeReports(guid, 7); + uint32 teleport_reports = sAnticheatMgr->GetTypeReports(guid, 8); + uint32 bgstart_reports = sAnticheatMgr->GetTypeReports(guid, 9); + + uint32 latency = 0; + latency = target->GetSession()->GetLatency(); + + // account ban info + QueryResult resultADB = LoginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate, banreason, bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC", target->GetSession()->GetAccountId()); + // character ban info + QueryResult resultCDB = CharacterDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate, banreason, bannedby FROM character_banned WHERE guid = '%u' ORDER BY bandate ASC", target->GetGUID()); + // 0 1 2 3 + QueryResult resultLDB = CharacterDatabase.PQuery("SELECT accountId, type, time, data FROM account_data WHERE `data` LIKE '%%CastSpellByName%%' AND accountId = '%u'", target->GetSession()->GetAccountId()); + + handler->PSendSysMessage("-----------------------------------------------------------------"); + handler->PSendSysMessage("Information about player %s", target->GetName().c_str()); + handler->PSendSysMessage("IP Address: %s || Latency %u ms", target->GetSession()->GetRemoteAddress().c_str(), latency); + if (resultADB) + { + do + { + Field* fields = resultADB->Fetch(); + std::string startbanEnd = TimeToTimestampStr(fields[3].GetUInt64()); + std::string bannedReason = fields[4].GetString(); + std::string bannedBy = fields[5].GetString(); + handler->PSendSysMessage("Account Previously Banned: Yes"); + handler->PSendSysMessage("Ban Ended: %s", startbanEnd.c_str()); + handler->PSendSysMessage("Ban by: %s || Ban Reason: %s", bannedBy.c_str(), bannedReason.c_str()); + } while (resultADB->NextRow()); + } + if (!resultADB) + { + handler->PSendSysMessage("Account Previously Banned: No"); + } + if (resultCDB) + { + do + { + Field* fields = resultCDB->Fetch(); + std::string startbanEnd = TimeToTimestampStr(fields[3].GetUInt64()); + std::string bannedReason = fields[4].GetString(); + std::string bannedBy = fields[5].GetString(); + handler->PSendSysMessage("Character Previously Banned: Yes"); + handler->PSendSysMessage("Ban Ended: %s", startbanEnd.c_str()); + handler->PSendSysMessage("Ban by: %s || Ban Reason: %s", bannedBy.c_str(), bannedReason.c_str()); + } while (resultCDB->NextRow()); + } + if (!resultCDB) + { + handler->PSendSysMessage("Character Previously Banned: No"); + } + if (resultLDB) + { + do + { + handler->PSendSysMessage("Macro Requiring Lua unlock Detected: Yes"); + } while (resultLDB->NextRow()); + } + if (!resultLDB) + { + handler->PSendSysMessage("Macro Requiring Lua unlock Detected: No"); + } + handler->PSendSysMessage("Average: %f || Total Reports: %u ", average, total_reports); + handler->PSendSysMessage("Speed Reports: %u || Fly Reports: %u || Jump Reports: %u ", speed_reports, fly_reports, jump_reports); + handler->PSendSysMessage("Walk On Water Reports: %u || Teleport To Plane Reports: %u", waterwalk_reports, teleportplane_reports); + handler->PSendSysMessage("Teleport Reports: %u || Climb Reports: %u", teleport_reports, climb_reports); + handler->PSendSysMessage("Time Manipuilation Reports: %u || Gravity Reports: %u", time_reports, gravity_reports); + handler->PSendSysMessage("Battle Ground Start Reports: %u", bgstart_reports); + return true; + } + static bool HandleAntiCheatDeleteCommand(ChatHandler* handler, char const* args) + { + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE)) + return false; + + Player* target = NULL; + std::string playerName; + if (!handler->extractPlayerTarget((char*)args, &target, NULL, &playerName)) + return false; + + sAnticheatMgr->AnticheatDeleteCommand(target->GetGUID()); + handler->PSendSysMessage("Anticheat players_reports_status deleted for player %s", target->GetName().c_str()); + return true; + } + static bool HandleAntiCheatPurgeCommand(ChatHandler* handler, const char* args) + { + // For the sins I am about to commit, may CTHULHU forgive me + // this will purge the daily_player_reports which is the cumlative statistics of auto reports + sAnticheatMgr->AnticheatPurgeCommand(handler); + handler->PSendSysMessage("The Anticheat daily_player_reports has been purged."); + return true; + } + static bool HandleAntiCheatHandleCommand(ChatHandler* handler, const char* args) + { + if (!handler->GetSession() && !handler->GetSession()->GetPlayer()) + return false; + + std::string argstr = (char*)args; + + if (argstr == "on") + { + sWorld->SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE, true); + handler->SendSysMessage("The Anticheat System is now: Enabled!"); + return true; + } + if (argstr == "off") + { + sWorld->SetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE, false); + handler->SendSysMessage("The Anticheat System is now: Disabled!"); + return true; + } + + std::string strACModIs = sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE) ? "enabled" : "disabled"; + handler->PSendSysMessage("Anticheat Manager is now %s.", strACModIs.c_str()); + + return true; + } + static bool HandleAnticheatJailCommand(ChatHandler* handler, char const* args) + { + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE)) + return false; + + Player* target = NULL; + std::string playerName; + if (!handler->extractPlayerTarget((char*)args, &target, NULL, &playerName)) + return false; + + WorldLocation jailLoc = WorldLocation(1, 16226.5f, 16403.6f, -64.5f, 3.2f);// GM Jail Location + target->TeleportTo(jailLoc); + target->SetHomebind(jailLoc, 876);// GM Jail Homebind location + target->CastSpell(target, FREEZE);// Freeze him in place to ensure no exploit happens for jail break attempt + + if (Aura* dungdesert = target->AddAura(LFG_SPELL_DUNGEON_DESERTER, target))// LFG_SPELL_DUNGEON_DESERTER + { + dungdesert->SetDuration(-1); + } + if (Aura* bgdesert = target->AddAura(BG_SPELL_DESERTER, target))// BG_SPELL_DESERTER + { + bgdesert->SetDuration(-1); + } + if (Aura* silent = target->AddAura(SILENCED, target))// SILENCED + { + silent->SetDuration(-1); + } + + return true; + } + static bool HandleAnticheatParoleCommand(ChatHandler* handler, char const* args) + { + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE)) + return false; + + Player* target = NULL; + std::string playerName; + if (!handler->extractPlayerTarget((char*)args, &target, NULL, &playerName)) + return false; + + WorldLocation Aloc = WorldLocation(0, -8833.37f, 628.62f, 94.00f, 1.06f);// Stormwind + WorldLocation Hloc = WorldLocation(1, 1569.59f, -4397.63f, 16.06f, 0.54f);// Orgrimmar + WorldLocation Nloc = WorldLocation(860, 1470.96f, 3466.06f, 181.63f, 2.78f);//Shang Xi Training Grounds + + if (target->getRace() == RACE_PANDAREN_NEUTRAL) + { + target->TeleportTo(860, 1470.96f, 3466.06f, 181.63f, 2.78f);//Shang Xi Training Grounds + target->SetHomebind(Nloc, 5834);// Orgrimmar Homebind location + } + if (target->GetTeamId() == TEAM_ALLIANCE && target->getRace() != RACE_PANDAREN_NEUTRAL) + { + target->TeleportTo(0, -8833.37f, 628.62f, 94.00f, 1.06f);//Stormwind + target->SetHomebind(Aloc, 1519);// Stormwind Homebind location + } + if (target->GetTeamId() == TEAM_HORDE && target->getRace() != RACE_PANDAREN_NEUTRAL) + { + target->TeleportTo(1, 1569.59f, -4397.63f, 7.7f, 0.54f);//Orgrimmar + target->SetHomebind(Hloc, 1653);// Orgrimmar Homebind location + } + target->RemoveAura(FREEZE);// remove shackles + target->RemoveAura(LFG_SPELL_DUNGEON_DESERTER);// LFG_SPELL_DUNGEON_DESERTER + target->RemoveAura(BG_SPELL_DESERTER);// BG_SPELL_DESERTER + target->RemoveAura(SILENCED);// SILENCED + sAnticheatMgr->AnticheatDeleteCommand(target->GetGUID());// deletes auto reports on player + return true; + } +}; + +void AddSC_anticheat_commandscript() +{ + new anticheat_commandscript(); +} diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 248491acc95..908a12ff799 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -656,5 +656,9 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_BLACKMARKET_AUCTION, "DELETE FROM blackmarket_auctions WHERE auctionId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_BLACKMARKET_AUCTION, "INSERT INTO blackmarket_auctions (auctionId, templateId, startTime, currentBidder, currentBid, minIncrement, numBids) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_BLACKMARKET_AUCTION, "UPDATE blackmarket_auctions SET currentBidder = ?, currentBid = ?, minIncrement = ?, numBids = ? WHERE auctionId = ?", CONNECTION_ASYNC); + + // Anticheat Lua Cheaters + PrepareStatement(CHAR_INS_ANTICHEAT_LUA_CHEATERS, "INSERT IGNORE INTO `lua_cheaters` (guid, account, macro) VALUES (?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_ANTICHEAT_LUA_CHEATERS, "SELECT guid, account FROM lua_cheaters WHERE account = ?", CONNECTION_SYNCH); } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 539ba72be28..afb94e90f61 100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -580,6 +580,10 @@ enum CharacterDatabaseStatements CHAR_DEL_BLACKMARKET_AUCTION, CHAR_UPD_BLACKMARKET_AUCTION, + // Anticheat + CHAR_INS_ANTICHEAT_LUA_CHEATERS, + CHAR_SEL_ANTICHEAT_LUA_CHEATERS, + MAX_CHARACTERDATABASE_STATEMENTS }; diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index e147c3ba098..3e2b58bfba2 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -81,4 +81,6 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_REQ_XP, "SELECT xp_for_next_level FROM player_xp_for_level WHERE lvl = ?", CONNECTION_SYNCH); // blackmarket PrepareStatement(WORLD_SEL_BLACKMARKET_TEMPLATE, "SELECT Id, MarketID, SellerID, ItemEntry, Quantity, MinBid, Duration, Chance FROM blackmarket_template", CONNECTION_SYNCH); + // Anticheat + PrepareStatement(WORLD_SEL_ANTICHEAT_FUNCTIONS, "SELECT function_name, enabled FROM lua_private_functions", CONNECTION_SYNCH); } diff --git a/src/server/shared/Database/Implementation/WorldDatabase.h b/src/server/shared/Database/Implementation/WorldDatabase.h index 01d71021878..117c409a0a3 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.h +++ b/src/server/shared/Database/Implementation/WorldDatabase.h @@ -100,7 +100,7 @@ enum WorldDatabaseStatements WORLD_DEL_DISABLES, WORLD_SEL_REQ_XP, WORLD_SEL_BLACKMARKET_TEMPLATE, - + WORLD_SEL_ANTICHEAT_FUNCTIONS, MAX_WORLDDATABASE_STATEMENTS }; diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 20141ffd9c7..275aa374d20 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -3110,3 +3110,141 @@ Boost.StartLevel = 90 # ################################################################################################### + +################################################################################################### +# ANTICHEAT +# +# Anticheat.Enable +# Description: Enables or disables the Anticheat System functionality +# Default: 1 - (Enabled) +# 0 - (Disabled) + +Anticheat.Enable = 1 + +# Anticheat.EnabledOnGmAccounts +# Description: Enables detection for GM accounts +# Default: 0 - (Disabled) +# 1 - (Enabled) + +Anticheat.EnabledOnGmAccounts = 0 + +# Anticheat REPORTING +# Description: Alerts GMs that are on line once reports hit designated threshhold and stops after desiganted threshhold +# Default: 70 - (Alerts at and Stops Alerting at 70 report thresh hold) +# 0 - (Disabled) + +Anticheat.Reports.InGame = 70 +Anticheat.Reports.InGame.Max = 70 + +# Anticheat.Detect +# Description: It represents which detections are enabled (ClimbHack disabled by default). +# Default: 0 - (Disabled) +# 1 - (Enabled) + +Anticheat.LUAblocker = 0 +Anticheat.DetectFlyHack = 0 +Anticheat.DetectWaterWalkHack = 0 +Anticheat.DetectJumpHack = 0 +Anticheat.StricterDetectJumpHack = 0 +Anticheat.DetectTelePlaneHack = 0 +Anticheat.DetectSpeedHack = 0 +Anticheat.DetectClimbHack = 0 +Anticheat.DetectGravityHack = 0 +Anticheat.DetectTelePortHack = 0 + +# ANTICHEAT COUNTER MEASURE +# +# Anticheat Counter Measures +# +# Anticheat.CM.Teleport +# +# Description: Sends player back to last gps position if player cheats and teleports. +# +# Default: 0 - (Disabled) +# 1 - (Enabled) +# +Anticheat.CM.Teleport = 0 +# +# Anticheat.CM.FLYHACK +# +# Description: Sets player back to the ground if fly hack is detected +# +# Default: 0 - (Disabled) +# 1 - (Enabled) +# +Anticheat.CM.FLYHACK = 0 +# +# Anticheat.CM.WATERHACK +# +# Description: Sets player to fall if water hack is detected +# +# Default: 0 - (Disabled) +# 1 - (Enabled) +# +Anticheat.CM.WATERHACK = 0 +# +# Anticheat.CM.JUMPHACK +# Anticheat.CM.ADVJUMPHACK +# Description: Sets player back to the ground if jump hack is detected +# +# Default: 0 - (Disabled) +# 1 - (Enabled) +# +Anticheat.CM.JUMPHACK = 0 +Anticheat.CM.ADVJUMPHACK = 0 +# +# Anticheat.CM.SPEEDHACK +# +# Description: Sets player back to allowed server rate speed when speed hack is detected +# Default: 0 - (Disabled) +# 1 - (Enabled) +# +Anticheat.CM.SPEEDHACK = 0 + +# Automatic Moderation Features +# +# Anticheat.KickPlayer +# Anticheat.ReportsForKick +# +# Description: Enables and Auto kick when reports reach threshhold +# Default: 0 - (Disabled) +# 1 - (Enabled) +# Default: 70 - (Kicks at 70 auto reports) +# + +Anticheat.KickPlayer = 0 +Anticheat.ReportsForKick = 75 + +# Anticheat.BanPlayer +# Anticheat.ReportsForBan +# +# Description: Enables and Auto ban when reports reach threshhold +# Default: 0 - (Disabled) +# 1 - (Enabled) +# Default: 70 - (Bans at 70 auto reports) +# + +Anticheat.BanPlayer = 0 +Anticheat.ReportsForBan = 70 + +# Anticheat.JailPlayer +# Anticheat.ReportsForJail +# +# Description: Enables and Auto Jail when reports reach threshhold +# Default: 0 - (Disabled) +# 1 - (Enabled) +# Default: 70 - (Jails at 70 auto reports) +# + +Anticheat.JailPlayer = 0 +Anticheat.ReportsForJail = 70 + +# Anticheat Logging\Appenders +# Currently spams into its own file +# If you want world console spam just use Logger.anticheat=3,Console Server Anticheat + +Appender.Anticheat=2,3,15,anticheat.log,a +Logger.anticheat=3,Server Anticheat + +# +################################################################################################### From 9c35e6a4935ef2686a11390a283ba26cadd9944b Mon Sep 17 00:00:00 2001 From: M'Dic Date: Fri, 24 Nov 2023 12:42:12 -0500 Subject: [PATCH 02/23] update (anticheat): Remove Lua Blocker --- .../characters/2023_11_12_00_characters.sql | 7 -- sql/updates/world/2023_11_22_world.sql | 10 -- src/server/game/Anticheat/AnticheatMgr.cpp | 99 ------------------- src/server/game/Anticheat/AnticheatMgr.h | 4 - src/server/game/Server/WorldSession.cpp | 13 --- src/server/game/Server/WorldSession.h | 4 - src/server/game/Spells/Spell.h | 1 - src/server/game/Spells/SpellEffects.cpp | 14 --- src/server/worldserver/worldserver.conf.dist | 1 - 9 files changed, 153 deletions(-) diff --git a/sql/updates/characters/2023_11_12_00_characters.sql b/sql/updates/characters/2023_11_12_00_characters.sql index b10a4685d0a..2eb4278f14e 100644 --- a/sql/updates/characters/2023_11_12_00_characters.sql +++ b/sql/updates/characters/2023_11_12_00_characters.sql @@ -1,10 +1,3 @@ -CREATE TABLE IF NOT EXISTS `lua_cheaters` ( - `guid` int unsigned NOT NULL DEFAULT 0, - `account` int unsigned NOT NULL DEFAULT 0, - `macro` varchar(255) NOT NULL DEFAULT '', - PRIMARY KEY (`guid`,`account`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - DROP TABLE `daily_players_reports`; CREATE TABLE IF NOT EXISTS `daily_players_reports` ( `guid` int unsigned NOT NULL DEFAULT 0, diff --git a/sql/updates/world/2023_11_22_world.sql b/sql/updates/world/2023_11_22_world.sql index e142a5c8fe1..b97a874fad0 100644 --- a/sql/updates/world/2023_11_22_world.sql +++ b/sql/updates/world/2023_11_22_world.sql @@ -1,13 +1,3 @@ -DROP TABLE IF EXISTS `lua_private_functions`; -CREATE TABLE IF NOT EXISTS `lua_private_functions` ( - `function_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, - `enabled` tinyint(4) NOT NULL DEFAULT '1' -) ENGINE=InnoDB DEFAULT CHARSET=latin1; -DELETE FROM `lua_private_functions`; -INSERT INTO `lua_private_functions` (`function_name`, `enabled`) VALUES - ('CastSpellByName', 1), - ('RunMacroText', 1); - DELETE FROM `skyfire_string` WHERE `entry`=11002; INSERT INTO `skyfire_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`, `content_loc9`, `content_loc10`, `content_loc11`)VALUES (11002, '|cFFFFBF00[%s]:|cFFFFFFFF|Hplayer:%s|h[%s]|h|cFF00FFFF potential |r|cFFFFFF00%s|r%s x %u|r', null, null, null, null, null, null, null, null, null, null, null); diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index 95d038c8e52..7d4e88283e3 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -120,105 +120,6 @@ AnticheatMgr::~AnticheatMgr() { } -void AnticheatMgr::LoadBlockedLuaFunctions() -{ - if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_LUABLOCKER_ENABLE)) - { - SF_LOG_INFO("server.loading", ">> Anticheat.LUAblocker conf is set to 0"); - return; - } - uint32 oldmsTime = getMSTime(); - auto pstmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_ANTICHEAT_FUNCTIONS); - auto result = WorldDatabase.Query(pstmt); - if (!result) - { - SF_LOG_INFO("server.loading", ">> Anticheat loaded 0 LUA blocked private functions"); - return; - } - uint32 count = 0; - do - { - auto fields = result->Fetch(); - _luaBlockedFunctions[fields[0].GetString()] = fields[1].GetBool(); - ++count; - } while (result->NextRow()); - - SF_LOG_INFO("server.loading", ">> Anticheat loaded %u LUA blocked private functions in %u ms", count, GetMSTimeDiffToNow(oldmsTime)); -} - -void AnticheatMgr::SaveLuaCheater(uint32 guid, uint32 accountId, std::string macro) -{ - auto pstmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ANTICHEAT_LUA_CHEATERS); - pstmt->setUInt32(0, guid); - pstmt->setUInt32(1, accountId); - pstmt->setString(2, macro); - CharacterDatabase.Execute(pstmt); -} - -bool AnticheatMgr::CheckIsLuaCheater(uint32 accountId) -{ - auto pstmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ANTICHEAT_LUA_CHEATERS); - pstmt->setUInt32(0, accountId); - auto result = CharacterDatabase.Query(pstmt); - if (result) - return true; - - return false; -} - -bool AnticheatMgr::CheckBlockedLuaFunctions(AccountData accountData[uint8(AccountDataType::NUM_ACCOUNT_DATA_TYPES)], Player* player) -{ - for (auto& kv : _luaBlockedFunctions) - { - for (uint8 i = 0; i < uint8(AccountDataType::NUM_ACCOUNT_DATA_TYPES); ++i) - { - std::string currentData = accountData[i].Data; - std::size_t pos = currentData.find(kv.first); - if (pos != std::string::npos) - { - // Code inside this if statement block will only execute if the variable 'pos' is not equal to std::string::npos. - // std::string::npos is a special value indicating the absence of a valid position. - // The following below is all done to capture the macro used and stored it in the SaveLuaCheater - - const static std::size_t defaultLength = 200; - // Declares a constant variable 'defaultLength' with a value of 200. - // This variable represents the default length of a substring to be extracted. - - std::size_t minPos = int64(int(pos) - 50) < 0 ? 0 : pos - 50; - - // Calculates the minimum position from where the substring will be extracted. - // It subtracts 50 from the 'pos' value, casts it to int64, and checks if it's less than 0. - // If it is less than 0, sets 'minPos' to 0, otherwise sets 'minPos' to 'pos - 50'. - // With out the - 50 we will get a crash on certain substrings - - std::size_t length = defaultLength + minPos > currentData.length() - 1 ? currentData.length() - minPos : defaultLength; - // Calculates the length of the substring to be extracted. - // It adds 'defaultLength' to 'minPos' and checks if it's greater than the length of 'currentData' minus 1. - // If it is greater, sets 'length' to 'currentData.length() - minPos', otherwise sets it to 'defaultLength'. - - std::string macro = currentData.substr(minPos, length); - // Extracts a substring from 'currentData' starting at 'minPos' with a length of 'length' and assigns it to the variable 'macro'. - - if (player) - { - // Checks if the 'player' pointer is not null (i.e., it points to a valid object, aka The NULL CHECK). - - SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE::Player %s has inaccessible LUA MACRO, placing on watch list", player->GetName().c_str()); - // Outputs a log message indicating that the player has an inaccessible Lua macro and is being placed on a watch list. - - SaveLuaCheater(player->GetGUID(), player->GetSession()->GetAccountId(), macro); - // Calls the 'SaveLuaCheater' function, passing in the player's GUID, session account ID, and the 'macro' string. - // This function saves information about the Lua cheater, such as the id of the player account, character, and macro used, for further analysis or enforcement actions. - } - - return true; - } - } - } - - return false; -} - void AnticheatMgr::StartHackDetection(Player* player, MovementInfo& movementInfo, uint32 opcode) { if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_ENABLE)) diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h index 6550ca92b74..9ea16b6e7fe 100644 --- a/src/server/game/Anticheat/AnticheatMgr.h +++ b/src/server/game/Anticheat/AnticheatMgr.h @@ -96,10 +96,6 @@ class AnticheatMgr void AnticheatDeleteCommand(uint32 guid); void AnticheatPurgeCommand(ChatHandler* handler); void ResetDailyReportStates(); - void LoadBlockedLuaFunctions(); - void SaveLuaCheater(uint32 guid, uint32 accountId, std::string macro); - bool CheckIsLuaCheater(uint32 accountId); - bool CheckBlockedLuaFunctions(AccountData accountData[uint8(AccountDataType::NUM_ACCOUNT_DATA_TYPES)], Player* player); private: void SpeedHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 67b9a2cc361..6dac9cbfca0 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -35,7 +35,6 @@ #include "WardenWin.h" #include "WardenMac.h" #include "CharacterBoost.h" -#include "AnticheatMgr.h" namespace { @@ -122,8 +121,6 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query } - _isLuaCheater = false; - InitializeQueryCallbackParameters(); _compressionStream = new z_stream(); @@ -773,16 +770,6 @@ void WorldSession::LoadAccountData(PreparedQueryResult result, uint32 mask) m_accountData[type].Data = fields[2].GetString(); } while (result->NextRow()); - - bool cheater = sAnticheatMgr->CheckIsLuaCheater(GetAccountId()); - if (!cheater) - { - cheater = sAnticheatMgr->CheckBlockedLuaFunctions(m_accountData, _player); - } - if (!_isLuaCheater) - { - _isLuaCheater = cheater; - } } void WorldSession::SetAccountData(AccountDataType type, time_t tm, std::string const& data) diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index d84aa6d6a9c..2bbafb17b21 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -520,8 +520,6 @@ class WorldSession z_stream_s* GetCompressionStream() { return _compressionStream; } - bool IsLuaCheater() const { return _isLuaCheater; } - public: // opcodes handlers void Handle_NULL(WorldPacket& recvPacket); // not used void Handle_EarlyProccess(WorldPacket& recvPacket); // just mark packets processed in WorldSocket::OnRead @@ -1200,8 +1198,6 @@ class WorldSession rbac::RBACData* _RBACData; WorldSession(WorldSession const& right) = delete; WorldSession & operator=(WorldSession const& right) = delete; - - bool _isLuaCheater; }; #endif /// @} diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 3b40300b00b..df9edc8d959 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -478,7 +478,6 @@ class Spell UsedSpellMods m_appliedMods; int32 GetCastTime() const { return m_casttime; } - int32 GetTimer() const { return m_timer; } bool IsAutoRepeat() const { return m_autoRepeat; } void SetAutoRepeat(bool rep) { m_autoRepeat = rep; } void ReSetTimer() { m_timer = m_casttime > 0 ? m_casttime : 0; } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 23283139e73..543bc18cf05 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3227,20 +3227,6 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex) { if (Spell* spell = unitTarget->GetCurrentSpell(CurrentSpellTypes(i))) { - // if player is lua cheater dont interrupt cast until timer reached 600ms - if (auto player = m_caster->ToPlayer()) - { - if (player->GetSession()->IsLuaCheater()) - { - if (spell->GetCastTime() - spell->GetTimer() < 600) - { - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "ANTICHEAT COUNTER MEASURE::Played %s attempted repeat LUA spell Casting - IP: %s - Flagged at: %s", player->GetName().c_str(), player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - return; - } - } - } - SpellInfo const* curSpellInfo = spell->m_spellInfo; // check if we can interrupt spell if ((spell->getState() == SPELL_STATE_CASTING diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 275aa374d20..01d30fdca1e 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -3141,7 +3141,6 @@ Anticheat.Reports.InGame.Max = 70 # Default: 0 - (Disabled) # 1 - (Enabled) -Anticheat.LUAblocker = 0 Anticheat.DetectFlyHack = 0 Anticheat.DetectWaterWalkHack = 0 Anticheat.DetectJumpHack = 0 From b4f7db8da762152879d4b305b5b4c3fcecbc26bf Mon Sep 17 00:00:00 2001 From: M'Dic Date: Fri, 24 Nov 2023 12:45:31 -0500 Subject: [PATCH 03/23] update (anticheat): Ace Singleton --- src/server/game/Anticheat/AnticheatMgr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h index 9ea16b6e7fe..2c53271df16 100644 --- a/src/server/game/Anticheat/AnticheatMgr.h +++ b/src/server/game/Anticheat/AnticheatMgr.h @@ -114,6 +114,6 @@ class AnticheatMgr AnticheatPlayersDataMap _players; }; -#define sAnticheatMgr AnticheatMgr::instance() +#define sAnticheatMgr ACE_Singleton::instance() #endif From 9225812b68c83dbb17afe845f329ac61a29c48d3 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Fri, 24 Nov 2023 12:51:54 -0500 Subject: [PATCH 04/23] update (anticheat): singleton pt 2 --- src/server/game/Anticheat/AnticheatMgr.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h index 2c53271df16..fb658d8fcce 100644 --- a/src/server/game/Anticheat/AnticheatMgr.h +++ b/src/server/game/Anticheat/AnticheatMgr.h @@ -70,6 +70,8 @@ typedef std::unordered_map AnticheatPlayersDataMap; class AnticheatMgr { + friend class ACE_Singleton; + AnticheatMgr(); ~AnticheatMgr(); From c52c93af1f109b8c9dbb3e05381146c37a2acb29 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Fri, 24 Nov 2023 12:54:13 -0500 Subject: [PATCH 05/23] update (anticheat): LUA Blocker removal pt2 --- src/server/game/World/World.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index d12830b034e..e4206b915ba 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1993,9 +1993,6 @@ void World::SetInitialWorldSettings() SF_LOG_INFO("server.loading", "Calculate random battleground reset time..."); InitRandomBGResetTime(); - SF_LOG_INFO("server.loading", "Loading Anticheat LUA blocked data..."); - sAnticheatMgr->LoadBlockedLuaFunctions(); - SF_LOG_INFO("server.loading", "Calculate guild limitation(s) reset time..."); InitGuildResetTime(); From 91df8894cefe057da208bf1428fa76081f1ac040 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Fri, 24 Nov 2023 12:59:39 -0500 Subject: [PATCH 06/23] update (anticheat): Remove unused variable --- src/server/game/Anticheat/AnticheatMgr.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index 7d4e88283e3..16fffaf12e7 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -648,8 +648,6 @@ void AnticheatMgr::ClimbHackDetection(Player *player, MovementInfo &movementInfo player->GetPosition(&playerPos); float deltaZ = fabs(playerPos.GetPositionZ() - movementInfo.pos.GetPositionZ()); - float deltaXY = movementInfo.pos.GetExactDist2d(&playerPos); - float tanangle = movementInfo.pos.GetExactDist2d(&playerPos) / deltaZ; if (!player->HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_SWIMMING)) From 961ab62201928194f4c2e709adcd7fbe8857388c Mon Sep 17 00:00:00 2001 From: M'Dic Date: Fri, 24 Nov 2023 13:06:05 -0500 Subject: [PATCH 07/23] update (anticheat): Lua Blocker Removal PT 3 --- .../shared/Database/Implementation/CharacterDatabase.cpp | 4 ---- src/server/shared/Database/Implementation/CharacterDatabase.h | 4 ---- src/server/shared/Database/Implementation/WorldDatabase.cpp | 2 -- src/server/shared/Database/Implementation/WorldDatabase.h | 2 +- 4 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 908a12ff799..248491acc95 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -656,9 +656,5 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_BLACKMARKET_AUCTION, "DELETE FROM blackmarket_auctions WHERE auctionId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_BLACKMARKET_AUCTION, "INSERT INTO blackmarket_auctions (auctionId, templateId, startTime, currentBidder, currentBid, minIncrement, numBids) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_BLACKMARKET_AUCTION, "UPDATE blackmarket_auctions SET currentBidder = ?, currentBid = ?, minIncrement = ?, numBids = ? WHERE auctionId = ?", CONNECTION_ASYNC); - - // Anticheat Lua Cheaters - PrepareStatement(CHAR_INS_ANTICHEAT_LUA_CHEATERS, "INSERT IGNORE INTO `lua_cheaters` (guid, account, macro) VALUES (?, ?, ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_ANTICHEAT_LUA_CHEATERS, "SELECT guid, account FROM lua_cheaters WHERE account = ?", CONNECTION_SYNCH); } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index afb94e90f61..539ba72be28 100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -580,10 +580,6 @@ enum CharacterDatabaseStatements CHAR_DEL_BLACKMARKET_AUCTION, CHAR_UPD_BLACKMARKET_AUCTION, - // Anticheat - CHAR_INS_ANTICHEAT_LUA_CHEATERS, - CHAR_SEL_ANTICHEAT_LUA_CHEATERS, - MAX_CHARACTERDATABASE_STATEMENTS }; diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index 3e2b58bfba2..e147c3ba098 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -81,6 +81,4 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_REQ_XP, "SELECT xp_for_next_level FROM player_xp_for_level WHERE lvl = ?", CONNECTION_SYNCH); // blackmarket PrepareStatement(WORLD_SEL_BLACKMARKET_TEMPLATE, "SELECT Id, MarketID, SellerID, ItemEntry, Quantity, MinBid, Duration, Chance FROM blackmarket_template", CONNECTION_SYNCH); - // Anticheat - PrepareStatement(WORLD_SEL_ANTICHEAT_FUNCTIONS, "SELECT function_name, enabled FROM lua_private_functions", CONNECTION_SYNCH); } diff --git a/src/server/shared/Database/Implementation/WorldDatabase.h b/src/server/shared/Database/Implementation/WorldDatabase.h index 117c409a0a3..01d71021878 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.h +++ b/src/server/shared/Database/Implementation/WorldDatabase.h @@ -100,7 +100,7 @@ enum WorldDatabaseStatements WORLD_DEL_DISABLES, WORLD_SEL_REQ_XP, WORLD_SEL_BLACKMARKET_TEMPLATE, - WORLD_SEL_ANTICHEAT_FUNCTIONS, + MAX_WORLDDATABASE_STATEMENTS }; From 140854f2b9de04417e7a2bc1d0377187cfe9abd2 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sat, 25 Nov 2023 08:46:53 -0500 Subject: [PATCH 08/23] update (anticheat): Move ace singleton --- src/server/game/Anticheat/AnticheatMgr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h index fb658d8fcce..fe4c6721b1f 100644 --- a/src/server/game/Anticheat/AnticheatMgr.h +++ b/src/server/game/Anticheat/AnticheatMgr.h @@ -70,12 +70,12 @@ typedef std::unordered_map AnticheatPlayersDataMap; class AnticheatMgr { - friend class ACE_Singleton; - AnticheatMgr(); ~AnticheatMgr(); public: + friend class ACE_Singleton; + static AnticheatMgr *instance() { static AnticheatMgr _instance; From fc431239f321e226180cf888c37239d9db0bdd0c Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sat, 25 Nov 2023 08:50:15 -0500 Subject: [PATCH 09/23] update (anticheat): Remove lua blocker leftover --- src/server/game/Anticheat/AnticheatMgr.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h index fe4c6721b1f..e86867ada3b 100644 --- a/src/server/game/Anticheat/AnticheatMgr.h +++ b/src/server/game/Anticheat/AnticheatMgr.h @@ -112,7 +112,6 @@ class AnticheatMgr void BuildReport(Player* player, AnticheatData& data, uint8 reportType); bool MustCheckTempReports(uint8 type); - std::unordered_map _luaBlockedFunctions; AnticheatPlayersDataMap _players; }; From abdf74e6db1ad5c8a712dbb3e23d9fefcb5a1396 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sat, 25 Nov 2023 09:08:59 -0500 Subject: [PATCH 10/23] update (anticheat): Reduce code complexity PT1 --- src/server/game/Anticheat/AnticheatMgr.cpp | 248 +++++++-------------- src/server/game/Anticheat/AnticheatMgr.h | 2 + 2 files changed, 87 insertions(+), 163 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index 16fffaf12e7..cfcdfaf0726 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -161,70 +161,87 @@ void AnticheatMgr::StartHackDetection(Player* player, MovementInfo& movementInfo data->lastOpcode = opcode; } -void AnticheatMgr::SpeedHackDetection(Player* player, MovementInfo& movementInfo, AnticheatData& data) +void AnticheatMgr::MapSpeedTeleExemption(Player* player) { - if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_SPEEDHACK_ENABLE)) - return; - // We exempt all transports found in 548 to prevent false tele hack hits if (player->GetMapId()) { switch (player->GetMapId()) { - case 369: //Transport: Deeprun Tram - case 607: //Transport: Strands of the Ancients - case 582: //Transport: Rut'theran to Auberdine - case 584: //Transport: Menethil to Theramore - case 586: //Transport: Exodar to Auberdine - case 587: //Transport: Feathermoon Ferry - case 588: //Transport: Menethil to Auberdine - case 589: //Transport: Orgrimmar to Grom'Gol - case 590: //Transport: Grom'Gol to Undercity - case 591: //Transport: Undercity to Orgrimmar - case 592: //Transport: Borean Tundra Test - case 593: //Transport: Booty Bay to Ratchet - case 594: //Transport: Howling Fjord Sister Mercy (Quest) - case 596: //Transport: Naglfar - case 610: //Transport: Tirisfal to Vengeance Landing - case 612: //Transport: Menethil to Valgarde - case 613: //Transport: Orgrimmar to Warsong Hold - case 614: //Transport: Stormwind to Valiance Keep - case 620: //Transport: Moa'ki to Unu'pe - case 621: //Transport: Moa'ki to Kamagua - case 622: //Transport: Orgrim's Hammer - case 623: //Transport: The Skybreaker - case 641: //Transport: Alliance Airship BG - case 642: //Transport: Horde Airship BG - case 647: //Transport: Orgrimmar to Thunder Bluff - case 672: //Transport: The Skybreaker (Icecrown Citadel Raid) - case 673: //Transport: Orgrim's Hammer (Icecrown Citadel Raid) - case 712: //Transport: The Skybreaker (IC Dungeon) - case 713: //Transport: Orgrim's Hammer (IC Dungeon) - case 718: //Transport: The Mighty Wind (Icecrown Citadel Raid) - case 766: // Transport 2033864 - case 767: // Transport 2033865 - case 747: // Transport 203732 - case 762: // Transport 203861 - case 763: // Transport 203862 - case 1172: // Transport_Siege_of_Orgrimmar_Alliance - case 1173: // Transport_Siege_of_Orgrimmar_Horde - case 662: // Transport197195 - case 674: // Transport197349-2 - case 738: // Transport200100 - case 739: // Transport200101 - case 740: // Transport200102 - case 741: // Transport200103 - case 742: // Transport203729 - case 743: // Transport203730 - case 748: // Transport203858 - case 749: // Transport203859 - case 750: // Transport203860 - case 765: // Transport203863 - case 1132: // Transport218599 - case 1133: // Transport218600 - return; + case 369: //Transport: Deeprun Tram + case 607: //Transport: Strands of the Ancients + case 582: //Transport: Rut'theran to Auberdine + case 584: //Transport: Menethil to Theramore + case 586: //Transport: Exodar to Auberdine + case 587: //Transport: Feathermoon Ferry + case 588: //Transport: Menethil to Auberdine + case 589: //Transport: Orgrimmar to Grom'Gol + case 590: //Transport: Grom'Gol to Undercity + case 591: //Transport: Undercity to Orgrimmar + case 592: //Transport: Borean Tundra Test + case 593: //Transport: Booty Bay to Ratchet + case 594: //Transport: Howling Fjord Sister Mercy (Quest) + case 596: //Transport: Naglfar + case 610: //Transport: Tirisfal to Vengeance Landing + case 612: //Transport: Menethil to Valgarde + case 613: //Transport: Orgrimmar to Warsong Hold + case 614: //Transport: Stormwind to Valiance Keep + case 620: //Transport: Moa'ki to Unu'pe + case 621: //Transport: Moa'ki to Kamagua + case 622: //Transport: Orgrim's Hammer + case 623: //Transport: The Skybreaker + case 641: //Transport: Alliance Airship BG + case 642: //Transport: Horde Airship BG + case 647: //Transport: Orgrimmar to Thunder Bluff + case 672: //Transport: The Skybreaker (Icecrown Citadel Raid) + case 673: //Transport: Orgrim's Hammer (Icecrown Citadel Raid) + case 712: //Transport: The Skybreaker (IC Dungeon) + case 713: //Transport: Orgrim's Hammer (IC Dungeon) + case 718: //Transport: The Mighty Wind (Icecrown Citadel Raid) + case 766: // Transport 2033864 + case 767: // Transport 2033865 + case 747: // Transport 203732 + case 762: // Transport 203861 + case 763: // Transport 203862 + case 1172: // Transport_Siege_of_Orgrimmar_Alliance + case 1173: // Transport_Siege_of_Orgrimmar_Horde + case 662: // Transport197195 + case 674: // Transport197349-2 + case 738: // Transport200100 + case 739: // Transport200101 + case 740: // Transport200102 + case 741: // Transport200103 + case 742: // Transport203729 + case 743: // Transport203730 + case 748: // Transport203858 + case 749: // Transport203859 + case 750: // Transport203860 + case 765: // Transport203863 + case 1132: // Transport218599 + case 1133: // Transport218600 + return; } } +} +void AnticheatMgr::BGLogger(Player* player, AnticheatData& data) +{ + uint32 latency = 0; + latency = player->GetSession()->GetLatency(); + std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); + SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); + BuildReport(player, data, BG_START_HACK_REPORT); +} + +void AnticheatMgr::SpeedHackDetection(Player* player, MovementInfo& movementInfo, AnticheatData& data) +{ + if (!sWorld->GetBoolConfig(WorldBoolConfigs::CONFIG_ANTICHEAT_SPEEDHACK_ENABLE)) + return; + + if (player) + { + MapSpeedTeleExemption(player); + } + if (player->HasAura(1850) /*Dash*/ || player->HasAuraType(SPELL_AURA_FEATHER_FALL) || player->HasAuraType(SPELL_AURA_SAFE_FALL)) { return; @@ -363,64 +380,9 @@ void AnticheatMgr::TeleportHackDetection(Player* player, MovementInfo movementIn if (player->IsFalling() || (player->IsFalling() && player->IsMounted())) return; - // We exempt all transports found in 548 to prevent false tele hack hits - if (player->GetMapId()) + if (player) { - switch (player->GetMapId()) - { - case 369: //Transport: Deeprun Tram - case 607: //Transport: Strands of the Ancients - case 582: //Transport: Rut'theran to Auberdine - case 584: //Transport: Menethil to Theramore - case 586: //Transport: Exodar to Auberdine - case 587: //Transport: Feathermoon Ferry - case 588: //Transport: Menethil to Auberdine - case 589: //Transport: Orgrimmar to Grom'Gol - case 590: //Transport: Grom'Gol to Undercity - case 591: //Transport: Undercity to Orgrimmar - case 592: //Transport: Borean Tundra Test - case 593: //Transport: Booty Bay to Ratchet - case 594: //Transport: Howling Fjord Sister Mercy (Quest) - case 596: //Transport: Naglfar - case 610: //Transport: Tirisfal to Vengeance Landing - case 612: //Transport: Menethil to Valgarde - case 613: //Transport: Orgrimmar to Warsong Hold - case 614: //Transport: Stormwind to Valiance Keep - case 620: //Transport: Moa'ki to Unu'pe - case 621: //Transport: Moa'ki to Kamagua - case 622: //Transport: Orgrim's Hammer - case 623: //Transport: The Skybreaker - case 641: //Transport: Alliance Airship BG - case 642: //Transport: Horde Airship BG - case 647: //Transport: Orgrimmar to Thunder Bluff - case 672: //Transport: The Skybreaker (Icecrown Citadel Raid) - case 673: //Transport: Orgrim's Hammer (Icecrown Citadel Raid) - case 712: //Transport: The Skybreaker (IC Dungeon) - case 713: //Transport: Orgrim's Hammer (IC Dungeon) - case 718: //Transport: The Mighty Wind (Icecrown Citadel Raid) - case 766: // Transport 2033864 - case 767: // Transport 2033865 - case 747: // Transport 203732 - case 762: // Transport 203861 - case 763: // Transport 203862 - case 1172: // Transport_Siege_of_Orgrimmar_Alliance - case 1173: // Transport_Siege_of_Orgrimmar_Horde - case 662: // Transport197195 - case 674: // Transport197349-2 - case 738: // Transport200100 - case 739: // Transport200101 - case 740: // Transport200102 - case 741: // Transport200103 - case 742: // Transport203729 - case 743: // Transport203730 - case 748: // Transport203858 - case 749: // Transport203859 - case 750: // Transport203860 - case 765: // Transport203863 - case 1132: // Transport218599 - case 1133: // Transport218600 - return; - } + MapSpeedTeleExemption(player); } /* Please work */ @@ -715,11 +677,7 @@ void AnticheatMgr::BGStartExploit(Player* player, MovementInfo movementInfo, Ant (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() > -1283.33f) || (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() < -716.0f)) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } } } @@ -730,11 +688,7 @@ void AnticheatMgr::BGStartExploit(Player* player, MovementInfo movementInfo, Ant // Only way to get this high is with engineering items malfunction. if (!(movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING_FAR) || data.lastOpcode == MSG_MOVE_JUMP) && movementInfo.pos.GetPositionZ() > 380.0f) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } if (Battleground* bg = player->GetBattleground()) @@ -746,21 +700,13 @@ void AnticheatMgr::BGStartExploit(Player* player, MovementInfo movementInfo, Ant (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() > 1500.0f) || (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < 1450.0f)) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } if ((player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() > 957.0f) || (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() < 1416.0f) || (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > 1466.0f)) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } } } @@ -777,20 +723,12 @@ void AnticheatMgr::BGStartExploit(Player* player, MovementInfo movementInfo, Ant (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < 1258.0f) || (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() > 1361.0f)) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } if ((player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() > 730.0f) || (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > 724.8f)) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } } } @@ -807,21 +745,13 @@ void AnticheatMgr::BGStartExploit(Player* player, MovementInfo movementInfo, Ant (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() > 1610.0f) || (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < 1584.0f)) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } if ((player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() > 1816.0f) || (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > 1554.0f) || (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() < 1526.0f)) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } } } @@ -838,21 +768,13 @@ void AnticheatMgr::BGStartExploit(Player* player, MovementInfo movementInfo, Ant (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < -911.0f) || (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() > -760.0f)) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } if ((player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionX() < 1147.8f) || (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() < -855.0f) || (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > -676.0f)) { - uint32 latency = 0; - latency = player->GetSession()->GetLatency(); - std::string goXYZ = ".go xyz " + std::to_string(player->GetPositionX()) + " " + std::to_string(player->GetPositionY()) + " " + std::to_string(player->GetPositionZ() + 1.0f) + " " + std::to_string(player->GetMap()->GetId()) + " " + std::to_string(player->GetOrientation()); - SF_LOG_INFO("anticheat", "Anticheat Manager:: BG START - Hack detected player %s - (GUID %u) - Latency: %u ms - IP: %s - Cheat Flagged at: %s", player->GetName().c_str(), player->GetGUID(), latency, player->GetSession()->GetRemoteAddress().c_str(), goXYZ.c_str()); - BuildReport(player, data, BG_START_HACK_REPORT); + BGLogger(player, data); } } } diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h index e86867ada3b..09af2748abf 100644 --- a/src/server/game/Anticheat/AnticheatMgr.h +++ b/src/server/game/Anticheat/AnticheatMgr.h @@ -100,6 +100,8 @@ class AnticheatMgr void ResetDailyReportStates(); private: + void MapSpeedTeleExemption(Player* player); + void BGLogger(Player* player, AnticheatData& data); void SpeedHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data); void FlyHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data); void TeleportHackDetection(Player* player, MovementInfo movementInfo, AnticheatData& data); From 75315182d1ece218257c820293b07d0da23b8759 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sat, 25 Nov 2023 09:11:28 -0500 Subject: [PATCH 11/23] chore (antcheat): whitespace --- src/server/game/Anticheat/AnticheatMgr.cpp | 105 +++++++++++---------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index cfcdfaf0726..710fe85c225 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -168,61 +168,62 @@ void AnticheatMgr::MapSpeedTeleExemption(Player* player) { switch (player->GetMapId()) { - case 369: //Transport: Deeprun Tram - case 607: //Transport: Strands of the Ancients - case 582: //Transport: Rut'theran to Auberdine - case 584: //Transport: Menethil to Theramore - case 586: //Transport: Exodar to Auberdine - case 587: //Transport: Feathermoon Ferry - case 588: //Transport: Menethil to Auberdine - case 589: //Transport: Orgrimmar to Grom'Gol - case 590: //Transport: Grom'Gol to Undercity - case 591: //Transport: Undercity to Orgrimmar - case 592: //Transport: Borean Tundra Test - case 593: //Transport: Booty Bay to Ratchet - case 594: //Transport: Howling Fjord Sister Mercy (Quest) - case 596: //Transport: Naglfar - case 610: //Transport: Tirisfal to Vengeance Landing - case 612: //Transport: Menethil to Valgarde - case 613: //Transport: Orgrimmar to Warsong Hold - case 614: //Transport: Stormwind to Valiance Keep - case 620: //Transport: Moa'ki to Unu'pe - case 621: //Transport: Moa'ki to Kamagua - case 622: //Transport: Orgrim's Hammer - case 623: //Transport: The Skybreaker - case 641: //Transport: Alliance Airship BG - case 642: //Transport: Horde Airship BG - case 647: //Transport: Orgrimmar to Thunder Bluff - case 672: //Transport: The Skybreaker (Icecrown Citadel Raid) - case 673: //Transport: Orgrim's Hammer (Icecrown Citadel Raid) - case 712: //Transport: The Skybreaker (IC Dungeon) - case 713: //Transport: Orgrim's Hammer (IC Dungeon) - case 718: //Transport: The Mighty Wind (Icecrown Citadel Raid) - case 766: // Transport 2033864 - case 767: // Transport 2033865 - case 747: // Transport 203732 - case 762: // Transport 203861 - case 763: // Transport 203862 - case 1172: // Transport_Siege_of_Orgrimmar_Alliance - case 1173: // Transport_Siege_of_Orgrimmar_Horde - case 662: // Transport197195 - case 674: // Transport197349-2 - case 738: // Transport200100 - case 739: // Transport200101 - case 740: // Transport200102 - case 741: // Transport200103 - case 742: // Transport203729 - case 743: // Transport203730 - case 748: // Transport203858 - case 749: // Transport203859 - case 750: // Transport203860 - case 765: // Transport203863 - case 1132: // Transport218599 - case 1133: // Transport218600 - return; + case 369: //Transport: Deeprun Tram + case 607: //Transport: Strands of the Ancients + case 582: //Transport: Rut'theran to Auberdine + case 584: //Transport: Menethil to Theramore + case 586: //Transport: Exodar to Auberdine + case 587: //Transport: Feathermoon Ferry + case 588: //Transport: Menethil to Auberdine + case 589: //Transport: Orgrimmar to Grom'Gol + case 590: //Transport: Grom'Gol to Undercity + case 591: //Transport: Undercity to Orgrimmar + case 592: //Transport: Borean Tundra Test + case 593: //Transport: Booty Bay to Ratchet + case 594: //Transport: Howling Fjord Sister Mercy (Quest) + case 596: //Transport: Naglfar + case 610: //Transport: Tirisfal to Vengeance Landing + case 612: //Transport: Menethil to Valgarde + case 613: //Transport: Orgrimmar to Warsong Hold + case 614: //Transport: Stormwind to Valiance Keep + case 620: //Transport: Moa'ki to Unu'pe + case 621: //Transport: Moa'ki to Kamagua + case 622: //Transport: Orgrim's Hammer + case 623: //Transport: The Skybreaker + case 641: //Transport: Alliance Airship BG + case 642: //Transport: Horde Airship BG + case 647: //Transport: Orgrimmar to Thunder Bluff + case 672: //Transport: The Skybreaker (Icecrown Citadel Raid) + case 673: //Transport: Orgrim's Hammer (Icecrown Citadel Raid) + case 712: //Transport: The Skybreaker (IC Dungeon) + case 713: //Transport: Orgrim's Hammer (IC Dungeon) + case 718: //Transport: The Mighty Wind (Icecrown Citadel Raid) + case 766: // Transport 2033864 + case 767: // Transport 2033865 + case 747: // Transport 203732 + case 762: // Transport 203861 + case 763: // Transport 203862 + case 1172: // Transport_Siege_of_Orgrimmar_Alliance + case 1173: // Transport_Siege_of_Orgrimmar_Horde + case 662: // Transport197195 + case 674: // Transport197349-2 + case 738: // Transport200100 + case 739: // Transport200101 + case 740: // Transport200102 + case 741: // Transport200103 + case 742: // Transport203729 + case 743: // Transport203730 + case 748: // Transport203858 + case 749: // Transport203859 + case 750: // Transport203860 + case 765: // Transport203863 + case 1132: // Transport218599 + case 1133: // Transport218600 + return; } } } + void AnticheatMgr::BGLogger(Player* player, AnticheatData& data) { uint32 latency = 0; From 181be46f1c27b43f40e21026e9085c9c8d8cdbaf Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sat, 25 Nov 2023 09:16:18 -0500 Subject: [PATCH 12/23] update (anticheat): include cleanup --- src/server/scripts/Commands/cs_anticheat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/scripts/Commands/cs_anticheat.cpp b/src/server/scripts/Commands/cs_anticheat.cpp index 66a584863bc..c825886d9ff 100644 --- a/src/server/scripts/Commands/cs_anticheat.cpp +++ b/src/server/scripts/Commands/cs_anticheat.cpp @@ -9,7 +9,7 @@ #include "Player.h" #include "ScriptMgr.h" #include "SpellAuras.h" -#include "../../game/Anticheat/AnticheatMgr.h" +#include "AnticheatMgr.h" enum Spells { From db8fc8712b6e1c6923b1328c8d159de87dd38617 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sat, 25 Nov 2023 09:18:13 -0500 Subject: [PATCH 13/23] update (anticehat): static clean up --- src/server/game/Anticheat/AnticheatMgr.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h index 09af2748abf..128af0ea772 100644 --- a/src/server/game/Anticheat/AnticheatMgr.h +++ b/src/server/game/Anticheat/AnticheatMgr.h @@ -76,11 +76,6 @@ class AnticheatMgr public: friend class ACE_Singleton; - static AnticheatMgr *instance() - { - static AnticheatMgr _instance; - return &_instance; - } void SetAllowedMovement(Player* player, bool); void StartHackDetection(Player* player, MovementInfo &movementInfo, uint32 opcode); void SavePlayerData(Player* player); From c5a43710ff4d8fb2f5e10c0f76630def0472b3e9 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sat, 25 Nov 2023 09:24:58 -0500 Subject: [PATCH 14/23] update (anticheat): Revert define change --- src/server/scripts/Commands/cs_anticheat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/scripts/Commands/cs_anticheat.cpp b/src/server/scripts/Commands/cs_anticheat.cpp index c825886d9ff..66a584863bc 100644 --- a/src/server/scripts/Commands/cs_anticheat.cpp +++ b/src/server/scripts/Commands/cs_anticheat.cpp @@ -9,7 +9,7 @@ #include "Player.h" #include "ScriptMgr.h" #include "SpellAuras.h" -#include "AnticheatMgr.h" +#include "../../game/Anticheat/AnticheatMgr.h" enum Spells { From e95afa0ba3f4d974d8faeb71289f144b8bb0f37e Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sat, 25 Nov 2023 09:38:05 -0500 Subject: [PATCH 15/23] update (anticheat)L cmake cmd fix --- src/server/scripts/CMakeLists.txt | 1 + src/server/scripts/Commands/cs_anticheat.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index 3ac24d8f530..30fc8811eb8 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -103,6 +103,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/game/AI/CoreAI ${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI ${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts + ${CMAKE_SOURCE_DIR}/src/server/game/Anticheat ${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse ${CMAKE_SOURCE_DIR}/src/server/game/Battlefield ${CMAKE_SOURCE_DIR}/src/server/game/Battlefield/Zones diff --git a/src/server/scripts/Commands/cs_anticheat.cpp b/src/server/scripts/Commands/cs_anticheat.cpp index 66a584863bc..c825886d9ff 100644 --- a/src/server/scripts/Commands/cs_anticheat.cpp +++ b/src/server/scripts/Commands/cs_anticheat.cpp @@ -9,7 +9,7 @@ #include "Player.h" #include "ScriptMgr.h" #include "SpellAuras.h" -#include "../../game/Anticheat/AnticheatMgr.h" +#include "AnticheatMgr.h" enum Spells { From 9a03203c24ee7635a5604cb3e086eeafc9c3fc93 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Sun, 26 Nov 2023 09:41:21 -0500 Subject: [PATCH 16/23] update (anticheat): Parole gps correction --- src/server/scripts/Commands/cs_anticheat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/scripts/Commands/cs_anticheat.cpp b/src/server/scripts/Commands/cs_anticheat.cpp index c825886d9ff..388bca361dd 100644 --- a/src/server/scripts/Commands/cs_anticheat.cpp +++ b/src/server/scripts/Commands/cs_anticheat.cpp @@ -240,7 +240,7 @@ class anticheat_commandscript : public CommandScript if (target->getRace() == RACE_PANDAREN_NEUTRAL) { target->TeleportTo(860, 1470.96f, 3466.06f, 181.63f, 2.78f);//Shang Xi Training Grounds - target->SetHomebind(Nloc, 5834);// Orgrimmar Homebind location + target->SetHomebind(Nloc, 5834);// Shang Xi Training Grounds Homebind location } if (target->GetTeamId() == TEAM_ALLIANCE && target->getRace() != RACE_PANDAREN_NEUTRAL) { @@ -249,7 +249,7 @@ class anticheat_commandscript : public CommandScript } if (target->GetTeamId() == TEAM_HORDE && target->getRace() != RACE_PANDAREN_NEUTRAL) { - target->TeleportTo(1, 1569.59f, -4397.63f, 7.7f, 0.54f);//Orgrimmar + target->TeleportTo(1, 1569.59f, -4397.63f, 16.06f, 0.54f);//Orgrimmar target->SetHomebind(Hloc, 1653);// Orgrimmar Homebind location } target->RemoveAura(FREEZE);// remove shackles From 6c38c923c5a7c76f9bd472e21da2a3d6475e4aa9 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Tue, 28 Nov 2023 08:24:42 -0500 Subject: [PATCH 17/23] update (anticheat): Added case default --- src/server/game/Anticheat/AnticheatMgr.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index 710fe85c225..a742e38c147 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -220,6 +220,8 @@ void AnticheatMgr::MapSpeedTeleExemption(Player* player) case 1132: // Transport218599 case 1133: // Transport218600 return; + default: + break; } } } @@ -510,6 +512,8 @@ void AnticheatMgr::JumpHackDetection(Player* player, MovementInfo& movementInfo, case 6724: //Backbreaker Bay case 6725: //Greymist Firth return; + default: + break; } } @@ -567,8 +571,10 @@ void AnticheatMgr::TeleportPlaneHackDetection(Player* player, MovementInfo& move { switch (player->GetAreaId()) { - case 4273: //Celestial Planetarium Observer Battle has a narrow path that false flags - return; + case 4273: //Celestial Planetarium Observer Battle has a narrow path that false flags + return; + default: + break; } } @@ -782,6 +788,8 @@ void AnticheatMgr::BGStartExploit(Player* player, MovementInfo movementInfo, Ant break; } return; + default: + break; } } From cc99ea7cd09f3fd554f377b8ae7643a3ebdc4375 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Thu, 30 Nov 2023 10:11:43 -0500 Subject: [PATCH 18/23] update (anticheat): Twin Peaks BG --- src/server/game/Anticheat/AnticheatMgr.cpp | 28 +++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index a742e38c147..8b03b4ba867 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -141,7 +141,10 @@ void AnticheatMgr::StartHackDetection(Player* player, MovementInfo& movementInfo SpeedHackDetection(player, movementInfo, *data); FlyHackDetection(player, movementInfo, *data); - TeleportHackDetection(player, movementInfo, *data); + if (!player->HasAtLoginFlag(AT_LOGIN_FIRST)) + { + TeleportHackDetection(player, movementInfo, *data); + } if (movementInfo.HasMovementFlag(MOVEMENTFLAG_WATERWALKING)) { WalkOnWaterHackDetection(player, movementInfo, *data); @@ -787,6 +790,29 @@ void AnticheatMgr::BGStartExploit(Player* player, MovementInfo movementInfo, Ant } break; } + case 726: // Twin Peaks + { + if (Battleground* bg = player->GetBattleground()) + { + if (bg->GetStatus() == STATUS_WAIT_JOIN) + { + // Outside of starting area before BG has started. + if ((player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionX() < 2075.00f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() < 154.30f) || + (player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionY() > 222.80f)) + { + BGLogger(player, data); + } + if ((player->GetTeamId() == TEAM_ALLIANCE && movementInfo.pos.GetPositionX() < 314.00f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() < 314.0f) || + (player->GetTeamId() == TEAM_HORDE && movementInfo.pos.GetPositionY() > 380.0f)) + { + BGLogger(player, data); + } + } + } + break; + } return; default: break; From 83e023dab0cd1af156b69b0144f4f8c031131df3 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Mon, 18 Dec 2023 13:29:19 -0500 Subject: [PATCH 19/23] update (anticheat): Replace case swith a better if --- src/server/game/Anticheat/AnticheatMgr.cpp | 75 ++++------------------ src/server/game/Anticheat/AnticheatMgr.h | 2 +- 2 files changed, 14 insertions(+), 63 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index 8b03b4ba867..8aada3fdd32 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -164,68 +164,19 @@ void AnticheatMgr::StartHackDetection(Player* player, MovementInfo& movementInfo data->lastOpcode = opcode; } -void AnticheatMgr::MapSpeedTeleExemption(Player* player) +void AnticheatMgr::MapSpeedTeleExemption(Player* player, MovementInfo& movementInfo) { - // We exempt all transports found in 548 to prevent false tele hack hits - if (player->GetMapId()) + // The anticheat is disabled on transports, so we need to be sure that the player is indeed on a transport. + Unit* mover = player->m_mover; + GameObject* transportGobj = mover->GetMap()->GetGameObject(movementInfo.transport.guid); + float maxDist2d = 70.0f; // Transports usually dont go far away. + if (player->GetMapId() == 369) // Deeprun tram { - switch (player->GetMapId()) - { - case 369: //Transport: Deeprun Tram - case 607: //Transport: Strands of the Ancients - case 582: //Transport: Rut'theran to Auberdine - case 584: //Transport: Menethil to Theramore - case 586: //Transport: Exodar to Auberdine - case 587: //Transport: Feathermoon Ferry - case 588: //Transport: Menethil to Auberdine - case 589: //Transport: Orgrimmar to Grom'Gol - case 590: //Transport: Grom'Gol to Undercity - case 591: //Transport: Undercity to Orgrimmar - case 592: //Transport: Borean Tundra Test - case 593: //Transport: Booty Bay to Ratchet - case 594: //Transport: Howling Fjord Sister Mercy (Quest) - case 596: //Transport: Naglfar - case 610: //Transport: Tirisfal to Vengeance Landing - case 612: //Transport: Menethil to Valgarde - case 613: //Transport: Orgrimmar to Warsong Hold - case 614: //Transport: Stormwind to Valiance Keep - case 620: //Transport: Moa'ki to Unu'pe - case 621: //Transport: Moa'ki to Kamagua - case 622: //Transport: Orgrim's Hammer - case 623: //Transport: The Skybreaker - case 641: //Transport: Alliance Airship BG - case 642: //Transport: Horde Airship BG - case 647: //Transport: Orgrimmar to Thunder Bluff - case 672: //Transport: The Skybreaker (Icecrown Citadel Raid) - case 673: //Transport: Orgrim's Hammer (Icecrown Citadel Raid) - case 712: //Transport: The Skybreaker (IC Dungeon) - case 713: //Transport: Orgrim's Hammer (IC Dungeon) - case 718: //Transport: The Mighty Wind (Icecrown Citadel Raid) - case 766: // Transport 2033864 - case 767: // Transport 2033865 - case 747: // Transport 203732 - case 762: // Transport 203861 - case 763: // Transport 203862 - case 1172: // Transport_Siege_of_Orgrimmar_Alliance - case 1173: // Transport_Siege_of_Orgrimmar_Horde - case 662: // Transport197195 - case 674: // Transport197349-2 - case 738: // Transport200100 - case 739: // Transport200101 - case 740: // Transport200102 - case 741: // Transport200103 - case 742: // Transport203729 - case 743: // Transport203730 - case 748: // Transport203858 - case 749: // Transport203859 - case 750: // Transport203860 - case 765: // Transport203863 - case 1132: // Transport218599 - case 1133: // Transport218600 - return; - default: - break; - } + maxDist2d = 3000.0f; + } + if (transportGobj && (transportGobj->IsTransport() || transportGobj->IsWithinDist(player, maxDist2d, false))) + { + return; } } @@ -245,7 +196,7 @@ void AnticheatMgr::SpeedHackDetection(Player* player, MovementInfo& movementInfo if (player) { - MapSpeedTeleExemption(player); + MapSpeedTeleExemption(player, movementInfo); } if (player->HasAura(1850) /*Dash*/ || player->HasAuraType(SPELL_AURA_FEATHER_FALL) || player->HasAuraType(SPELL_AURA_SAFE_FALL)) @@ -388,7 +339,7 @@ void AnticheatMgr::TeleportHackDetection(Player* player, MovementInfo movementIn if (player) { - MapSpeedTeleExemption(player); + MapSpeedTeleExemption(player, movementInfo); } /* Please work */ diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h index 128af0ea772..07d3b138e8a 100644 --- a/src/server/game/Anticheat/AnticheatMgr.h +++ b/src/server/game/Anticheat/AnticheatMgr.h @@ -95,7 +95,7 @@ class AnticheatMgr void ResetDailyReportStates(); private: - void MapSpeedTeleExemption(Player* player); + void MapSpeedTeleExemption(Player* player, MovementInfo& movementInfo); void BGLogger(Player* player, AnticheatData& data); void SpeedHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data); void FlyHackDetection(Player* player, MovementInfo &movementInfo, AnticheatData& data); From 6cbf03826b45dbbae36ae8ee73134fd47b542d2c Mon Sep 17 00:00:00 2001 From: M'Dic Date: Fri, 5 Jan 2024 17:15:56 -0500 Subject: [PATCH 20/23] update (anticheat): False hits for select elevators --- src/server/game/Anticheat/AnticheatMgr.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index 8aada3fdd32..00ef12425b7 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -167,8 +167,7 @@ void AnticheatMgr::StartHackDetection(Player* player, MovementInfo& movementInfo void AnticheatMgr::MapSpeedTeleExemption(Player* player, MovementInfo& movementInfo) { // The anticheat is disabled on transports, so we need to be sure that the player is indeed on a transport. - Unit* mover = player->m_mover; - GameObject* transportGobj = mover->GetMap()->GetGameObject(movementInfo.transport.guid); + GameObject* transportGobj = player->GetMap()->GetGameObject(movementInfo.transport.guid); float maxDist2d = 70.0f; // Transports usually dont go far away. if (player->GetMapId() == 369) // Deeprun tram { @@ -448,6 +447,13 @@ void AnticheatMgr::JumpHackDetection(Player* player, MovementInfo& movementInfo, if (!distance2D) return; + // The anticheat is disabled on transports, so we need to be sure that the player is indeed on a transport. + GameObject* transportGobj = player->GetMap()->GetGameObject(movementInfo.transport.guid); + if (transportGobj && transportGobj->IsTransport()) + { + return; + } + if (!player->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY) && movementInfo.jump.zspeed < -10.0f) return; From 1637b18f3e10183ec5de6dcce280d764f58e5494 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Mon, 19 Feb 2024 14:39:00 -0500 Subject: [PATCH 21/23] add (anticheat\log): add logging this is to address race condition when mapupdate threads are set higher then 2 in the wold conf --- src/server/game/Anticheat/AnticheatMgr.cpp | 2 +- src/server/scripts/Commands/cs_anticheat.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index 00ef12425b7..4539f218d21 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -981,7 +981,7 @@ void AnticheatMgr::BuildReport(Player* player, AnticheatData& data, uint8 report player->TeleportTo(loc);// we defined loc as the jail location so we tele them there player->SetHomebind(loc, 876);// GM Jail Homebind location player->CastSpell(player, FREEZE);// freeze him in place to ensure no exploit happens for jail break attempt - + SF_LOG_INFO("anticheat", "AnticheatMgr:: Jailing player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); if (Aura* dungdesert = player->AddAura(LFG_SPELL_DUNGEON_DESERTER,player))// LFG_SPELL_DUNGEON_DESERTER { dungdesert->SetDuration(-1); diff --git a/src/server/scripts/Commands/cs_anticheat.cpp b/src/server/scripts/Commands/cs_anticheat.cpp index 388bca361dd..3b550301cfe 100644 --- a/src/server/scripts/Commands/cs_anticheat.cpp +++ b/src/server/scripts/Commands/cs_anticheat.cpp @@ -5,6 +5,7 @@ #include "Chat.h" #include "Language.h" +#include "Log.h" #include "ObjectMgr.h" #include "Player.h" #include "ScriptMgr.h" @@ -207,7 +208,7 @@ class anticheat_commandscript : public CommandScript target->TeleportTo(jailLoc); target->SetHomebind(jailLoc, 876);// GM Jail Homebind location target->CastSpell(target, FREEZE);// Freeze him in place to ensure no exploit happens for jail break attempt - + SF_LOG_INFO("anticheat", "AnticheatMgr:: Jail command used on player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); if (Aura* dungdesert = target->AddAura(LFG_SPELL_DUNGEON_DESERTER, target))// LFG_SPELL_DUNGEON_DESERTER { dungdesert->SetDuration(-1); @@ -252,6 +253,7 @@ class anticheat_commandscript : public CommandScript target->TeleportTo(1, 1569.59f, -4397.63f, 16.06f, 0.54f);//Orgrimmar target->SetHomebind(Hloc, 1653);// Orgrimmar Homebind location } + SF_LOG_INFO("anticheat", "AnticheatMgr:: Parole command used on player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); target->RemoveAura(FREEZE);// remove shackles target->RemoveAura(LFG_SPELL_DUNGEON_DESERTER);// LFG_SPELL_DUNGEON_DESERTER target->RemoveAura(BG_SPELL_DESERTER);// BG_SPELL_DESERTER From 147ff4d70cc9ceeef47aa7d25535b0fce38427a1 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Tue, 20 Feb 2024 09:08:57 -0500 Subject: [PATCH 22/23] update (anticheat): Reorder this works better for the race condition --- src/server/game/Anticheat/AnticheatMgr.cpp | 12 ++++++------ src/server/scripts/Commands/cs_anticheat.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index 4539f218d21..83b1f0660c9 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -976,12 +976,7 @@ void AnticheatMgr::BuildReport(Player* player, AnticheatData& data, uint8 report if (data.totalReports > sWorld->getIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_JAILS)) { SF_LOG_INFO("anticheat", "AnticheatMgr:: Reports reached assigned threshhold and counteracted by jailing player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); - // This is where they end up going shaw shank redemption style - WorldLocation loc = WorldLocation(1, 16226.5f, 16403.6f, -64.5f, 3.2f);// GM Jail Location - player->TeleportTo(loc);// we defined loc as the jail location so we tele them there - player->SetHomebind(loc, 876);// GM Jail Homebind location - player->CastSpell(player, FREEZE);// freeze him in place to ensure no exploit happens for jail break attempt - SF_LOG_INFO("anticheat", "AnticheatMgr:: Jailing player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); + if (Aura* dungdesert = player->AddAura(LFG_SPELL_DUNGEON_DESERTER,player))// LFG_SPELL_DUNGEON_DESERTER { dungdesert->SetDuration(-1); @@ -994,6 +989,11 @@ void AnticheatMgr::BuildReport(Player* player, AnticheatData& data, uint8 report { silent->SetDuration(-1); } + // This is where they end up going shaw shank redemption style + WorldLocation loc = WorldLocation(1, 16226.5f, 16403.6f, -64.5f, 3.2f);// GM Jail Location + player->TeleportTo(loc);// we defined loc as the jail location so we tele them there + player->SetHomebind(loc, 876);// GM Jail Homebind location + player->CastSpell(player, FREEZE);// freeze him in place to ensure no exploit happens for jail break attempt } } } diff --git a/src/server/scripts/Commands/cs_anticheat.cpp b/src/server/scripts/Commands/cs_anticheat.cpp index 3b550301cfe..d6dcd7a1a92 100644 --- a/src/server/scripts/Commands/cs_anticheat.cpp +++ b/src/server/scripts/Commands/cs_anticheat.cpp @@ -5,7 +5,6 @@ #include "Chat.h" #include "Language.h" -#include "Log.h" #include "ObjectMgr.h" #include "Player.h" #include "ScriptMgr.h" @@ -204,11 +203,8 @@ class anticheat_commandscript : public CommandScript if (!handler->extractPlayerTarget((char*)args, &target, NULL, &playerName)) return false; - WorldLocation jailLoc = WorldLocation(1, 16226.5f, 16403.6f, -64.5f, 3.2f);// GM Jail Location - target->TeleportTo(jailLoc); - target->SetHomebind(jailLoc, 876);// GM Jail Homebind location target->CastSpell(target, FREEZE);// Freeze him in place to ensure no exploit happens for jail break attempt - SF_LOG_INFO("anticheat", "AnticheatMgr:: Jail command used on player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); + if (Aura* dungdesert = target->AddAura(LFG_SPELL_DUNGEON_DESERTER, target))// LFG_SPELL_DUNGEON_DESERTER { dungdesert->SetDuration(-1); @@ -222,6 +218,10 @@ class anticheat_commandscript : public CommandScript silent->SetDuration(-1); } + WorldLocation jailLoc = WorldLocation(1, 16226.5f, 16403.6f, -64.5f, 3.2f);// GM Jail Location + target->TeleportTo(jailLoc); + target->SetHomebind(jailLoc, 876);// GM Jail Homebind location + return true; } static bool HandleAnticheatParoleCommand(ChatHandler* handler, char const* args) @@ -253,7 +253,7 @@ class anticheat_commandscript : public CommandScript target->TeleportTo(1, 1569.59f, -4397.63f, 16.06f, 0.54f);//Orgrimmar target->SetHomebind(Hloc, 1653);// Orgrimmar Homebind location } - SF_LOG_INFO("anticheat", "AnticheatMgr:: Parole command used on player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); + target->RemoveAura(FREEZE);// remove shackles target->RemoveAura(LFG_SPELL_DUNGEON_DESERTER);// LFG_SPELL_DUNGEON_DESERTER target->RemoveAura(BG_SPELL_DESERTER);// BG_SPELL_DESERTER From fa90c0f73e4ed4b22f78622d5c9a9b797afb29d8 Mon Sep 17 00:00:00 2001 From: M'Dic Date: Tue, 20 Feb 2024 09:12:06 -0500 Subject: [PATCH 23/23] update (anticheat): :Reorder --- src/server/game/Anticheat/AnticheatMgr.cpp | 6 +++--- src/server/scripts/Commands/cs_anticheat.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp index 83b1f0660c9..cc8dbd3c9c4 100644 --- a/src/server/game/Anticheat/AnticheatMgr.cpp +++ b/src/server/game/Anticheat/AnticheatMgr.cpp @@ -976,7 +976,7 @@ void AnticheatMgr::BuildReport(Player* player, AnticheatData& data, uint8 report if (data.totalReports > sWorld->getIntConfig(WorldIntConfigs::CONFIG_ANTICHEAT_MAX_REPORTS_FOR_JAILS)) { SF_LOG_INFO("anticheat", "AnticheatMgr:: Reports reached assigned threshhold and counteracted by jailing player %s (GUID %u)", player->GetName().c_str(), player->GetGUID()); - + player->CastSpell(player, FREEZE);// freeze him in place to ensure no exploit happens for jail break attempt if (Aura* dungdesert = player->AddAura(LFG_SPELL_DUNGEON_DESERTER,player))// LFG_SPELL_DUNGEON_DESERTER { dungdesert->SetDuration(-1); @@ -991,9 +991,9 @@ void AnticheatMgr::BuildReport(Player* player, AnticheatData& data, uint8 report } // This is where they end up going shaw shank redemption style WorldLocation loc = WorldLocation(1, 16226.5f, 16403.6f, -64.5f, 3.2f);// GM Jail Location - player->TeleportTo(loc);// we defined loc as the jail location so we tele them there player->SetHomebind(loc, 876);// GM Jail Homebind location - player->CastSpell(player, FREEZE);// freeze him in place to ensure no exploit happens for jail break attempt + player->TeleportTo(loc);// we defined loc as the jail location so we tele them there + } } } diff --git a/src/server/scripts/Commands/cs_anticheat.cpp b/src/server/scripts/Commands/cs_anticheat.cpp index d6dcd7a1a92..4c83685f669 100644 --- a/src/server/scripts/Commands/cs_anticheat.cpp +++ b/src/server/scripts/Commands/cs_anticheat.cpp @@ -219,8 +219,8 @@ class anticheat_commandscript : public CommandScript } WorldLocation jailLoc = WorldLocation(1, 16226.5f, 16403.6f, -64.5f, 3.2f);// GM Jail Location - target->TeleportTo(jailLoc); target->SetHomebind(jailLoc, 876);// GM Jail Homebind location + target->TeleportTo(jailLoc); return true; }