Update (detection): New Detection No Fall Damage

New detection No Fall Damage Hack. Its when players use external apps to prevent fall damage from registering.
New conf:
Anticheat.NoFallDamage = 1

Autoupdate feature should apply the sql update automatically to add the new column.  If not then apply it manually from either the sql\characters folder or the sql\updates folder
This commit is contained in:
MDIC
2022-08-12 11:17:47 -04:00
parent 74d7518187
commit cc6816378c
7 changed files with 74 additions and 12 deletions

View File

@@ -83,6 +83,7 @@ Anticheat.DetectZaxisHack =1
Anticheat.AntiSwimHack = 1 Anticheat.AntiSwimHack = 1
Anticheat.DetectGravityHack = 1 Anticheat.DetectGravityHack = 1
Anticheat.AntiKnockBack = 1 Anticheat.AntiKnockBack = 1
Anticheat.NoFallDamage = 1
# Anticheat.StricterFlyHackCheck # Anticheat.StricterFlyHackCheck
# Description: Checks moveflag ascending (may give false positives) # Description: Checks moveflag ascending (may give false positives)

View File

@@ -16,6 +16,7 @@ CREATE TABLE IF NOT EXISTS `daily_players_reports` (
`antiswim_reports` bigint unsigned NOT NULL DEFAULT 0, `antiswim_reports` bigint unsigned NOT NULL DEFAULT 0,
`gravity_reports` bigint unsigned NOT NULL DEFAULT 0, `gravity_reports` bigint unsigned NOT NULL DEFAULT 0,
`antiknockback_reports` bigint unsigned NOT NULL DEFAULT 0, `antiknockback_reports` bigint unsigned NOT NULL DEFAULT 0,
`no_fall_damage_reports` bigint unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`guid`) PRIMARY KEY (`guid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -37,5 +38,6 @@ CREATE TABLE IF NOT EXISTS `players_reports_status` (
`antiswim_reports` bigint unsigned NOT NULL DEFAULT 0, `antiswim_reports` bigint unsigned NOT NULL DEFAULT 0,
`gravity_reports` bigint unsigned NOT NULL DEFAULT 0, `gravity_reports` bigint unsigned NOT NULL DEFAULT 0,
`antiknockback_reports` bigint unsigned NOT NULL DEFAULT 0, `antiknockback_reports` bigint unsigned NOT NULL DEFAULT 0,
`no_fall_damage_reports` bigint unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`guid`) PRIMARY KEY (`guid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@@ -0,0 +1,6 @@
-- run on character db
ALTER TABLE `daily_players_reports`
ADD COLUMN `no_fall_damage_reports` BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER `antiknockback_reports`;
ALTER TABLE `players_reports_status`
ADD COLUMN `no_fall_damage_reports` BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER `antiknockback_reports`;

View File

@@ -27,7 +27,7 @@
#include "AnticheatMgr.h" #include "AnticheatMgr.h"
#define MAX_REPORT_TYPES 12 #define MAX_REPORT_TYPES 13
class AnticheatData class AnticheatData
{ {

View File

@@ -89,7 +89,8 @@ void AnticheatMgr::StartHackDetection(Player* player, MovementInfo movementInfo,
{ {
AntiSwimHackDetection(player, movementInfo, opcode); AntiSwimHackDetection(player, movementInfo, opcode);
} }
AntiKnockBackHactDetection(player, movementInfo); AntiKnockBackHackDetection(player, movementInfo);
NoFallDamageDetection(player, movementInfo);
m_Players[key].SetLastMovementInfo(movementInfo); m_Players[key].SetLastMovementInfo(movementInfo);
m_Players[key].SetLastOpcode(opcode); m_Players[key].SetLastOpcode(opcode);
} }
@@ -702,7 +703,7 @@ void AnticheatMgr::AntiSwimHackDetection(Player* player, MovementInfo movementIn
} }
// basic detection // basic detection
void AnticheatMgr::AntiKnockBackHactDetection(Player* player, MovementInfo movementInfo) void AnticheatMgr::AntiKnockBackHackDetection(Player* player, MovementInfo movementInfo)
{ {
if (!sConfigMgr->GetOption<bool>("Anticheat.AntiKnockBack", true)) if (!sConfigMgr->GetOption<bool>("Anticheat.AntiKnockBack", true))
return; return;
@@ -728,6 +729,52 @@ void AnticheatMgr::AntiKnockBackHactDetection(Player* player, MovementInfo movem
player->SetCanKnockback(false); player->SetCanKnockback(false);
} }
// basic detection
void AnticheatMgr::NoFallDamageDetection(Player* player, MovementInfo movementInfo)
{
if (!sConfigMgr->GetOption<bool>("Anticheat.NoFallDamage", true))
return;
// ghost can not get damaged
if (player->HasAuraType(SPELL_AURA_GHOST))
return;
// players with water walk aura jumping on to the water from ledge would not get damage and neither will safe fall and feather fall
if (player->HasAuraType(SPELL_AURA_WATER_WALK) && player->GetLiquidData().Status == LIQUID_MAP_WATER_WALK && !player->IsFlying() ||
player->HasAuraType(SPELL_AURA_FEATHER_FALL) || player->HasAuraType(SPELL_AURA_SAFE_FALL))
{
return;
}
ObjectGuid key = player->GetGUID();
float lastZ = m_Players[key].GetLastMovementInfo().pos.GetPositionZ();
float newZ = movementInfo.pos.GetPositionZ();
float zDiff = fabs(lastZ - newZ);
int32 safe_fall = player->GetTotalAuraModifier(SPELL_AURA_SAFE_FALL);
float damageperc = 0.018f * (zDiff - safe_fall) - 0.2426f;
uint32 damage = (uint32)(damageperc * player->GetMaxHealth() * sWorld->getRate(RATE_DAMAGE_FALL));
// in the Player::Handlefall 14.57f is used to calculated the damageperc formula below to 0 for fall damamge
if (movementInfo.pos.GetPositionZ() < m_Players[key].GetLastMovementInfo().pos.GetPositionZ() && zDiff > 14.57f)
{
if (movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING) || m_Players[key].GetLastMovementInfo().HasMovementFlag(MOVEMENTFLAG_FALLING))
{
if (damage == 0 && !player->IsImmunedToDamageOrSchool(SPELL_SCHOOL_MASK_NORMAL))
{
if (sConfigMgr->GetOption<bool>("Anticheat.WriteLog", true))
{
uint32 latency = 0;
latency = player->GetSession()->GetLatency();
LOG_INFO("anticheat.module", "AnticheatMgr:: No Fall Damage - Hack detected player {} ({}) - Latency: {} ms", player->GetName(), player->GetGUID().ToString(), latency);
}
BuildReport(player, NO_FALL_DAMAGE_HACK_REPORT);
}
}
}
}
void AnticheatMgr::HandlePlayerLogin(Player* player) void AnticheatMgr::HandlePlayerLogin(Player* player)
{ {
// we must delete this to prevent errors in case of crash // we must delete this to prevent errors in case of crash
@@ -753,15 +800,15 @@ void AnticheatMgr::HandlePlayerLogout(Player* player)
void AnticheatMgr::SavePlayerData(Player* player) void AnticheatMgr::SavePlayerData(Player* player)
{ {
AnticheatData playerData = m_Players[player->GetGUID()]; AnticheatData playerData = m_Players[player->GetGUID()];
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
CharacterDatabase.Execute("REPLACE INTO players_reports_status (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,teleport_reports,ignorecontrol_reports,zaxis_reports,antiswim_reports,gravity_reports,antiknockback_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{});", player->GetGUID().GetCounter(), playerData.GetAverage(), playerData.GetTotalReports(), playerData.GetTypeReports(SPEED_HACK_REPORT), playerData.GetTypeReports(FLY_HACK_REPORT), playerData.GetTypeReports(JUMP_HACK_REPORT), playerData.GetTypeReports(WALK_WATER_HACK_REPORT), playerData.GetTypeReports(TELEPORT_PLANE_HACK_REPORT), playerData.GetTypeReports(CLIMB_HACK_REPORT), playerData.GetTypeReports(TELEPORT_HACK_REPORT), playerData.GetTypeReports(IGNORE_CONTROL_REPORT), playerData.GetTypeReports(ZAXIS_HACK_REPORT), playerData.GetTypeReports(ANTISWIM_HACK_REPORT), playerData.GetTypeReports(GRAVITY_HACK_REPORT), playerData.GetTypeReports(ANTIKNOCK_BACK_HACK_REPORT), playerData.GetCreationTime()); CharacterDatabase.Execute("REPLACE INTO players_reports_status (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,teleport_reports,ignorecontrol_reports,zaxis_reports,antiswim_reports,gravity_reports,antiknockback_reports,no_fall_damage_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{});", player->GetGUID().GetCounter(), playerData.GetAverage(), playerData.GetTotalReports(), playerData.GetTypeReports(SPEED_HACK_REPORT), playerData.GetTypeReports(FLY_HACK_REPORT), playerData.GetTypeReports(JUMP_HACK_REPORT), playerData.GetTypeReports(WALK_WATER_HACK_REPORT), playerData.GetTypeReports(TELEPORT_PLANE_HACK_REPORT), playerData.GetTypeReports(CLIMB_HACK_REPORT), playerData.GetTypeReports(TELEPORT_HACK_REPORT), playerData.GetTypeReports(IGNORE_CONTROL_REPORT), playerData.GetTypeReports(ZAXIS_HACK_REPORT), playerData.GetTypeReports(ANTISWIM_HACK_REPORT), playerData.GetTypeReports(GRAVITY_HACK_REPORT), playerData.GetTypeReports(ANTIKNOCK_BACK_HACK_REPORT), playerData.GetTypeReports(NO_FALL_DAMAGE_HACK_REPORT), playerData.GetCreationTime());
} }
void AnticheatMgr::SavePlayerDataDaily(Player* player) void AnticheatMgr::SavePlayerDataDaily(Player* player)
{ {
AnticheatData playerData = m_Players[player->GetGUID()]; AnticheatData playerData = m_Players[player->GetGUID()];
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
CharacterDatabase.Execute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,teleport_reports,ignorecontrol_reports,zaxis_reports,antiswim_reports,gravity_reports,antiknockback_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{});", player->GetGUID().GetCounter(), playerData.GetAverage(), playerData.GetTotalReports(), playerData.GetTypeReports(SPEED_HACK_REPORT), playerData.GetTypeReports(FLY_HACK_REPORT), playerData.GetTypeReports(JUMP_HACK_REPORT), playerData.GetTypeReports(WALK_WATER_HACK_REPORT), playerData.GetTypeReports(TELEPORT_PLANE_HACK_REPORT), playerData.GetTypeReports(CLIMB_HACK_REPORT), playerData.GetTypeReports(TELEPORT_HACK_REPORT), playerData.GetTypeReports(IGNORE_CONTROL_REPORT), playerData.GetTypeReports(ZAXIS_HACK_REPORT), playerData.GetTypeReports(ANTISWIM_HACK_REPORT), playerData.GetTypeReports(GRAVITY_HACK_REPORT), playerData.GetTypeReports(ANTIKNOCK_BACK_HACK_REPORT), playerData.GetCreationTime()); CharacterDatabase.Execute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,teleport_reports,ignorecontrol_reports,zaxis_reports,antiswim_reports,gravity_reports,antiknockback_reports,no_fall_damage_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{});", player->GetGUID().GetCounter(), playerData.GetAverage(), playerData.GetTotalReports(), playerData.GetTypeReports(SPEED_HACK_REPORT), playerData.GetTypeReports(FLY_HACK_REPORT), playerData.GetTypeReports(JUMP_HACK_REPORT), playerData.GetTypeReports(WALK_WATER_HACK_REPORT), playerData.GetTypeReports(TELEPORT_PLANE_HACK_REPORT), playerData.GetTypeReports(CLIMB_HACK_REPORT), playerData.GetTypeReports(TELEPORT_HACK_REPORT), playerData.GetTypeReports(IGNORE_CONTROL_REPORT), playerData.GetTypeReports(ZAXIS_HACK_REPORT), playerData.GetTypeReports(ANTISWIM_HACK_REPORT), playerData.GetTypeReports(GRAVITY_HACK_REPORT), playerData.GetTypeReports(ANTIKNOCK_BACK_HACK_REPORT), playerData.GetTypeReports(NO_FALL_DAMAGE_HACK_REPORT), playerData.GetCreationTime());
} }
uint32 AnticheatMgr::GetTotalReports(ObjectGuid guid) uint32 AnticheatMgr::GetTotalReports(ObjectGuid guid)
{ {
@@ -795,6 +842,9 @@ bool AnticheatMgr::MustCheckTempReports(uint8 type)
if (type == ANTIKNOCK_BACK_HACK_REPORT) if (type == ANTIKNOCK_BACK_HACK_REPORT)
return false; return false;
if (type == NO_FALL_DAMAGE_HACK_REPORT)
return false;
return true; return true;
} }
@@ -860,8 +910,8 @@ void AnticheatMgr::BuildReport(Player* player, uint16 reportType)
if (!m_Players[key].GetDailyReportState()) if (!m_Players[key].GetDailyReportState())
{ {
AnticheatData playerData = m_Players[player->GetGUID()]; AnticheatData playerData = m_Players[player->GetGUID()];
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
CharacterDatabase.Execute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,teleport_reports,ignorecontrol_reports,zaxis_reports,antiswim_reports,gravity_reports,antiknockback_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{});", player->GetGUID().GetCounter(), playerData.GetAverage(), playerData.GetTotalReports(), playerData.GetTypeReports(SPEED_HACK_REPORT), playerData.GetTypeReports(FLY_HACK_REPORT), playerData.GetTypeReports(JUMP_HACK_REPORT), playerData.GetTypeReports(WALK_WATER_HACK_REPORT), playerData.GetTypeReports(TELEPORT_PLANE_HACK_REPORT), playerData.GetTypeReports(CLIMB_HACK_REPORT), playerData.GetTypeReports(TELEPORT_HACK_REPORT), playerData.GetTypeReports(IGNORE_CONTROL_REPORT), playerData.GetTypeReports(ZAXIS_HACK_REPORT), playerData.GetTypeReports(ANTISWIM_HACK_REPORT), playerData.GetTypeReports(GRAVITY_HACK_REPORT), playerData.GetTypeReports(ANTIKNOCK_BACK_HACK_REPORT), playerData.GetCreationTime()); CharacterDatabase.Execute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,teleport_reports,ignorecontrol_reports,zaxis_reports,antiswim_reports,gravity_reports,antiknockback_reports,no_fall_damage_reports,creation_time) VALUES ({},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{});", player->GetGUID().GetCounter(), playerData.GetAverage(), playerData.GetTotalReports(), playerData.GetTypeReports(SPEED_HACK_REPORT), playerData.GetTypeReports(FLY_HACK_REPORT), playerData.GetTypeReports(JUMP_HACK_REPORT), playerData.GetTypeReports(WALK_WATER_HACK_REPORT), playerData.GetTypeReports(TELEPORT_PLANE_HACK_REPORT), playerData.GetTypeReports(CLIMB_HACK_REPORT), playerData.GetTypeReports(TELEPORT_HACK_REPORT), playerData.GetTypeReports(IGNORE_CONTROL_REPORT), playerData.GetTypeReports(ZAXIS_HACK_REPORT), playerData.GetTypeReports(ANTISWIM_HACK_REPORT), playerData.GetTypeReports(GRAVITY_HACK_REPORT), playerData.GetTypeReports(ANTIKNOCK_BACK_HACK_REPORT), playerData.GetTypeReports(NO_FALL_DAMAGE_HACK_REPORT), playerData.GetCreationTime());
m_Players[key].SetDailyReportState(true); m_Players[key].SetDailyReportState(true);
} }
} }

View File

@@ -49,7 +49,8 @@ enum ReportTypes
ZAXIS_HACK_REPORT = 8, ZAXIS_HACK_REPORT = 8,
ANTISWIM_HACK_REPORT = 9, ANTISWIM_HACK_REPORT = 9,
GRAVITY_HACK_REPORT = 10, GRAVITY_HACK_REPORT = 10,
ANTIKNOCK_BACK_HACK_REPORT = 11 ANTIKNOCK_BACK_HACK_REPORT = 11,
NO_FALL_DAMAGE_HACK_REPORT = 12
// MAX_REPORT_TYPES // MAX_REPORT_TYPES
}; };
@@ -97,7 +98,8 @@ class AnticheatMgr
void WalkOnWaterHackDetection(Player* player, MovementInfo movementInfo); void WalkOnWaterHackDetection(Player* player, MovementInfo movementInfo);
void ZAxisHackDetection(Player* player, MovementInfo movementInfo); void ZAxisHackDetection(Player* player, MovementInfo movementInfo);
void AntiSwimHackDetection(Player* player, MovementInfo movementInfo, uint32 opcode); void AntiSwimHackDetection(Player* player, MovementInfo movementInfo, uint32 opcode);
void AntiKnockBackHactDetection(Player* player, MovementInfo movementInfo); void AntiKnockBackHackDetection(Player* player, MovementInfo movementInfo);
void NoFallDamageDetection(Player* player, MovementInfo movementInfo);
void BuildReport(Player* player,uint16 reportType); void BuildReport(Player* player,uint16 reportType);
bool MustCheckTempReports(uint8 type); bool MustCheckTempReports(uint8 type);
uint32 _counter = 0; uint32 _counter = 0;

