Client Anti Cheats
They aren’t as bad as you think!
If you’ve been on the devforum for a while, you’ve probably already seen the saying, “Never Trust the Client”, alongside multiple reasons why you shouldn’t develop a client-sided anti-cheat.
Now, I am not going to say that this claim is 100% false; the client should indeed be considered as a secondary defense, with the server being the main focus for security. However, it is worth noting that some individuals on the DevForums may make such statements without having practical experience in developing anti-exploit measures. I bet that 90% of the DevForums users who make these claims have never actually attempted to create an anti-exploit system themselves.
So the point of this tutorial is to show you how the client-side can be secured. Let’s start with a simple method that prevents the anti-cheat script from being displayed in Dex Explorer and being disabled or deleted.
Environment Hide
A simple method to hide the environment of the script would be as follows:
getfenv().script:Destroy()
getfenv().script = nil
print("Hello World!") --> This will still run!
The following code deletes the script from its environment. This script will no longer show up in Dex Explorer, and it also cannot be accessed in order to disable or destroy it. It is also not visible in getnilinstances()
Handshakes
One of the most common reasons client-side anti-cheats receive criticism is due to how easily they can be disabled or deleted. While the environment hide feature can take care of preventing it from being disabled or deleted via DEX, exploits are still capable of hooking a function that the script uses and causing it to yield. This is where handshakes come into play.
A handshake is basically the client sending a RemoteEvent to the server every few seconds to validate its still alive. If the server doesn’t receive the RemoteEvent within a few seconds, the client will get kicked. Here’s a simple example on how to implement this:
Usually, you would use keys and encryption so that exploiters aren’t just able to replicate the handshake. However, this is a simple example, so it will be a simple FireServer.
--> Clientside
while task.wait(5) do
Remote:FireServer() --> You would normally use keys and encryption to aovid exploiters just replicating this loop
end
--> Server Side
Remote.OnServerEvent:Connect(function(Player)
PlayerData[Player].Handshake = tick() --> Reset Handshake Tick
end)
--> In a while loop check PlayerData if the handshake time is over lets say, 30 seconds
if tick() - PlayerData[Player].Handshake > 30 then
Player:Kick("Communication Timed out") --> The client was most likely disabled or the event was blocked
end
This is a very simple example of a handshake; a more advanced one will, as mentioned already, use keys and encryption to make sure an exploiter won’t just be able to replicate it cough cough aston v1 cough cough
Conclusion
There are many more ways to secure the client via tamper checks, such as Property Spoofing, namecall tampering detections, and more, that I will not go into detail with in this tutorial. This tutorial is mainly supposed to show that the client isn’t just a little script that is helpless and unable to be protected. Client anti-cheats are actually good, especially when combined with server anti-cheats.
Thank you @HexadecimalLiker for helping me with this post and for allowing me to make the joke about aston version 1
Please excuse me for any grammar mistakes I might’ve made; show me where it is in a PM, and I’ll fix it!
“Never trust DevForum members.”