Я делаю античит для игры, и хотелось бы узнать какие есть уязвимости в нем, чтобы их исправить, и напиши как их исправить:
Project Zomboid Anti-Cheat Types
So, I've taken the liberty of exploring Project Zomboid's anti-cheat types, since they seem to have been fairly stable in recent updates.
There are some additional anti-cheat measures implemented into the game outside of the main controllable types but these are the main ones.

It is important to note that none of these checks run if any of the following conditions is true:
Co-op mode is enabled.
The player is in debug mode (unless the doKickInDebug flag is set).
The player is not fully connected.
The player is privileged.
The player has god mode enabled.

The types are as follows:
Type 1: Hitting Players/Vehicles
This check makes sure you don't hurt someone that you shouldn't be able to, specifically, it will fail if any of the following is correct:
The victim is in god-mode.
PVP is disabled in Server Options.
Either the victim or the attacker have safety enabled (when the safety system is enabled in Server Options).
Either the victim or the attacker are in a non-PVP zone.
The victim or the attacker are in the same faction, and faction PVP is disabled.

Type 2: Speed Check
A simple, raw speed check that verifies that the player or their vehicle is not going too fast. For vehicles, it uses the speed limit in the server options, and for players, it uses an hardcoded value of 10.

Type 3: Distance Checks
Only runs when a player hits another player, a vehicle or a zombie. Makes sure you don't try to hit something from too far away.
This check is split into two types, the long distance and the short distance check.
Long Distance
Verifies that the distance is below:
Code:
UdpConnection.RelevantRange * 10.0 * type_3_multiplier
Even if the check fails, the player will only be kicked if they are marked as suspicious (more on this later), otherwise it only adds an infraction point.
Short Distance
Verifies that the distance is above:
Code:
10.0 * type_3_multiplier
Kicks the player otherwise.
Type 4: Damage Checks
Verifies that the player does not cause damage above:
Code:
101.0 * type_4_multiplier
Kicks the player otherwise.

Type 5: Zombie Owner Check
In the ZombieHitPlayerPacket packet, verifies that the player sending the packet is the network owner of the zombie, as long as the network owner of the zombie has not changed in 2000ms.
This check also only kicks the player if the player is marked as suspicious, and only adds an infraction point otherwise.

Type 6: Zombie Target Check
In the ZombieHitPlayerPacket packet, verifies that the player sending the packet is the target of the packet. The player is kicked otherwise.

Type 7: Safehouse Authorization Check
In the ZombieHitPlayerPacket packet, kicks the player if none of the following conditions apply:
The safehouse has no owner (set to null or empty string).
The player is the owner of the safehouse.
The player is a moderator.

Type 8: Packet Authorization Check
Checks if a player is "authorized" to send a certain packet based on the action that they represent, unless the player is in debug mode or privileged.
Individual packets can be set to one of three policies: log/kick/ban. However, at the current time, it appears that all packet types are set to kick. This may change in the future.

Type 9: XP Growth Check
A check that runs every-time update is called and checks if the player's XP growth since the last update exceeds the following threshold:
Code:
1000.0 * sandbox_vars.XpMultiplier * type_9_threshold
If the player does exceed the threshold, they get kicked. If they only exceed half the threshold, it gets logged instead.

Type 10: Unknown Packet Check
Simply kicks the player if UdpEngine receives an unknown packet from the player.

Type 11: Unused
This isn't used anywhere in the entirety of the game's code-base, unless I'm missing something major.

Type 12: Access-Level Abuse
Kicks the player if they are spoofing/abusing their accessLevel.

Type 13: Invalid PacketType Check
Kicks the player if the game receives a packet with an invalid PacketType that gets parsed to null.
If this happens to you, you're probably sending malformed packets.

Type 14: Invalid player in AddXp
Closes the connection sending the player if they don't have a valid player in the AddXp packet. Check UdpConnection.havePlayer for details.

Type 15: XP Limit in AddXp
Kicks the player if they try sending an AddXp packet with an amount above the following threshold:
Code:
1000.0 * sandbox_vars.XpMultiplier * type_15_multiplier
Logs if the player sends the packet with an amount above half of the threshold. Notably, the only difference in the actual threshold amount is the type-specific multiplier.

Type 16: Starting Fires when Disabled
One of the checks in the StartFire packet, kicking the player if they send the packet while ServerOptions.NoFire is set to true.
Note that this check does not run if the smoke field on the packet is set to true.

Type 17: Valid Fire Squares
Inside of the StartFire packet, this check verifies that the square specified is fit for a fire (e.g. not water). For details, see IsoFire.CanAddFire, which includes a complete list of the checks on a specific square. The player is kicked if this check fails.
This check also does not run if the smoke field on the packet is set to true.