View File

@@ -220,6 +220,7 @@ public:
uint32 antiswim_reports = sAnticheatMgr->GetTypeReports(guid, 9); uint32 antiswim_reports = sAnticheatMgr->GetTypeReports(guid, 9);
uint32 gravity_reports = sAnticheatMgr->GetTypeReports(guid, 10); uint32 gravity_reports = sAnticheatMgr->GetTypeReports(guid, 10);
uint32 antiknockback_reports = sAnticheatMgr->GetTypeReports(guid, 11); uint32 antiknockback_reports = sAnticheatMgr->GetTypeReports(guid, 11);
uint32 no_fall_damage_reports = sAnticheatMgr->GetTypeReports(guid, 12);
Player* playerTarget = player->GetConnectedPlayer(); Player* playerTarget = player->GetConnectedPlayer();
uint32 latency = 0; uint32 latency = 0;
latency = playerTarget->GetSession()->GetLatency(); latency = playerTarget->GetSession()->GetLatency();
@@ -230,7 +231,7 @@ public:
handler->PSendSysMessage("Teleport Reports: %u || Climb Reports: %u", teleport_reports, climb_reports); handler->PSendSysMessage("Teleport Reports: %u || Climb Reports: %u", teleport_reports, climb_reports);
handler->PSendSysMessage("Ignore Control Reports: %u || Ignore Z-Axis Reports: %u", ignorecontrol_reports, zaxis_reports); handler->PSendSysMessage("Ignore Control Reports: %u || Ignore Z-Axis Reports: %u", ignorecontrol_reports, zaxis_reports);
handler->PSendSysMessage("Ignore Anti-Swim Reports: %u || Gravity Reports: %u", antiswim_reports, gravity_reports); handler->PSendSysMessage("Ignore Anti-Swim Reports: %u || Gravity Reports: %u", antiswim_reports, gravity_reports);
handler->PSendSysMessage("Anti-Knock Back Reports: %u", antiknockback_reports); handler->PSendSysMessage("Anti-Knock Back Reports: %u || No Fall Damage Reports: %u", antiknockback_reports, no_fall_damage_reports);
return true; return true;
} }
else else