fix rare issues when converting encodings
add readme for AC
This commit is contained in:
parent
47d5df1aa1
commit
58a73e581f
79
Plugins/Stats/Cheat/README.md
Normal file
79
Plugins/Stats/Cheat/README.md
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# IW4MAdmin Anticheat
|
||||||
|
**Initial document draft | 8.30.19**
|
||||||
|
|
||||||
|
**IW4MAdmin** anticheat for IW4x uses data from in-game logs to track player locations, hit locations, and view angles
|
||||||
|
to validate against a known set of play styles.
|
||||||
|
Every hit event ocurring in the game (Damage or Kill from a gun) is captured by IW4MAdmin and analyzed.
|
||||||
|
**Session analysis** occurs against all hit events since the player connected to the server.
|
||||||
|
**Lifetime analysis** occurs against all hit events ever occuring for a given player.
|
||||||
|
## Detection Types
|
||||||
|
### Bone
|
||||||
|
Compares the number of times a particular bone is hit against the number of hits on all other bones.
|
||||||
|
Many rudimentary aimbots lock onto a particular player bone position such as _Head_, or _Upper Torso_.
|
||||||
|
This detection method has the highest chance of a false positive, as non-cheaters can play abnormally
|
||||||
|
(e.g. going for headshots, or using a weapon that unconciously changes their playstyle)
|
||||||
|
|
||||||
|
#### Hit Location Reference
|
||||||
|
| Number | Hit Location |
|
||||||
|
|--------|-----------------|
|
||||||
|
| 2 | Head |
|
||||||
|
| 3 | Neck |
|
||||||
|
| 4 | Upper Torso |
|
||||||
|
| 5 | Lower Torso |
|
||||||
|
| 6 | Upper Right Arm |
|
||||||
|
| 7 | Upper Left Arm |
|
||||||
|
| 8 | Lower Right Arm |
|
||||||
|
| 9 | Lower Left Arm |
|
||||||
|
| 10 | Right Hand |
|
||||||
|
| 11 | Left Hand |
|
||||||
|
| 12 | Upper Right Leg |
|
||||||
|
| 13 | Upper Left Leg |
|
||||||
|
| 14 | Lower Right Leg |
|
||||||
|
| 15 | Right Foot |
|
||||||
|
| 16 | Left Foot |
|
||||||
|
### Chest
|
||||||
|
Identical to *Bone* detection, except it specifically compares the ratio of Upper Torso / Lower Torso hit counts.
|
||||||
|
It can be thought of as a focused bone detection type, as most aimbots don't aim to unusual bones such as a foot.
|
||||||
|
As with *Bone* detection, this is prone to false positives.
|
||||||
|
### Offset
|
||||||
|
Compares the player angles from three snapshots. The first snapshot being the snapshot immediately before the server registered the hit for a player.
|
||||||
|
The second snapshot is the "frame" the server registered the kill. The final snapshot is the snapshot immediately after the server registers the hit.
|
||||||
|
The algorithm is:
|
||||||
|
```
|
||||||
|
let a = first snapshot angles
|
||||||
|
let b = second snapshot angles
|
||||||
|
let c = third snapshot angles
|
||||||
|
offset = ((a - b) + (c - b)) - (a-c)
|
||||||
|
```
|
||||||
|
This detection method is very effective at detecting silent aimbots.
|
||||||
|
Silent aimbots "fake" a shot by changing a player's view angles for a single snapshot. From a spectator's position, the single snapshot view angle altering is not visible.
|
||||||
|
The larger "FOV" (field of view) from a silent aimbot, the more absolute difference between the three snapshots.
|
||||||
|
Over time if the average distance between these two viewangles is higher than expected, a detection is triggered.
|
||||||
|
False positives are very rare with this detection. However, extreme client lag can trigger a false positive in special situations.
|
||||||
|
### Strain
|
||||||
|
Analyzes the frequency, viewangle distance, and player distance between hits.
|
||||||
|
The algorithm is:
|
||||||
|
```
|
||||||
|
let v = view angle distance between two hits
|
||||||
|
let t = delta time (time between hits)
|
||||||
|
let d = distance between the attacker and victim
|
||||||
|
let s = decay over time
|
||||||
|
strain = ((v / t) * d)^s
|
||||||
|
```
|
||||||
|
A high value indicates fast target switching at large distance intervals, which if done naturally, requires an extreme level of mechanical effort.
|
||||||
|
"Rage" aimbots commonly switch to targets as fast as possible in any direction.
|
||||||
|
### Recoil
|
||||||
|
Compares the average of the last few snapshots of player angles to 0. Client sided no recoil prevents the view angle "Z" axis from changing.
|
||||||
|
If the average view angle "Z" axis value remains 0, the detection is triggered.
|
||||||
|
As of 8.30.19, there are no known false positives for this detection.
|
||||||
|
Several weapons which do not have any recoil from the game are excluded in this detection.
|
||||||
|
### Format
|
||||||
|
Detection penalty reasons are as follow:
|
||||||
|
<_detectionType_>-<_location/value_>@<_hitCount_>
|
||||||
|
Example:
|
||||||
|
- detectionType = Strain
|
||||||
|
- value = 1.39
|
||||||
|
- hitCount = 136
|
||||||
|
|
||||||
|
Result: **Strain-1.39@136**
|
||||||
|
This reason is only visible to logged in privileged users.
|
@ -86,33 +86,44 @@ namespace SharedLibraryCore.RCon
|
|||||||
return defaultEncoding.GetString(convertedBytes);
|
return defaultEncoding.GetString(convertedBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
string convertedRConPassword = convertEncoding(RConPassword);
|
try
|
||||||
string convertedParameters = convertEncoding(parameters);
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case StaticHelpers.QueryType.GET_DVAR:
|
string convertedRConPassword = convertEncoding(RConPassword);
|
||||||
waitForResponse |= true;
|
string convertedParameters = convertEncoding(parameters);
|
||||||
payload = string.Format(Config.CommandPrefixes.RConGetDvar, convertedRConPassword, convertedParameters + '\0').Select(Convert.ToByte).ToArray();
|
|
||||||
break;
|
switch (type)
|
||||||
case StaticHelpers.QueryType.SET_DVAR:
|
{
|
||||||
payload = string.Format(Config.CommandPrefixes.RConSetDvar, convertedRConPassword, convertedParameters + '\0').Select(Convert.ToByte).ToArray();
|
case StaticHelpers.QueryType.GET_DVAR:
|
||||||
break;
|
waitForResponse |= true;
|
||||||
case StaticHelpers.QueryType.COMMAND:
|
payload = string.Format(Config.CommandPrefixes.RConGetDvar, convertedRConPassword, convertedParameters + '\0').Select(Convert.ToByte).ToArray();
|
||||||
payload = string.Format(Config.CommandPrefixes.RConCommand, convertedRConPassword, convertedParameters + '\0').Select(Convert.ToByte).ToArray();
|
break;
|
||||||
break;
|
case StaticHelpers.QueryType.SET_DVAR:
|
||||||
case StaticHelpers.QueryType.GET_STATUS:
|
payload = string.Format(Config.CommandPrefixes.RConSetDvar, convertedRConPassword, convertedParameters + '\0').Select(Convert.ToByte).ToArray();
|
||||||
waitForResponse |= true;
|
break;
|
||||||
payload = (Config.CommandPrefixes.RConGetStatus + '\0').Select(Convert.ToByte).ToArray();
|
case StaticHelpers.QueryType.COMMAND:
|
||||||
break;
|
payload = string.Format(Config.CommandPrefixes.RConCommand, convertedRConPassword, convertedParameters + '\0').Select(Convert.ToByte).ToArray();
|
||||||
case StaticHelpers.QueryType.GET_INFO:
|
break;
|
||||||
waitForResponse |= true;
|
case StaticHelpers.QueryType.GET_STATUS:
|
||||||
payload = (Config.CommandPrefixes.RConGetInfo + '\0').Select(Convert.ToByte).ToArray();
|
waitForResponse |= true;
|
||||||
break;
|
payload = (Config.CommandPrefixes.RConGetStatus + '\0').Select(Convert.ToByte).ToArray();
|
||||||
case StaticHelpers.QueryType.COMMAND_STATUS:
|
break;
|
||||||
waitForResponse |= true;
|
case StaticHelpers.QueryType.GET_INFO:
|
||||||
payload = string.Format(Config.CommandPrefixes.RConCommand, convertedRConPassword, "status\0").Select(Convert.ToByte).ToArray();
|
waitForResponse |= true;
|
||||||
break;
|
payload = (Config.CommandPrefixes.RConGetInfo + '\0').Select(Convert.ToByte).ToArray();
|
||||||
|
break;
|
||||||
|
case StaticHelpers.QueryType.COMMAND_STATUS:
|
||||||
|
waitForResponse |= true;
|
||||||
|
payload = string.Format(Config.CommandPrefixes.RConCommand, convertedRConPassword, "status\0").Select(Convert.ToByte).ToArray();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this happens when someone tries to send something that can't be converted into a 7 bit character set
|
||||||
|
// e.g: emoji -> windows-1252
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
connectionState.OnComplete.Release(1);
|
||||||
|
throw new NetworkException($"Invalid character expected when converting encodings - {parameters}");
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] response = null;
|
byte[] response = null;
|
||||||
|
Loading…
Reference in New Issue
Block a user