More config options + stricter fly/waterwalk hack detects

This commit is contained in:
3ndos
2016-12-07 18:15:15 -05:00
parent 38bca106c9
commit 6ebd04b452
3 changed files with 306 additions and 277 deletions

View File

@@ -9,6 +9,8 @@
# 0 - (Disabled)
Anticheat.Enabled = 1
#Enable detection for GM accounts
Anticheat.EnabledOnGmAccounts = 0
# Anticheat.ReportsForIngameWarnings
# Description: How many reports the player must have to notify to GameMasters ingame when he generates a new report.
@@ -26,7 +28,13 @@ Anticheat.LoginMessage = 1
# Description: It represents which detections are enabled.
# Default 1 (climbhack = 0 by default)
Anticheat.DetectFlyHack = 1
Anticheat.DetectWaterWalk = 1
#Checks moveflag ascending (may give flase positives)
Anticheat.StricterFlyHackCheck = 0
#kick option for first detect on flyhack, if false positives disable(disabled by default)
Anticheat.KickPlayerFlyHack = 0
Anticheat.DetectWaterWalkHack = 1
#kick option for first detect on waterwalkhack, if false positives disable(disabled by default)
Anticheat.KickPlayerWaterWalkHack = 0
Anticheat.DetectJumpHack = 1
Anticheat.DetectTelePlaneHack = 1
Anticheat.DetectSpeedHack = 1

View File