Type 18: Valid Smoke Squares
Another check in the StartFire packet, verifying that the square specified is fit for smoke (somewhat similar checks). For details, see IsoFire.CanAddSmoke. The player is kicked if this check fails.
This check only runs when the smoke field on the packet is set to true.

Type 19: Valid Safehouse for Syncing
A check in the SyncSafehousePacket packet, that assures that the player sending the packet has a safehouse in the first place when they send it. The player is kicked otherwise.

Type 20: Invalid Safehouse Details
A check in the SyncSafehousePacket packet, that only runs if the player sending the packet is a user (unprivileged) and either the weight or height exceed the threshold:
Code:
100.0 * type_20_multiplier
If the above fields are invalid, the player is kicked.

Type 21: Checksum
Kicks the player if they fail the checksum check in ValidatePacket.
The checksum is constructed in the dumbest way available, using the registered recipes:
Code:
   private long calculateChecksum(UdpConnection var1, int var2) {
      if ((this.flags & 4) != 0) {
         var1.validator.details.clear();
      }
 
      CRC32 var3 = new CRC32();
      CRC32 var4 = new CRC32();
      ByteBuffer var5 = ByteBuffer.allocate(8);
      var3.update(var2);
      ArrayList var6 = ScriptManager.instance.getAllRecipes();
      Iterator var7 = var6.iterator();
 
      while(var7.hasNext()) {
         Recipe var8 = (Recipe)var7.next();
         var4.reset();
         var5.clear();
         var4.update(var8.getOriginalname().getBytes());
         var4.update((int)var8.TimeToMake);
         Iterator var9;
         if (var8.skillRequired != null) {
            var9 = var8.skillRequired.iterator();
 
            while(var9.hasNext()) {
               Recipe.RequiredSkill var10 = (Recipe.RequiredSkill)var9.next();
               var4.update(var10.getPerk().index());
               var4.update(var10.getLevel());
            }
         }
 
         var9 = var8.getSource().iterator();
 
         while(var9.hasNext()) {
            Recipe.Source var14 = (Recipe.Source)var9.next();
            Iterator var11 = var14.getItems().iterator();
 
            while(var11.hasNext()) {
               String var12 = (String)var11.next();
               var4.update(var12.getBytes());
            }
         }
 
         var4.update(var8.getResult().getType().getBytes());
         var4.update(var8.getResult().getModule().getBytes());
         var4.update(var8.getResult().getCount());
         long var13 = var4.getValue();
         var5.putLong(var13);
         var5.position(0);
         var3.update(var5);
         if ((this.flags & 4) != 0) {
            var1.validator.details.put(var8.getOriginalname(), new PacketValidator.RecipeDetails(var8.getOriginalname(), var13, (int)var8.TimeToMake, var8.skillRequired, var8.getSource(), var8.getResult().getType(), var8.getResult().getModule(), var8.getResult().getCount()));
         }
      }
 
      return var3.getValue();
   }
Type 22: Checksum Time-out
Kicks the player if they don't respond to the checksum check in time. The timeout for the checksum check is: (in milliseconds)
Code:
10000 * type_22_multiplier
Type 23: Time Multiplier Check
Kicks the player if their time multiplier is different than the one on the server when GameTime.receiveTimeSync is called.

Type 23: Time Multiplier Time-out
Kicks the player if they don't respond to the time multiplier check in time. The timeout for the time multiplier check is (in milliseconds)
Code:
10000 * type_24_multiplier
Suspicious Players/Infraction Points
The anti-cheat uses infraction points/marks players as suspicious for some types, resulting in actions that don't immediately kick you.
At the moment, the anti-cheat only kicks you if you've accumulated over four infractions, otherwise, it simply adds another infraction point:
Code:
   public boolean checkSuspiciousActivity(String var1) {
      if (this.suspiciousActivityCounter < 4) {
         ++this.suspiciousActivityCounter;
         this.latestSuspiciousActivityDescription = var1;
         DebugLog.Multiplayer.warn("SuspiciousActivity increase: counter=%d %s", this.suspiciousActivityCounter, var1);
      }
 
      return this.suspiciousActivityCounter >= 4;
   }
Every 150,000 milliseconds, a single infraction point gets deduced from your record, down to 0.

Additional Notes
Writing this quite late at night, I've most definitely missed a thing or two - so let me know if you have any questions, I'll be happy to reply.
This is up to date as of Project Zomboid 41.78, which means it will probably change in the next update - I'll try to update this thread or post a new one if necessary depending on the changes.
If anything is wrong or misleading, please let me know so I can correct the thread.

Have a nice day! (: