Client Anti Cheats: Aren't as bad as you think!

it reminds me of this post


I do like this tutorial though, I will rely on both client and server sided anti cheats (though exploiters are more powerful than us developers)

5 Likes

I wouldn’t use any methods here. They are unstable and can be spoofed easily. Honeypotting only works once before everyone finds out.

5 Likes

Hackers can hook on events sent by a localscript, so with a local anticheat, hackers can’t be banned using kick. An attempt to let a script kick the player by using a remote instead can be blocked too by hooking it and returning wait(9e9).

Correct me if i’m wrong, but to me it looks like local anticheat isnt gonna do its job with these possibilities for hackers.

3 Likes

This method makes the whole script variable nil, was this intentional?

2 Likes

Are exploiters able to read the contents of a script that does this?

2 Likes

Yeah it was, to hide the script

Believe us or not, it actually works

3 Likes

Well if they can’t find the script in the first place it would be a little complicated, wouldn’t it be?

1 Like

Client code is hidden and the server sends and tells the client to run it’s compiled version instead.

1 Like

Yes, they can indeed do that. They can indeed yield the script. However, the handshake will see that the script isn’t sending remotes anymore and will kick them. The same case applies to errors. However, you can also detect them and not just wait for the handshake. Take this simple script, for example:

local Players = game:GetService("Players")
hookfunction(Players.LocalPlayer.Kick, newcclosure(function(...)
    return 
end))

A possible way to detect this would be:

local Success, Error = pcall(function()
    Players.LocalPlayer.Kick(workspace)
end)

if Success then
   print('Detected hook!')
end

or this hook:

local Old
Old = hookmetamethod(game, "__namecall", newcclosure(function(self, ...)
   local Method = getnamecallmethod()
   if self == LocalPlayer and Method:lower() == "kick" then
      return
   end

   return Old(self, ...)
end))

Can be detected by using

local Success, Error = pcall(function()
    Players.LocalPlayer:KICK()
end)

if Success then
   print('Detected hook!')
end
5 Likes

Yes, this is indeed intentional; it allows the script to be hidden from the environment itself. This also hides it from getnilinstances(), dex explorer, and such.

5 Likes

I’m interested in how you’d go about introducing keys and encryption to the handshake events, as there is no built-in cryptography modules and it’s possible for the client to just read the keys or the code on how to construct the key.

I’m not a cryptography pro by any means, so I apologise in advance if I seem unsure

1 Like

The keys should, of course, be dynamic, so an exploiter couldn’t just RemoteSpy, get the key and replicate the handshake.

You could make your own encryption and decryption functions in order to use them (or you could find one one the dev forum)

3 Likes

I’m aware yeah, they should be dynamic, but even then, could they not bypass the getfenv removal of the script in the environment, and then get the method for creating the key?

1 Like

The key itself should be created on the server, given to the client, and sent back to the server in an encrypted version; I would guess you meant getting the key.

They could tamper with the getfenv function to prevent the script from deleting itself; however, most environment hooks I know of just do not return the script itself when calling getfenv, so you could detect it by checking if getfenv().script.Parent errors.

1 Like

I’ve created a rough concept, with the same idea, so it’ll generate a GUID using httpservice on the server, and when the player joins they get sent it and every time they send the handshake, it checks with their token they sent and the one the server has. It seems to work but I feel like if someone made a listener for the event the token could be caught.

Essentially it will work up until the point where the exploiter has enough time to make a listener script and then sends that event periodically. A method to catch this (although clunky) could be to time how long it takes to send the event, and if it doesn’t line up with how it should, you could kick them. However this does rely on the user’s performance in terms of internet bandwidth and client performance as they could be slower/faster depending on those factors.

Sounds good.

3 Likes

What about saveinstance()? Does it also get around that or?

2 Likes

Yes! It also goes around saveinstance() which is pretty neat for hiding the anti-cheat script itself from the client.

6 Likes

Well that’s good, appreciate it!

5 Likes

Did you create TCP Handshakes, with SYN, ACK, FIN, and RST? Nice!

Now, I got my Computer snarkiness out of the way.

Background about me:
Currently, studying for my SANS GFACT Certification with the NCSF (National Cyber Scholarship Foundation), an entry-level certification to understand cybersecurity terminology and methodology. I am also, studying for CCNA and CompTIA NET+.

Anything on the client side can always be stolen, decrypted, exploited, etc. because the client needs to decrypt and intercept data (from packets, and frames) to display stuff on the screen/display properly.

Client-side is anything the end user or client sees. The way attackers exploit or infiltrate is by understanding the application layer. This can be XSS (Cross-Site Scripting), SQL injections, XMF, LFI, RFI, etc.

If the server side doesn’t sanitize/serialize data, you have a potential vulnerability. If you ever get into offensive security, if you find an error. Then, you exploit it to see what you can get.

But, a major flaw with client-side anti-cheats is their aggression. Every program/code, function, etc. uses CPU (or processor) cycles, the more your run the program/function, the less power the CPU (or processor) has. Don’t be aggressive while trying to battle cheaters/exploiters, it only harms the gameplay or performance of other users.

A few years ago, I had the same idea, thought, or intention as you. Thinking anti-cheats will fix x, y, and z is a fair idea, but how you execute it is where it really comes into effect. If you create an anti-cheat that checks if a player is not on the ground for x seconds, and you run this every second, sounds fantastic, at first. Until, you realize if a player jumps off this high building, cliff, or block, it triggers the anti-cheat and kicks them (or however you handle it). Checking if they are flying every second wastes time and processing power. Instead, check if they are flying when they kill someone or when they get points/rewards.

If you are still reading, I want to think about the following? Why does the same exploit work on other games and not just yours? The exploiter uses a program that affects Roblox’s engine, not your just game. 99.9% of the exploit used wasn’t developed for just your game.

I want the development community to switch gears (and their mindset) on how to handle exploiters/cheaters. Think passively and not actively. If the cheater kills someone on the other team at their spawn? Then the cheater gets no points. Don’t waste time or processing power on small groups of people, instead focus on improving the gameplay and adding new features to keep the community engaged.

16 Likes

Could you break this down? A bit confusing, this is roblox!

FireServer? This is roblox

3 Likes