@@ -28,7 +28,7 @@ AnticheatMgr::~AnticheatMgr()
m_Players.clear();
}
void AnticheatMgr::JumpHackDetection(Player* player, MovementInfo /* movementInfo */,uint32 opcode)
void AnticheatMgr::JumpHackDetection(Player* player, MovementInfo /* movementInfo */, uint32 opcode)
{
if (!sConfigMgr->GetBoolDefault("Anticheat.DetectJumpHack", true))
return;
@@ -37,18 +37,19 @@ void AnticheatMgr::JumpHackDetection(Player* player, MovementInfo /* movementInf
if (m_Players[key].GetLastOpcode() == MSG_MOVE_JUMP && opcode == MSG_MOVE_JUMP)
{
BuildReport(player,JUMP_HACK_REPORT);
sLog->outString( "AnticheatMgr:: Jump-Hack detected player GUID (low) %u",player->GetGUIDLow());
BuildReport(player, JUMP_HACK_REPORT);
sLog->outString("AnticheatMgr:: Jump-Hack detected player %s (%u)", player->GetName(), player->GetGUIDLow());
}
}
void AnticheatMgr::WalkOnWaterHackDetection(Player* player, MovementInfo /* movementInfo */)
void AnticheatMgr::WalkOnWaterHackDetection(Player* player, MovementInfo movementInfo)
{
if (!sConfigMgr->GetBoolDefault("Anticheat.DetectWaterWalk", true))
if (!sConfigMgr->GetBoolDefault("Anticheat.DetectWaterWalkHack", true))
return;
uint32 key = player->GetGUIDLow();
if (!m_Players[key].GetLastMovementInfo().HasMovementFlag(MOVEMENTFLAG_WATERWALKING))
/* Thanks to @LilleCarl */
if (!m_Players[key].GetLastMovementInfo().HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !movementInfo.HasMovementFlag(MOVEMENTFLAG_WATERWALKING))
return;
// if we are a ghost we can walk on water
@@ -59,27 +60,42 @@ void AnticheatMgr::WalkOnWaterHackDetection(Player* player, MovementInfo /* move
player->HasAuraType(SPELL_AURA_SAFE_FALL) ||
player->HasAuraType(SPELL_AURA_WATER_WALK))
return;
sLog->outString( "AnticheatMgr:: Walk on Water - Hack detected player GUID (low) %u",player->GetGUIDLow());
BuildReport(player,WALK_WATER_HACK_REPORT);
if (sConfigMgr->GetBoolDefault("Anticheat.KickPlayerWaterWalkHack", false))
{
/* cheap hack for now, look at "applyfortargets" later*/
/*player->AddAura(SPELL_AURA_WATER_WALK, player);
player->RemoveAura(SPELL_AURA_WATER_WALK);*/
//cba to double check this, just adding a kick option
player->GetSession()->KickPlayer(true);
sLog->outString("AnticheatMgr:: Walk on Water - Hack detected and counteracted by kicking player %s (%u)", player->GetName(), player->GetGUIDLow());
}
else {
sLog->outString("AnticheatMgr:: Walk on Water - Hack detected player %s (%u)", player->GetName(), player->GetGUIDLow());
}
BuildReport(player, WALK_WATER_HACK_REPORT);
}
void AnticheatMgr::FlyHackDetection(Player* player, MovementInfo /* movementInfo */)
void AnticheatMgr::FlyHackDetection(Player* player, MovementInfo movementInfo)
{
if (!sConfigMgr->GetBoolDefault("Anticheat.DetectFlyHack", true))
return;
uint32 key = player->GetGUIDLow();
if (!m_Players[key].GetLastMovementInfo().HasMovementFlag(MOVEMENTFLAG_FLYING))
if (player->HasAuraType(SPELL_AURA_FLY) || player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || player->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED))//overkill but wth
return;
if (player->HasAuraType(SPELL_AURA_FLY) ||
player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) ||
player->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED))
/*Thanks to @LilleCarl for info to check extra flag*/
bool stricterChecks = true;
if (sConfigMgr->GetBoolDefault("Anticheat.StricterFlyHackCheck", false))
stricterChecks = !(movementInfo.HasMovementFlag(MOVEMENTFLAG_ASCENDING) && !player->IsInWater());
if (!movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY) && !movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING) && stricterChecks)
return;
sLog->outString( "AnticheatMgr:: Fly-Hack detected player GUID (low) %u",player->GetGUIDLow());
if (sConfigMgr->GetBoolDefault("Anticheat.KickPlayerFlyHack", false))
{
sLog->outString("AnticheatMgr:: Fly-Hack detected and counteracted by kicking player %s (%u)", player->GetName(), player->GetGUIDLow());
player->GetSession()->KickPlayer(true);
}else
sLog->outString( "AnticheatMgr:: Fly-Hack detected player %s (%u)", player->GetName(), player->GetGUIDLow());
BuildReport(player,FLY_HACK_REPORT);
}
@@ -108,8 +124,8 @@ void AnticheatMgr::TeleportPlaneHackDetection(Player* player, MovementInfo movem
// we are not really walking there
if (z_diff > 1.0f)
{
sLog->outString( "AnticheatMgr:: Teleport To Plane - Hack detected player GUID (low) %u",player->GetGUIDLow());
BuildReport(player,TELEPORT_PLANE_HACK_REPORT);
sLog->outString("AnticheatMgr:: Teleport To Plane - Hack detected player %s (%u)", player->GetName(), player->GetGUIDLow());
BuildReport(player, TELEPORT_PLANE_HACK_REPORT);
}
}
@@ -130,12 +146,12 @@ void AnticheatMgr::StartHackDetection(Player* player, MovementInfo movementInfo,
return;
}
SpeedHackDetection(player,movementInfo);
FlyHackDetection(player,movementInfo);
WalkOnWaterHackDetection(player,movementInfo);
JumpHackDetection(player,movementInfo,opcode);
SpeedHackDetection(player, movementInfo);
FlyHackDetection(player, movementInfo);
WalkOnWaterHackDetection(player, movementInfo);
JumpHackDetection(player, movementInfo, opcode);
TeleportPlaneHackDetection(player, movementInfo);
ClimbHackDetection(player,movementInfo,opcode);
ClimbHackDetection(player, movementInfo, opcode);
m_Players[key].SetLastMovementInfo(movementInfo);
m_Players[key].SetLastOpcode(opcode);
@@ -165,16 +181,16 @@ void AnticheatMgr::ClimbHackDetection(Player *player, MovementInfo movementInfo,
float deltaZ = fabs(playerPos.GetPositionZ() - movementInfo.pos.GetPositionZ());
float deltaXY = movementInfo.pos.GetExactDist2d(&playerPos);
float angle = Position::NormalizeOrientation(tan(deltaZ/deltaXY));
float angle = Position::NormalizeOrientation(tan(deltaZ / deltaXY));
if (angle > CLIMB_ANGLE)
{
sLog->outString( "AnticheatMgr:: Climb-Hack detected player GUID (low) %u", player->GetGUIDLow());
BuildReport(player,CLIMB_HACK_REPORT);
sLog->outString("AnticheatMgr:: Climb-Hack detected player %s (%u)", player->GetName(), player->GetGUIDLow());
BuildReport(player, CLIMB_HACK_REPORT);
}
}
void AnticheatMgr::SpeedHackDetection(Player* player,MovementInfo movementInfo)
void AnticheatMgr::SpeedHackDetection(Player* player, MovementInfo movementInfo)
{
if (!sConfigMgr->GetBoolDefault("Anticheat.DetectSpeedHack", true))
return;
@@ -205,7 +221,7 @@ void AnticheatMgr::SpeedHackDetection(Player* player,MovementInfo movementInfo)
uint32 speedRate = (uint32)(player->GetSpeed(UnitMoveType(moveType)) + movementInfo.jump.xyspeed);
// how long the player took to move to here.
uint32 timeDiff = getMSTimeDiff(m_Players[key].GetLastMovementInfo().time,movementInfo.time);
uint32 timeDiff = getMSTimeDiff(m_Players[key].GetLastMovementInfo().time, movementInfo.time);
if (!timeDiff)
timeDiff = 1;
@@ -216,8 +232,8 @@ void AnticheatMgr::SpeedHackDetection(Player* player,MovementInfo movementInfo)
// we did the (uint32) cast to accept a margin of tolerance
if (clientSpeedRate > speedRate)
{
BuildReport(player,SPEED_HACK_REPORT);
sLog->outString( "AnticheatMgr:: Speed-Hack detected player GUID (low) %u",player->GetGUIDLow());
BuildReport(player, SPEED_HACK_REPORT);
sLog->outString("AnticheatMgr:: Speed-Hack detected player %s (%u)", player->GetName(), player->GetGUIDLow());
}
}
@@ -225,10 +241,10 @@ void AnticheatMgr::SpeedHackDetection(Player* player,MovementInfo movementInfo)
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());
CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u", player->GetGUIDLow());
// we initialize the pos of lastMovementPosition var.
m_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());
m_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)
m_Players[player->GetGUIDLow()].SetDailyReportState(true);
@@ -239,14 +255,14 @@ 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());
CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u", player->GetGUIDLow());
// Delete not needed data from the memory.
m_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,creation_time) VALUES (%u,%f,%u,%u,%u,%u,%u,%u,%u,%u);",player->GetGUIDLow(),m_Players[player->GetGUIDLow()].GetAverage(),m_Players[player->GetGUIDLow()].GetTotalReports(), m_Players[player->GetGUIDLow()].GetTypeReports(SPEED_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(FLY_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(JUMP_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(WALK_WATER_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(CLIMB_HACK_REPORT),m_Players[player->GetGUIDLow()].GetCreationTime());
CharacterDatabase.PExecute("REPLACE INTO players_reports_status (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,creation_time) VALUES (%u,%f,%u,%u,%u,%u,%u,%u,%u,%u);", player->GetGUIDLow(), m_Players[player->GetGUIDLow()].GetAverage(), m_Players[player->GetGUIDLow()].GetTotalReports(), m_Players[player->GetGUIDLow()].GetTypeReports(SPEED_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(FLY_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(JUMP_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(WALK_WATER_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(CLIMB_HACK_REPORT), m_Players[player->GetGUIDLow()].GetCreationTime());
}
uint32 AnticheatMgr::GetTotalReports(uint32 lowGUID)
@@ -272,7 +288,7 @@ bool AnticheatMgr::MustCheckTempReports(uint8 type)
return true;
}
void AnticheatMgr::BuildReport(Player* player,uint8 reportType)
void AnticheatMgr::BuildReport(Player* player, uint8 reportType)
{
uint32 key = player->GetGUIDLow();
@@ -281,18 +297,19 @@ void AnticheatMgr::BuildReport(Player* player,uint8 reportType)
uint32 actualTime = getMSTime();
if (!m_Players[key].GetTempReportsTimer(reportType))
m_Players[key].SetTempReportsTimer(actualTime,reportType);
m_Players[key].SetTempReportsTimer(actualTime, reportType);
if (getMSTimeDiff(m_Players[key].GetTempReportsTimer(reportType),actualTime) < 3000)
if (getMSTimeDiff(m_Players[key].GetTempReportsTimer(reportType), actualTime) < 3000)
{
m_Players[key].SetTempReports(m_Players[key].GetTempReports(reportType)+1,reportType);
m_Players[key].SetTempReports(m_Players[key].GetTempReports(reportType) + 1, reportType);
if (m_Players[key].GetTempReports(reportType) < 3)
return;
} else
}
else
{
m_Players[key].SetTempReportsTimer(actualTime,reportType);
m_Players[key].SetTempReports(1,reportType);
m_Players[key].SetTempReportsTimer(actualTime, reportType);
m_Players[key].SetTempReports(1, reportType);
return;
}
}
@@ -302,12 +319,12 @@ void AnticheatMgr::BuildReport(Player* player,uint8 reportType)
m_Players[key].SetCreationTime(getMSTime());
// increasing total_reports
m_Players[key].SetTotalReports(m_Players[key].GetTotalReports()+1);
m_Players[key].SetTotalReports(m_Players[key].GetTotalReports() + 1);
// increasing specific cheat report
m_Players[key].SetTypeReports(reportType,m_Players[key].GetTypeReports(reportType)+1);
m_Players[key].SetTypeReports(reportType, m_Players[key].GetTypeReports(reportType) + 1);
// diff time for average calculation
uint32 diffTime = getMSTimeDiff(m_Players[key].GetCreationTime(),getMSTime()) / IN_MILLISECONDS;
uint32 diffTime = getMSTimeDiff(m_Players[key].GetCreationTime(), getMSTime()) / IN_MILLISECONDS;
if (diffTime > 0)
{
@@ -320,7 +337,7 @@ void AnticheatMgr::BuildReport(Player* player,uint8 reportType)
{
if (!m_Players[key].GetDailyReportState())
{
CharacterDatabase.PExecute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,creation_time) VALUES (%u,%f,%u,%u,%u,%u,%u,%u,%u,%u);",player->GetGUIDLow(),m_Players[player->GetGUIDLow()].GetAverage(),m_Players[player->GetGUIDLow()].GetTotalReports(), m_Players[player->GetGUIDLow()].GetTypeReports(SPEED_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(FLY_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(JUMP_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(WALK_WATER_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT),m_Players[player->GetGUIDLow()].GetTypeReports(CLIMB_HACK_REPORT),m_Players[player->GetGUIDLow()].GetCreationTime());
CharacterDatabase.PExecute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,creation_time) VALUES (%u,%f,%u,%u,%u,%u,%u,%u,%u,%u);", player->GetGUIDLow(), m_Players[player->GetGUIDLow()].GetAverage(), m_Players[player->GetGUIDLow()].GetTotalReports(), m_Players[player->GetGUIDLow()].GetTypeReports(SPEED_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(FLY_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(JUMP_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(WALK_WATER_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT), m_Players[player->GetGUIDLow()].GetTypeReports(CLIMB_HACK_REPORT), m_Players[player->GetGUIDLow()].GetCreationTime());
m_Players[key].SetDailyReportState(true);
}
}
@@ -329,8 +346,8 @@ void AnticheatMgr::BuildReport(Player* player,uint8 reportType)
{
// display warning at the center of the screen, hacky way?
std::string str = "";
str = "|cFFFFFC00[AC]|cFF00FFFF[|cFF60FF00" + std::string(player->GetName().c_str()) + "|cFF00FFFF] Possible cheater!";
WorldPacket data(SMSG_NOTIFICATION, (str.size()+1));
str = "|cFFFFFC00[Playername:|cFF00FFFF[|cFF60FF00" + std::string(player->GetName().c_str()) + "|cFF00FFFF] Possible cheater!";
WorldPacket data(SMSG_NOTIFICATION, (str.size() + 1));
data << str;
sWorld->SendGlobalGMMessage(&data);
}
@@ -346,7 +363,8 @@ void AnticheatMgr::AnticheatGlobalCommand(ChatHandler* handler)
{
handler->PSendSysMessage("No players found.");
return;
} else
}
else
{
handler->SendSysMessage("=============================");
handler->PSendSysMessage("Players with the lowest averages:");
@@ -359,7 +377,7 @@ void AnticheatMgr::AnticheatGlobalCommand(ChatHandler* handler)
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);
handler->PSendSysMessage("Player: %s Average: %f Total Reports: %u", player->GetName().c_str(), average, total_reports);
} while (resultDB->NextRow());
}
@@ -371,7 +389,8 @@ void AnticheatMgr::AnticheatGlobalCommand(ChatHandler* handler)
{
handler->PSendSysMessage("No players found.");
return;
} else
}
else
{
handler->PSendSysMessage("=============================");
handler->PSendSysMessage("Players with the more reports:");
@@ -384,7 +403,7 @@ void AnticheatMgr::AnticheatGlobalCommand(ChatHandler* handler)
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);
handler->PSendSysMessage("Player: %s Total Reports: %u Average: %f", player->GetName().c_str(), total_reports, average);
} while (resultDB->NextRow());
}
@@ -401,9 +420,9 @@ void AnticheatMgr::AnticheatDeleteCommand(uint32 guid)
(*it).second.SetCreationTime(0);
for (uint8 i = 0; i < MAX_REPORT_TYPES; i++)
{
(*it).second.SetTempReports(0,i);
(*it).second.SetTempReportsTimer(0,i);
(*it).second.SetTypeReports(i,0);
(*it).second.SetTempReports(0, i);
(*it).second.SetTempReportsTimer(0, i);
(*it).second.SetTypeReports(i, 0);
}
}
CharacterDatabase.PExecute("DELETE FROM players_reports_status;");
@@ -415,11 +434,11 @@ void AnticheatMgr::AnticheatDeleteCommand(uint32 guid)
m_Players[guid].SetCreationTime(0);
for (uint8 i = 0; i < MAX_REPORT_TYPES; i++)
{
m_Players[guid].SetTempReports(0,i);
m_Players[guid].SetTempReportsTimer(0,i);
m_Players[guid].SetTypeReports(i,0);
m_Players[guid].SetTempReports(0, i);
m_Players[guid].SetTempReportsTimer(0, i);
m_Players[guid].SetTypeReports(i, 0);
}
CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u;",guid);
CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u;", guid);
}
}

View File

@@ -1,6 +1,7 @@
#include "Configuration/Config.h"
#include "AnticheatMgr.h"
#include "Object.h"
#include "AccountMgr.h"
int64 resetTime = 0;
int64 lastIterationPlayer = sWorld->GetUptime() + 30;//TODO: change 30 secs static to a configurable option
@@ -82,6 +83,7 @@ class AnticheatMovementHandlerScript : public MovementHandlerScript
}
void AnticheatMovementHandlerScript::OnPlayerMove(Player* player, MovementInfo mi, uint32 opcode) override
{
if (!AccountMgr::IsGMAccount(player->GetSession()->GetSecurity()) || sConfigMgr->GetBoolDefault("Anticheat.EnabledOnGmAccounts", false))
sAnticheatMgr->StartHackDetection(player, mi, opcode);
}
};