Thank you to everyone who contributed to the post! It was kinda hard to decide who to give the solution to: my final picks was CodedJer’s and Ihaveash0rtname’s posts but it eventually came down to Ihaveash0rtname’s posts
For any future readers, I found a really nice post by Reapimus
VERY IMPORTANT Can anyone tell me how I’d actually start making the anti-cheat and if that’s how top games would make an anti-cheat. If you’re answering this specific question, you can quote this (btw thank you for everyone who has already contributed )
As the title suggests, how would I start developing a goodSERVER SIDED anti cheat? Many others have asked this question too so I guess I’m also speaking on their behalf.
I know that people who do know how to develop effective anti-cheats don’t usually share their knowledge. And that’s why as someone with no experience; it’s pretty damn dang confusing and practically impossible to create a good anti-cheat.
Now obviously anti cheats depend on the game. Like in [Roblox] Bedwars, their anti-cheat targets stuff like flying, no-clipping, and other stuff that another game’s anti-cheat wouldn’t be focused on.
I’ve seen a whole bunch of posts that provide basic insight into the topic; but none really have helped me understand the topic much.
And before someone asks, yes I’m aware and actively use server sanity checks.
I’m thinking about making a FPS game in the future so that’s what I’ll base the below with. So here’s what I’m kinda needing help with:
List of things I need someone to help explain:
Help explaining handshakes
How to start creating the anti-cheat
How to detect no-clipping
How to detect position tampering (like flying)
How to go about detecting an injection
Pretty dumb question but: would the anti-cheat be in a module script? And if yes, would it be in “OOP style”?
More advanced techniques that the big games use
Other stuff:
What stuff to give network ownership to the client and what stuff to give to the server
Links to DevForum posts, code snippets, and or explanations (simplify them if you can ) are the most helpful!
But any sort of insight or help is very much appreciated by me!
Thank you to everyone who shares something
Are you confident in your “anti-cheat making skills”?
Yes
No
I don’t know
0voters
Things I’ve learned from this topic so far that I didn’t know before:
Handshakes (they can yield a lot of false positives if the player lags and it doesn’t ping the server but still should ping every interval of 60 seconds)
Dealing with position tampering
Hacker bait remotes →
How to start the anti-cheat (the main goal of the post overall)
Hard to say anything about this without getting jumped by 20 people telling you, you can’t stop hackers. I guess hackers have a fan club now. I would just start with a basic test system. Something that tests values vs what they should be.
That’s true. I’m not really expecting to keep up with the latest bypasses from the big guys (Synapse X, Krnl, etc).
Just to keep those “NEW EASY INFINITE CASH EXPLOIT WORKING 2023 ROBLOX” people out.
Edit: I said I didn’t want to keep up much, that doesn’t necessarily mean that I didn’t want to protect my future game from Synapse users. Just not all the time
If an exploiter wants to delete any of local scripts you may use 2 local scripts (1 may be used with any in-game mechanics) and the second. When any of the script deleted (any of 2) The method :Destroying will trigger and Kick an exploiter. I don’t know if it would work but it’s as a suggestion.
P.S. It any of 2 should detect script injection.
all ways check the roblox version and kick people using the microsoft version its or a serverside checker, checking every second to see any difference without a remote or any system being runned( this is my thought on this topic)
something like this would stop that in it’s tracks
local transactionCooldown = {}
local function validateTransaction(player, amount)
if typeof(amount) == "number" and amount >= 0 then
local currentTime = tick()
local lastTransactionTime = transactionCooldown[player.UserId] or 0
if currentTime - lastTransactionTime >= 5 then
transactionCooldown[player.UserId] = currentTime
player.Currency = player.Currency + amount
player:SendNotification("Currency updated: " .. player.Currency)
else
warn("Transaction rate limit exceeded for player: " .. player.Name)
end
else
warn("Invalid transaction for player: " .. player.Name)
end
end
game:GetService("ReplicatedStorage").ValidateTransaction.OnServerEvent:Connect(function(player, amount)
validateTransaction(player, amount)
end)
Checked out a few videos on this to see what you were talking about. Seem this always comes down to force firing a remote that was set up off a menu (GUI).
Restricted Area
local LockedRoom = game.Workspace.LockedRoom
local RequiredItemName = "Key"
LockedRoom.Touched:Connect(function(hit)
local character = hit.Parent
local player = game.Players:GetPlayerFromCharacter(character)
if player then
if not hasRequiredItem(player) then
player:Kick("You need a key to enter this room.")
end
end
end)
function hasRequiredItem(player)
local character = player.Character
if character then
local backpack = player.Backpack
local characterItems = character:GetChildren()
for _, item in pairs(characterItems) do
if item.Name == RequiredItemName then
return true
end
end
if backpack then
local backpackItems = backpack:GetChildren()
for _, item in pairs(backpackItems) do
if item.Name == RequiredItemName then
return true
end
end
end
end
return false
end
Different cash trap
local MaxScoreIncreasePerSecond = 100
local function detectSuspiciousScoreIncrease(player)
local lastScore = player.leavingScore or 0
local currentTime = tick()
local timeElapsed = currentTime - player.joinTime
if timeElapsed > 0 and (player.Score - lastScore) / timeElapsed > MaxScoreIncreasePerSecond then
player:Kick("Suspicious behavior detected.")
end
player.leavingScore = player.Score
end
game.Players.PlayerAdded:Connect(function(player)
player.joinTime = tick()
end)
game.Players.PlayerRemoving:Connect(function(player)
detectSuspiciousScoreIncrease(player)
end)
Speed trap
local MaxMovementSpeed = 100
local function detectSuspiciousMovement(player)
local character = player.Character
if character then
local humanoid = character:FindFirstChild("Humanoid")
if humanoid then
local currentSpeed = humanoid.WalkSpeed
if currentSpeed > MaxMovementSpeed then
player:Kick("Suspicious behavior detected.")
end
end
end
end
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
detectSuspiciousMovement(player)
end)
end)
Hacker bait remote
-- Server-side script
local BaitRemote = Instance.new("RemoteFunction")
BaitRemote.Name = "AddCoins"
BaitRemote.Parent = game.ServerScriptService
local function checkForBan(player)
local shouldBan = false
if shouldBan then
player:Kick("You have been banned for unauthorized actions.")
end
end
BaitRemote.OnServerInvoke = function(player)
checkForBan(player)
end
Basic outline to a ban datastore
-- Server-side script
local DataStoreService = game:GetService("DataStoreService")
local BanDataStore = DataStoreService:GetDataStore("BanDataStore")
local function isPlayerBanned(player)
local success, banData = pcall(function()
return BanDataStore:GetAsync(tostring(player.UserId))
end)
if success and banData then
return true
else
return false
end
end
local function banPlayerByName(playerName)
local playerToBan = game.Players:FindFirstChild(playerName)
if playerToBan then
local success, error = pcall(function()
BanDataStore:SetAsync(tostring(playerToBan.UserId), true)
end)
if not success then
warn("Failed to ban player: " .. error)
end
playerToBan:Kick("You have been banned from this game.")
else
warn("Player with name " .. playerName .. " not found.")
end
end
game.Players.PlayerAdded:Connect(function(player)
if isPlayerBanned(player) then
player:Kick("You are banned from this game.")
end
end)
-- Example: Ban a player by name
local playerNameToBan = "UsernameToBan"
banPlayerByName(playerNameToBan)
These are all sever side scripts that do checks for hacking.
Each one of these I would add to permeant ban list.
Protip: don’t trust people who say “don’t rely on client”, these people are not professional and do not see the potential of client anti-cheats when used properly.
Their potential? Their only potential is to stop unexperienced exploiters. If your game is small and gets no visits then sure rely on a client-sided anti-cheat… however, once your game gets big people will bypass it and upload the script for others to use.
You could do a lot on a client, and I do support @weakroblox35’s comment.
You could use a remote event client & server and if the client is deleted then the server brings a copy from server storage to the player that doesn’t have the script. You could also camo the script name so it could look like a built in Roblox player script. And you could obviously protect your anti cheat remote event. Clients do have potential.
It has potential only as long as it isn’t bypassed, which it will. Maybe won’t get bypassed if your game is very very small, but if it is moderate then it’s a waiting game until a bypass gets released somewhere.
Client-sided anti-cheats is a game of mouse and cat. They bypass it, you patch, and they bypass it again… not a good thing for big games huh
Generally, if you are okay with wasting your time on a client-sided anticheat when you could’ve made a reliable server-sided one, go for a client one.
Could be bypassed in a matter of minutes. There are a lot of methods to protect your client sided anti-cheat since I’ve myself used one for a long time and maintained one (and more, I used to work on anti-cheats for bigger games than mine), but ever since creating my own server one I stand with my opinion and experience
But my client idea I suggested would also work well with an independent server anti cheat. As when the exploiter tries to delete the anti-cheat in player scripts it’s going to keep coming back and you can’t do anything about it because it would be recloned on server and there’s not a lot you could do. But of course, protect the remote event as well.
This script would not take long at all. I suggest on top of this you could put a simple alt detection as well. And another addon to the client system that checks if the screengui of a player is being tampered with, also banning the names of Orion which is a popular script hub I’m pretty sure some exploiters use. And the banning of any screengui named Dex. Or anything similar.
There is a lot you can do here. But clients should still be considered as a plan B. And not thrown in the garbage acting as clients can’t do anything.
a DescendantAdded-based function can automatically delete those
Remote-spy, figure out what the remote does, then use that knowledge to bypass it
Good point, I use that for my anti-cheats as well.
Yeah this is definitely handy and something server cannot do, however it can still be sadly bypassed. I did use this but believe me that having to patch a bypass every moment gets tiring.
Agree, it is effective against exploiters that cannot script and don’t have a big knowledge. But they can figure out a bypass by googling for it (if it exists)