Small anti-cheat update

This commit is contained in:
RaidMax 2018-10-28 20:47:56 -05:00
parent 1779bf821d
commit d9d548ea18
5 changed files with 58 additions and 60 deletions

View File

@ -46,40 +46,40 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
/// <summary> /// <summary>
/// Analyze kill and see if performed by a cheater /// Analyze kill and see if performed by a cheater
/// </summary> /// </summary>
/// <param name="kill">kill performed by the player</param> /// <param name="hit">kill performed by the player</param>
/// <returns>true if detection reached thresholds, false otherwise</returns> /// <returns>true if detection reached thresholds, false otherwise</returns>
public DetectionPenaltyResult ProcessKill(EFClientKill kill, bool isDamage) public DetectionPenaltyResult ProcessHit(EFClientKill hit, bool isDamage)
{ {
if ((kill.DeathType != IW4Info.MeansOfDeath.MOD_PISTOL_BULLET && if ((hit.DeathType != IW4Info.MeansOfDeath.MOD_PISTOL_BULLET &&
kill.DeathType != IW4Info.MeansOfDeath.MOD_RIFLE_BULLET && hit.DeathType != IW4Info.MeansOfDeath.MOD_RIFLE_BULLET &&
kill.DeathType != IW4Info.MeansOfDeath.MOD_HEAD_SHOT) || hit.DeathType != IW4Info.MeansOfDeath.MOD_HEAD_SHOT) ||
kill.HitLoc == IW4Info.HitLocation.none || kill.TimeOffset - LastOffset < 0 || hit.HitLoc == IW4Info.HitLocation.none || hit.TimeOffset - LastOffset < 0 ||
// hack: prevents false positives // hack: prevents false positives
(LastWeapon != kill.Weapon && (kill.TimeOffset - LastOffset) == 50)) (LastWeapon != hit.Weapon && (hit.TimeOffset - LastOffset) == 50))
return new DetectionPenaltyResult() return new DetectionPenaltyResult()
{ {
ClientPenalty = Penalty.PenaltyType.Any, ClientPenalty = Penalty.PenaltyType.Any,
}; };
DetectionPenaltyResult result = null; DetectionPenaltyResult result = null;
LastWeapon = kill.Weapon; LastWeapon = hit.Weapon;
HitLocationCount[hit.HitLoc]++;
HitCount++;
HitLocationCount[kill.HitLoc]++;
if (!isDamage) if (!isDamage)
{ {
Kills++; Kills++;
} }
HitCount++;
#region VIEWANGLES #region VIEWANGLES
if (kill.AnglesList.Count >= 2) if (hit.AnglesList.Count >= 2)
{ {
double realAgainstPredict = Vector3.ViewAngleDistance(kill.AnglesList[0], kill.AnglesList[1], kill.ViewAngles); double realAgainstPredict = Vector3.ViewAngleDistance(hit.AnglesList[0], hit.AnglesList[1], hit.ViewAngles);
// LIFETIME // LIFETIME
var hitLoc = ClientStats.HitLocations var hitLoc = ClientStats.HitLocations
.First(hl => hl.Location == kill.HitLoc); .First(hl => hl.Location == hit.HitLoc);
float previousAverage = hitLoc.HitOffsetAverage; float previousAverage = hitLoc.HitOffsetAverage;
double newAverage = (previousAverage * (hitLoc.HitCount - 1) + realAgainstPredict) / hitLoc.HitCount; double newAverage = (previousAverage * (hitLoc.HitCount - 1) + realAgainstPredict) / hitLoc.HitCount;
@ -88,11 +88,11 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
if (hitLoc.HitOffsetAverage > Thresholds.MaxOffset(hitLoc.HitCount) && if (hitLoc.HitOffsetAverage > Thresholds.MaxOffset(hitLoc.HitCount) &&
hitLoc.HitCount > 100) hitLoc.HitCount > 100)
{ {
Log.WriteDebug("*** Reached Max Lifetime Average for Angle Difference ***"); //Log.WriteDebug("*** Reached Max Lifetime Average for Angle Difference ***");
Log.WriteDebug($"Lifetime Average = {newAverage}"); //Log.WriteDebug($"Lifetime Average = {newAverage}");
Log.WriteDebug($"Bone = {hitLoc.Location}"); //Log.WriteDebug($"Bone = {hitLoc.Location}");
Log.WriteDebug($"HitCount = {hitLoc.HitCount}"); //Log.WriteDebug($"HitCount = {hitLoc.HitCount}");
Log.WriteDebug($"ID = {kill.AttackerId}"); //Log.WriteDebug($"ID = {hit.AttackerId}");
result = new DetectionPenaltyResult() result = new DetectionPenaltyResult()
{ {
@ -110,10 +110,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
if (sessAverage > Thresholds.MaxOffset(HitCount) && if (sessAverage > Thresholds.MaxOffset(HitCount) &&
HitCount > 30) HitCount > 30)
{ {
Log.WriteDebug("*** Reached Max Session Average for Angle Difference ***"); //Log.WriteDebug("*** Reached Max Session Average for Angle Difference ***");
Log.WriteDebug($"Session Average = {sessAverage}"); //Log.WriteDebug($"Session Average = {sessAverage}");
Log.WriteDebug($"HitCount = {HitCount}"); //Log.WriteDebug($"HitCount = {HitCount}");
Log.WriteDebug($"ID = {kill.AttackerId}"); //Log.WriteDebug($"ID = {hit.AttackerId}");
result = new DetectionPenaltyResult() result = new DetectionPenaltyResult()
{ {
@ -130,17 +130,20 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
#endif #endif
} }
double currentStrain = Strain.GetStrain(isDamage, kill.Damage, kill.Distance / 0.0254, kill.ViewAngles, Math.Max(50, kill.TimeOffset - LastOffset)); double currentStrain = Strain.GetStrain(isDamage, hit.Damage, hit.Distance / 0.0254, hit.ViewAngles, Math.Max(50, hit.TimeOffset - LastOffset));
LastOffset = kill.TimeOffset; #if DEBUG == true
Log.WriteDebug($"Current Strain: {currentStrain}");
#endif
LastOffset = hit.TimeOffset;
if (currentStrain > ClientStats.MaxStrain) if (currentStrain > ClientStats.MaxStrain)
{ {
ClientStats.MaxStrain = currentStrain; ClientStats.MaxStrain = currentStrain;
} }
// flag // flag
if (currentStrain > Thresholds.MaxStrainFlag && if (currentStrain > Thresholds.MaxStrainFlag)
HitCount >= 10)
{ {
result = new DetectionPenaltyResult() result = new DetectionPenaltyResult()
{ {
@ -153,7 +156,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
// ban // ban
if (currentStrain > Thresholds.MaxStrainBan && if (currentStrain > Thresholds.MaxStrainBan &&
HitCount >= 15) HitCount >= 5)
{ {
result = new DetectionPenaltyResult() result = new DetectionPenaltyResult()
{ {
@ -163,11 +166,6 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
Type = DetectionType.Strain Type = DetectionType.Strain
}; };
} }
#if DEBUG
Log.WriteDebug($"Current Strain: {currentStrain}");
#endif
#endregion #endregion
#region SESSION_RATIOS #region SESSION_RATIOS
@ -197,7 +195,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
if (currentHeadshotRatio > maxHeadshotLerpValueForBan) if (currentHeadshotRatio > maxHeadshotLerpValueForBan)
{ {
Log.WriteDebug("**Maximum Headshot Ratio Reached For Ban**"); Log.WriteDebug("**Maximum Headshot Ratio Reached For Ban**");
Log.WriteDebug($"ClientId: {kill.AttackerId}"); Log.WriteDebug($"ClientId: {hit.AttackerId}");
Log.WriteDebug($"**HitCount: {HitCount}"); Log.WriteDebug($"**HitCount: {HitCount}");
Log.WriteDebug($"**Ratio {currentHeadshotRatio}"); Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}"); Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
@ -218,7 +216,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
else else
{ {
Log.WriteDebug("**Maximum Headshot Ratio Reached For Flag**"); Log.WriteDebug("**Maximum Headshot Ratio Reached For Flag**");
Log.WriteDebug($"ClientId: {kill.AttackerId}"); Log.WriteDebug($"ClientId: {hit.AttackerId}");
Log.WriteDebug($"**HitCount: {HitCount}"); Log.WriteDebug($"**HitCount: {HitCount}");
Log.WriteDebug($"**Ratio {currentHeadshotRatio}"); Log.WriteDebug($"**Ratio {currentHeadshotRatio}");
Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}"); Log.WriteDebug($"**MaxRatio {maxHeadshotLerpValueForFlag}");
@ -247,7 +245,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
if (currentMaxBoneRatio > maxBoneRatioLerpValueForBan) if (currentMaxBoneRatio > maxBoneRatioLerpValueForBan)
{ {
Log.WriteDebug("**Maximum Bone Ratio Reached For Ban**"); Log.WriteDebug("**Maximum Bone Ratio Reached For Ban**");
Log.WriteDebug($"ClientId: {kill.AttackerId}"); Log.WriteDebug($"ClientId: {hit.AttackerId}");
Log.WriteDebug($"**HitCount: {HitCount}"); Log.WriteDebug($"**HitCount: {HitCount}");
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}"); Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForBan}"); Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForBan}");
@ -268,7 +266,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
else else
{ {
Log.WriteDebug("**Maximum Bone Ratio Reached For Flag**"); Log.WriteDebug("**Maximum Bone Ratio Reached For Flag**");
Log.WriteDebug($"ClientId: {kill.AttackerId}"); Log.WriteDebug($"ClientId: {hit.AttackerId}");
Log.WriteDebug($"**HitCount: {HitCount}"); Log.WriteDebug($"**HitCount: {HitCount}");
Log.WriteDebug($"**Ratio {currentMaxBoneRatio}"); Log.WriteDebug($"**Ratio {currentMaxBoneRatio}");
Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForFlag}"); Log.WriteDebug($"**MaxRatio {maxBoneRatioLerpValueForFlag}");
@ -309,7 +307,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan && chestHits >= Thresholds.MediumSampleMinKills + 30) if (currentChestAbdomenRatio > chestAbdomenLerpValueForBan && chestHits >= Thresholds.MediumSampleMinKills + 30)
{ {
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**"); Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Ban**");
Log.WriteDebug($"ClientId: {kill.AttackerId}"); Log.WriteDebug($"ClientId: {hit.AttackerId}");
Log.WriteDebug($"**Chest Hits: {chestHits}"); Log.WriteDebug($"**Chest Hits: {chestHits}");
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}"); Log.WriteDebug($"**MaxRatio {chestAbdomenLerpValueForBan}");
@ -330,7 +328,7 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
else else
{ {
Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**"); Log.WriteDebug("**Maximum Chest/Abdomen Ratio Reached For Flag**");
Log.WriteDebug($"ClientId: {kill.AttackerId}"); Log.WriteDebug($"ClientId: {hit.AttackerId}");
Log.WriteDebug($"**Chest Hits: {chestHits}"); Log.WriteDebug($"**Chest Hits: {chestHits}");
Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}"); Log.WriteDebug($"**Ratio {currentChestAbdomenRatio}");
Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}"); Log.WriteDebug($"**MaxRatio {chestAbdomenRatioLerpValueForFlag}");
@ -356,31 +354,31 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
Tracker.OnChange(new EFACSnapshot() Tracker.OnChange(new EFACSnapshot()
{ {
When = kill.When, When = hit.When,
ClientId = ClientStats.ClientId, ClientId = ClientStats.ClientId,
SessionAngleOffset = AngleDifferenceAverage, SessionAngleOffset = AngleDifferenceAverage,
CurrentSessionLength = (int)(DateTime.UtcNow - ConnectionTime).TotalSeconds, CurrentSessionLength = (int)(DateTime.UtcNow - ConnectionTime).TotalSeconds,
CurrentStrain = currentStrain, CurrentStrain = currentStrain,
CurrentViewAngle = kill.ViewAngles, CurrentViewAngle = hit.ViewAngles,
Hits = HitCount, Hits = HitCount,
Kills = Kills, Kills = Kills,
Deaths = ClientStats.SessionDeaths, Deaths = ClientStats.SessionDeaths,
HitDestinationId = kill.DeathOrigin.Vector3Id, HitDestinationId = hit.DeathOrigin.Vector3Id,
HitDestination = kill.DeathOrigin, HitDestination = hit.DeathOrigin,
HitOriginId = kill.KillOrigin.Vector3Id, HitOriginId = hit.KillOrigin.Vector3Id,
HitOrigin = kill.KillOrigin, HitOrigin = hit.KillOrigin,
EloRating = ClientStats.EloRating, EloRating = ClientStats.EloRating,
HitLocation = kill.HitLoc, HitLocation = hit.HitLoc,
LastStrainAngle = Strain.LastAngle, LastStrainAngle = Strain.LastAngle,
PredictedViewAngles = kill.AnglesList, PredictedViewAngles = hit.AnglesList,
// this is in "meters" // this is in "meters"
Distance = kill.Distance, Distance = hit.Distance,
SessionScore = ClientStats.SessionScore, SessionScore = ClientStats.SessionScore,
HitType = kill.DeathType, HitType = hit.DeathType,
SessionSPM = ClientStats.SessionSPM, SessionSPM = ClientStats.SessionSPM,
StrainAngleBetween = Strain.LastDistance, StrainAngleBetween = Strain.LastDistance,
TimeSinceLastEvent = (int)Strain.LastDeltaTime, TimeSinceLastEvent = (int)Strain.LastDeltaTime,
WeaponId = kill.Weapon WeaponId = hit.Weapon
}); });
return result ?? new DetectionPenaltyResult() return result ?? new DetectionPenaltyResult()

View File

@ -14,8 +14,6 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
public Vector3 LastAngle { get; private set; } public Vector3 LastAngle { get; private set; }
public double LastDeltaTime { get; private set; } public double LastDeltaTime { get; private set; }
public int TimesReachedMaxStrain { get; private set; }
public double GetStrain(bool isDamage, int damage, double killDistance, Vector3 newAngle, double deltaTime) public double GetStrain(bool isDamage, int damage, double killDistance, Vector3 newAngle, double deltaTime)
{ {
if (LastAngle == null) if (LastAngle == null)
@ -33,6 +31,10 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
double[] distance = Helpers.Extensions.AngleStuff(newAngle, LastAngle); double[] distance = Helpers.Extensions.AngleStuff(newAngle, LastAngle);
LastDistance = distance[0] + distance[1]; LastDistance = distance[0] + distance[1];
#if DEBUG == true
Console.WriteLine($"Last Distance = {LastDistance}");
#endif
// this happens on first kill // this happens on first kill
if ((distance[0] == 0 && distance[1] == 0) || if ((distance[0] == 0 && distance[1] == 0) ||
deltaTime == 0 || deltaTime == 0 ||
@ -41,14 +43,11 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
return CurrentStrain; return CurrentStrain;
} }
double newStrain = Math.Pow(distance[0] + distance[1], 0.99) / deltaTime; double newStrain = Math.Pow(LastDistance, 0.99) / deltaTime;
newStrain *= killDistance / 1000.0; newStrain *= killDistance / 1000.0;
CurrentStrain += newStrain; CurrentStrain += newStrain;
if (CurrentStrain > Thresholds.MaxStrainBan)
TimesReachedMaxStrain++;
LastAngle = newAngle; LastAngle = newAngle;
return CurrentStrain; return CurrentStrain;
} }

View File

@ -27,9 +27,8 @@ namespace IW4MAdmin.Plugins.Stats.Cheat
public const int HighSampleMinKills = 100; public const int HighSampleMinKills = 100;
public const double KillTimeThreshold = 0.2; public const double KillTimeThreshold = 0.2;
public const double MaxStrainBan = 1.12; public const double MaxStrainBan = 0.9;
//=exp((MAX(-3.07+(-3.07/sqrt(J20)),-3.07-(-3.07/sqrt(J20))))+(4*(0.869)))
public static double MaxOffset(int sampleSize) => Math.Exp(Math.Max(-3.07 + (-3.07 / Math.Sqrt(sampleSize)), -3.07 - (-3.07 / Math.Sqrt(sampleSize))) + 4 * (0.869)); public static double MaxOffset(int sampleSize) => Math.Exp(Math.Max(-3.07 + (-3.07 / Math.Sqrt(sampleSize)), -3.07 - (-3.07 / Math.Sqrt(sampleSize))) + 4 * (0.869));
public const double MaxStrainFlag = 0.36; public const double MaxStrainFlag = 0.36;

View File

@ -548,7 +548,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
if (Plugin.Config.Configuration().EnableAntiCheat) if (Plugin.Config.Configuration().EnableAntiCheat)
{ {
ApplyPenalty(clientDetection.ProcessKill(hit, isDamage), clientDetection, attacker, ctx); ApplyPenalty(clientDetection.ProcessHit(hit, isDamage), clientDetection, attacker, ctx);
ApplyPenalty(clientDetection.ProcessTotalRatio(clientStats), clientDetection, attacker, ctx); ApplyPenalty(clientDetection.ProcessTotalRatio(clientStats), clientDetection, attacker, ctx);
} }

View File

@ -119,7 +119,9 @@ namespace SharedLibraryCore
{ {
string formattedMessage = String.Format(RconParser.GetCommandPrefixes().Say, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{message}"); string formattedMessage = String.Format(RconParser.GetCommandPrefixes().Say, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{message}");
//Logger.WriteVerbose(message.StripColors()); #if DEBUG == true
Logger.WriteVerbose(message.StripColors());
#endif
var e = new GameEvent() var e = new GameEvent()
{ {