A Guide to Making Proper Anti-Exploits

Just edited this post from over a year ago to adjust my response. os.clock() is actually quite performant, and should be used over os.time() in most circumstances since it is a lot more accurate (by a lot!).

Original reply

Interesting, this is the first I’ve heard of this :thinking:

Good to know! However, I mentioned using tick since os.clock is intended for benchmarking.

If tick has plans for deprecation, then replace os.clock with os.time. Clock is used for benchmarking because it’s extremely precise, but with sacrifice to performance. os.time will function quite well for your needs!

1 Like

os.time returns an integer whereas os.clock does not. When precision is needed, what shall I use when tick is deprecated?

out of personal preference os.clock has generally been my go-to since os.time doesn’t have the precision I desired to make cooldown periods like 0.5 but it is good to only use either dependent on the level of precision required.

I also found the post where tick's deprecation was mentioned:

  • tick() sounds perfect - it has a high resolution (usually around 1 microsecond), and a well-defined baseline - it counts since UNIX epoch! Or, well, it actually doesn’t. On Windows, it returns you a variant of the UNIX timestamp in local time zone. In addition, it can be off by 1 second from the actual, real UNIX timestamp, and might have other idiosyncrasies on non-Windows platforms. We’re going to deprecate this in the future.
5 Likes

This is a bad and incorrect advise, os.time should not be used for calculating delta times as it is only accurate up to an integer.

@Reapimus time() should be used in favor of tick(). It is constantly updated per physics simulation frame as it is based on physics simulation. So if physics slow down in your game, time will also update slowly which is ideal for calculating delta times as you’ll be taking in account of low physics frame rate when calculating delta time and thus helping out a bit in preventing false positives.

Here is a chart for better understanding:

10 Likes

in the case of the speed check, yes that would certainly be a better choice, I definitely believe that os.clock is the better choice in the case of a cooldown period for an attack or skill usage of some form because I don’t believe it is slowed down by performance issues.

Also that chart looks useful, where is it from?

1 Like

Your usecases are correct and the chart is from here.

3 Likes

Thanks for this chart. I’ll use this in the future!

Does anti-cheats can be tested in Studio if I change something on client?

2 Likes

I made this one and it’s about anti-speed/teleport (and noclip). Though the code is messy, it achieves what it promises to do. An unbypassable, high accuracy detection for games that do not have anything that pushes the player (other than walkspeed).

Emphasis on unbypassable because it’s probably the reason why it’s listed. Though yes, the script uses data given by the client, if you understand how it works, you will say otherwise. Every data from the client is validated on the server at some point, they can’t be modified, which also means, it’s unbypassable. Other than this, I can’t seem to think why it was listed.

1 Like

It has it’s own problems because of the client. If your game starts getting frame drops, I noticed that you had a higher chance of getting kicked, also that when there was network lag it kept spamming “Detected” in the output.

2 Likes

the problem still lies that you are relying purely on the client to provide this data, the client is able to manipulate any and all data it sends, it doesn’t matter if it is being validated on the server, the fact that the server is trusting that the data sent from the client is the issue.

This was a fact I specifically called out in my explanation of what exploits can access. Don’t underestimate the power exploits wield over the data on their clients.

1 Like

In this case, they are not relying/trusting on the client.
Using information≠Trusting information.

Sending data through remotes is no different than having it directly replicate via physics, it doesn’t matter how the data is replicated, it matters how it’s handled.

This \ / ignores basically everything about security, you have to always use some information from the client, if you don’t then its impossible to connect to a server.

Sending the data through a remote is no different than sending it directly through physics, if we use your argument here, then all server sided anti-cheats would also by “bypassable”, because they “rely” on the Roblox physics data which is sent from the client.

If we take this argument to the extreme, then a player wouldn’t be able to even connect to a Roblox server because apparently “it doesn’t matter if it is being validated on the server”.

His anti-cheat is no different than any other “fully serversided” anti cheat, because both use the same physics data, other is replicated directly via physics, other via remotes. Both verify the data. (It doesn’t matter how the the data is replicated, what matters is how its handled.)

2 Likes

While this is a good post and I very much admire it.

This one doesn’t really have that much problems. And it definetly doesn’t have a core issue. Yes it did have some bypasses but those were patched, and it also sometimes false detects.

However I think you are sort of misunderstanding what trusting the client really means (or you didn’t check out his anti cheat thoroughly).

1 Like

I suppose that is so but my point may have been misunderstood just a small bit, the issue I see with his is that the server is trusting the client to send a legitimate character position, and on top of that, trusting that the client’s connection is near flawless and otherwise causes too many false positives if they are lagging as was pointed out by @Judgy_Oreo in his reply

The thing about purely checking from the server-side and relying on the position of the player’s character and information only the server controls is that it leaves no room for the client to lie and no room for the client lagging to cause that many false positives.

As far as I’ve seen, looking through the code for their anti-cheat, is that it never validates the truthfulness of the position the client is providing, meaning that all the exploiter would need to do to effectively bypass it is start making the client-sided ended of it send only the last position it was at, effectively tricking the server into believing they just aren’t moving at all

Would it be a good idea to have certain anti-exploits in important localscripts, so if they were to disable/delete it, it would be game breaking?

I mean if cheaters can access all local scripts code they can just erase anti-cheat part of code.

1 Like

I can’t say for 100%, but I am pretty positive that they can’t just erase a few lines of the code. Although, they are able to completely read/delete the whole localscript.

they can most definitely do this, all they need to do is copy the source of the localscript, modify that, and then create an exploit that deletes your localscript and replaces it with their own. As stated in my guide, you should only be using a client-side anti-cheat if it is also being supported by a server-side anti-cheat.

I do believe it is a common misconception that placing the anti-cheat code within important client-side code will protect it, security through this method or obscurity is never actual security.

4 Likes

You can use a server script to access it too.

local suspicious = {}
game:GetService('RunService').Heartbeat:Connect(function()
     for i, player in pairs(game.Players:GetChildren()) do
        local humanoid = player:WaitForChild('Character'):FindFirstChild('Humanoid')
        local speed = humanoid.WalkSpeed
        -- If they are going too fast:
        table.insert(suspicious, player)
        -- This is more like 2 step verification where the server adds them to a table and keeps checking to see if the problem persists. 
        -- You can loop through the suspicious table via while wait() loop outside the RunService function. You can double check through the other for i, v... loop and then kick the player.
end) 

I’ve never tried this but just asking.
Is a script in StarterCharacterScripts considered client sided?

1 Like

This is a very useful tutorial and I will keep all your advice in mind when making my games. Thanks for the contribution.

1 Like