Add some logging for suspicious HitMessages (#459)

* Add some logging for suspicious HitMessages

* Add HitPositionDiscrepancyThreshold config settings

* Add hit position discrepancy check to LashMessage & SplashHitMessage

* Whitespace
This commit is contained in:
Mazo 2020-05-26 21:17:19 +01:00 committed by GitHub
parent e51e970e51
commit 11a01b038f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 5 deletions

View file

@ -12,14 +12,14 @@ import scodec.codecs._
* @param player na
* @param victim na
* @param bullet na
* @param pos na
* @param hit_pos na
* @param unk1 na
*/
final case class LashMessage(seq_time : Int,
player : PlanetSideGUID,
victim : PlanetSideGUID,
bullet : PlanetSideGUID,
pos : Vector3,
hit_pos : Vector3,
unk1 : Int)
extends PlanetSideGamePacket {
type Packet = LashMessage
@ -33,7 +33,7 @@ object LashMessage extends Marshallable[LashMessage] {
("player" | PlanetSideGUID.codec) ::
("victim" | PlanetSideGUID.codec) ::
("bullet" | PlanetSideGUID.codec) ::
("pos" | Vector3.codec_pos) ::
("hit_pos" | Vector3.codec_pos) ::
("unk1" | uintL(3))
).as[LashMessage]
}

View file

@ -248,3 +248,12 @@ NetSim.ReorderTime = 150 milliseconds
# yes - (Enabled)
Active = no
[antihack]
# HitPositionDiscrepancyThreshold (int)
# Description: The distance (squared) threshold that triggers if the reported hit location of a shot does not match the object being hit's location on the server
# Range: [1, 1000000]
# Default: 10000 (sqrt 10000 = ~100 ingame units)
HitPositionDiscrepancyThreshold = 10000

View file

@ -45,6 +45,9 @@ object WorldConfig extends ConfigParser {
),
ConfigSection("kamon",
ConfigEntryBool("Active", false)
),
ConfigSection("antihack",
ConfigEntryInt("HitPositionDiscrepancyThreshold", 10000, Constraints.min(1), Constraints.max(1000000))
)
)

View file

@ -5,7 +5,10 @@ import com.github.mauricio.async.db.general.ArrayRowData
import com.github.mauricio.async.db.{Connection, QueryResult}
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import net.psforever.WorldConfig
import org.log4s.{Logger, MDC}
import scala.annotation.{switch, tailrec}
import scala.collection.mutable.LongMap
import scala.concurrent.{Await, Future, Promise}
@ -6213,6 +6216,7 @@ class WorldSessionActor extends Actor
case Some(hitInfo) =>
ValidObject(hitInfo.hitobject_guid) match {
case Some(target : PlanetSideGameObject with FactionAffinity with Vitality) =>
CheckForHitPositionDiscrepancy(projectile_guid, hitInfo.hit_pos, target)
Some((target, hitInfo.shot_origin, hitInfo.hit_pos))
case _ =>
None
@ -6238,6 +6242,7 @@ class WorldSessionActor extends Actor
//direct_victim_uid
ValidObject(direct_victim_uid) match {
case Some(target : PlanetSideGameObject with FactionAffinity with Vitality) =>
CheckForHitPositionDiscrepancy(projectile_guid, explosion_pos, target)
ResolveProjectileEntry(projectile, ProjectileResolution.Splash, target, target.Position) match {
case Some(projectile) =>
HandleDealingDamage(target, projectile)
@ -6249,6 +6254,7 @@ class WorldSessionActor extends Actor
targets.foreach(elem => {
ValidObject(elem.uid) match {
case Some(target : PlanetSideGameObject with FactionAffinity with Vitality) =>
CheckForHitPositionDiscrepancy(projectile_guid, explosion_pos, target)
ResolveProjectileEntry(projectile, ProjectileResolution.Splash, target, explosion_pos) match {
case Some(projectile) =>
HandleDealingDamage(target, projectile)
@ -6270,11 +6276,12 @@ class WorldSessionActor extends Actor
case None => ;
}
case msg @ LashMessage(seq_time, killer_guid, victim_guid, projectile_guid, pos, unk1) =>
case msg @ LashMessage(seq_time, killer_guid, victim_guid, projectile_guid, hit_pos, unk1) =>
log.info(s"Lash: $msg")
ValidObject(victim_guid) match {
case Some(target : PlanetSideGameObject with FactionAffinity with Vitality) =>
ResolveProjectileEntry(projectile_guid, ProjectileResolution.Lash, target, pos) match {
CheckForHitPositionDiscrepancy(projectile_guid, hit_pos, target)
ResolveProjectileEntry(projectile_guid, ProjectileResolution.Lash, target, hit_pos) match {
case Some(projectile) =>
HandleDealingDamage(target, projectile)
case None => ;
@ -11397,6 +11404,14 @@ class WorldSessionActor extends Actor
}
}
def CheckForHitPositionDiscrepancy(projectile_guid: PlanetSideGUID, hitPos : Vector3, target : PlanetSideGameObject with FactionAffinity with Vitality): Unit = {
val hitPositionDiscrepancy = Vector3.DistanceSquared(hitPos, target.Position)
if(hitPositionDiscrepancy > WorldConfig.Get[Int]("antihack.HitPositionDiscrepancyThreshold")) {
// If the target position on the server does not match the position where the projectile landed within reason there may be foul play
log.warn(s"Shot guid ${projectile_guid} has hit location discrepancy with target location. Target: ${target.Position} Reported: ${hitPos}, Distance: ${hitPositionDiscrepancy} / ${math.sqrt(hitPositionDiscrepancy).toFloat}; suspect")
}
}
def failWithError(error : String) = {
log.error(error)
sendResponse(ConnectionClose())