How you should secure your game - A beginner guide for secure networking and developing anticheats

No because it would be done server sided.

Server generates token for dataset
Server sends only the token to the client
The client makes a request using the token
The token contains the embedded dataset. The server generates a new token using data gathered from the client request (e.g. client supplied or other data like time).
The server compares the tokens and if they match the request is granted.

1 Like

Can’t they overwrite the OnClientInvoke / OnClientEvent though?

1 Like

Yes. The token restricts what they can use it for though. It works due to the fact that they cannot access the server’s private key therefore they cannot forge these tokens.

The token has two components. One, the private key. Two, the “generalized” data.

Here’s some example psuedocode:

-- Client
local myToken, myTimeDiff = receiveSomeEvent()
sendSomeEvent(myToken, myTimeDiff, myData)
-- Server
function makeKey(timeDiff, theirTimeDiff)
    timeDiff = timeDiff or theirTimeDiff
    return sha256(privateKey..":"..math.min(theirTimeDiff, timeDiff)) -- If timeDiff is greater than theirTimeDiff it will become theirTimeDiff therefore the verification will pass.
end
function verify(token, otherTime, criteria)
    local curTime = os.time()+tick()%1
    if makeKey(curTime-otherTime, criteria) == token then
        return true -- Key is valid
    else
        return false -- Key is invalid
    end
end
sendTheKey(makeKey(nil, theirTimeDiff), theirTimeDiff)

local lastTime = 0
local function whenSomeEvent(token, theirSupposedTimeDiff, data)
    if token == makeKey(nil, theirSupposedTimeDiff) then -- Their token matches with the data criteria
        if verify(token, lastTime, theirSupposedTimeDiff) then -- Their token contains the correct criteria which we just verified so making a new token with the extra data we have gathered should succeed
            lastTime = os.time() + tick()%1
            doStuff(data) -- It succeeded
        end
    end
end

Pretty sure they can just use your functions or get myToken or anything else …

Like I’ve said that is known. The token is used for data verification. Of course they can intercept the token that doesn’t matter though because it is solely used as a way of verifying data.

I just want to make a note which I learned more recently: Because Heartbeat runs after physics it is actually more reliable to use Stepped which runs before. This prevents any odd delay between frames and will make rubber banding less of a problem.

5 Likes

How we can test our game without downloading any hacks??

Use the studio command bar. You can find it under the View tab, just write lua in it and it’ll run.

2 Likes

You can use a local script or modify your existing scripts. Exploiters can basically change the functionality of your code, so it’s pretty similar to just modifying your localscript.

2 Likes

Sorry for my clueness and extremely late response, but, how would we start a anticheat script? If its done on the server does that mean I have to send over the player on a localscript first?

I’m not sure what you mean. I generally keep my anticheats in ServerScriptService under their own script, and then I loop through all of the players in the game on Heartbeat/Stepped and I store information for each player in a table.

Oh yeah, sorry I completely forgot about that, thanks :slight_smile:

I would like to add onto the honey pots portion of this thread. There’s apparently a thing called “RemoteSpy” that can grab the arguments of a remote whenever it’s fired.

Let’s say you have a “BanUser” remote. If an exploiter is using a RemoteSpy script and they see that the remote event was fired with the argument “jessica_3592” (random name of a player that isn’t in the game), it’ll seem legit and the exploiter might think they can ban people.

Once it’s fired by the exploiter, possibly trying to ban someone in-game, add them to a banlist, or make them lose their stats and blame it on an ‘error’ or even better, wait(math.random(60,120)) Exploiter.Humanoid.Health = 0.

1 Like

Thing is remote spies only log :FireServer and :InvokeServer calls made by their client, plus if you are firing these at an arbitrary rate with fake names surely they will notice that and just know not to fire that remote with a real username.

I meant that the client itself would have a random script fire a random argument name. Possibly whenever a player leaves it could fire their name blankly?

And with a simple check (logging which player left, giving a few seconds grace period so non-exploiters aren’t banned) the server could detect who’s exploiting and who isn’t.

For advanced exploiters this is easily detectable, but for someone who downloads a free exploit and just wants to make a ban script they can get easily caught especially if they don’t know what they’re doing and if they don’t know “too good to be true.”

Also adding onto this further, what if I created an account on sites where people post scripts for certain games and I post a “ban script” for my game, but in the end it just logs whoever fires it? Easily atleast a few exploiters caught, possibly with their main.

1 Like

But they can decompile local scripts and see that you are doing this. And not sure what “fire their name blankly” means.

There are exploiters who know what they are doing even with free exploits, if it is a skid usually the scripts they copy accounts for anti-exploits for them, so /shrug

They can just read the code…if you think on obfuscating they can just deobfuscate it or just dump its constants and see what it does.

1 Like

I see what you’re saying but in general it’s bound to catch a few mindless exploiters. Implementing it can’t do any harm.

Surely, if skids know how to use a remote spy they will know how to inspect the arguments passed over.

If they notice any pattern that will just help them out even more.

Don’t trust the client.

Yep, this is 100% true! I’d say that tricking exploiters by firing remotes is actually a quite good way to at least catch people trying to reverse your game.

Personally I do think that an intelligent exploiter wouldn’t fall for something like you’ve suggested, but, that’s no big deal.

Here’s a little tip because exploiters have no way to stop this: pull a while true do :wink:
The thing is, modern exploits are very powerful and will and can allow for silent modification to everything down to the setting of very specific properties, or even manipulating active event connections. (I mean, hey, this stuff is documented by them! For example, Synapse currently has a very detailed documentation on their website, and it even tells you what not to do if you don’t want your scripts being detected… Yeah, that’s also a weak point for exploiters too haha)

This is the sole reasoning for my philosophy of “think of it like your script can be directly edited” because the behaviour of directly editing your script can be emulated in at least five or six ways usually. Hell, an exploiter can literally emulate your script’s original source under their environment with any modifications they want, so, even if its uncommon, they can literally edit your scripts.

Exploits are extremely powerful from a client perspective as to be expected! And this philosophy greatly simplifies that into something very understandable.

Here is a great way to catch exploiters. Plain and simple, sanity check. Always. If you have code that accepts something from the client that you can validate with 100% certainty, you can also use that validation. Even if it isn’t 100% certainty, there’s no harm in just reducing your reaction, for example, simply kicking! Vagueness is key, and as such, waiting a random amount of time, such as 30-60 seconds is absolutely, and entirely, something you should do when banning or kicking a player.

Someone reversing your game will be testing various things. Hell, you can even intentionally leave minor vulnerabilities in, but still detect them! If someone reversing your game tries something, they may likely respond with something like “Hey, this does something weird that isn’t intended! I’ll put this on my list for later.” A great example of this in use is in some sort of structure placement code. For example, placing invalid structures. Intentionally make structures that are harmless but appear to be specific to development if you want to! When someone uses these, make it seem like nothing is wrong. Then, after a while, ban the exploiter with a vague message, and they’ll be stuck having to redo everything to find what they can use. The more places this is possible, the more times they have to receive the ban to check. Think about how many times they’ll be doing captchas creating and logging into alts. The longer you wait, the better, as long as it isn’t too long because that means they might be able to get useful information. This is a brutal way to stop people reversing your games.

Lastly, as I mentioned before, while true do is the best form of client kick. In fact, rather than straight out kicking the user, give their client a little remote request a second or so before, maybe even hijack a valid loop! The result? The remote request won’t even be detectable a majority of the time This is, another, brutal way to absolutely 100% annoy the people exploiting your games. This also applies to skidding, obviously! Again, this falls into that idea of being as vague as possible, give them as little information as possible.

Also, uh, don’t fix this EVER please, Roblox, I mean it, because it’s hilarious and useful despite being very weird behaviour (PLEASE, this is too good), but, if you :Destroy() the player and delete their character when it gets added (I believe at the moment Roblox won’t even add their character if they’re connecting) or temporarily pause CharacterAutoLoads (and you should most definitely handle characters dying in the meantime or you’ll have a rare case of actually making someone’s character unloadable) you can get some very hilarious results over a kick. They will technically be connected to your game… And they will technically be connected… But… Remotes will stop working only for outgoing content (omg), they won’t show up in the player list, and they’ll still get replications and stuff. THEN you can send a busy loop to freeze their game, THEN you can kick them just for that extra bit of hilarity for the off chance that they get through ALL OF THAT DEBUGGING.

Before I get into this: This crash is actually a surprisingly safe crash it doesn’t do anything afaik and the method to invoke it is ridiculously convoluted so that’s probably why it’s existed for like 10 years (It actually got reported here too I think)
Another, REALLY fun way to mess with exploiters is to create fake (but real) Roblox crashes so they think they’ve goofed up their code (again, this is actually useful, and will never come up in real code, and I think will actually send Roblox memory dumps automatically for that extra goodness of getting people auto banned, please DON’T fix this issue, although, I can maybe see it still getting fixed anyway since it is technically a crash which is super sad). The easiest, and afaik most reliable and really the only way to do this ever, is to make an addition to the above (because like I said, things get weird) and take advantage of a character load mechanic, and before the Player’s character has loaded firstly set a character to a model (this causes funk I don’t understand to trigger the following epicness), then set the character to nil again, then wait for their actual character to load via CharacterAdded, then Destroy their Player, then literally just Destroy the Character to invoke the crash. This causes something with the LoadCharacter mechanism which only happens for the first character load to break and thus crash immediately with no warning. Sure its a crash but the method to cause it is so convoluted I am very much so hoping this never gets fixed (fun fact: this crash has existed since the earliest studio build publicly available iirc, or at least the 2007 build, again, iirc, so, it’s an OLD crash and afaik has never received a patch likely due to how simply convoluted it is to pull off).

Nonetheless, these are all methods I personally like to employ. In one of my little fun anticheat builds (because I like to make them) I randomly use crashing when a verified exploiter joins and is banned and delay the whole process so they think that their exploit messed up their game permanently, it’s quite fun to think about someone having to deal with everything I’ve done and having no clue any of it is actually them being messed with even if they find out one or two things.

13 Likes

I think the crash is insanely cool and please Roblox don’t ever patch it as I’ll be using it from now on. Honestly I’m shocked I found someone just as passionate about tricking exploiters.

I will definitely be adding your ideas of minor vulnerabilities to give the impression that my game is more vulnerable than it is, and just catching exploiters in the meantime if they decide to use it.

As of now, I have a datastore filled with exploiters (and most likely hundreds of their alts) that aren’t there from any possible false positives (because they’ve fired remotes that should never have been fired, etc). Whenever they join the game, I give them errors such as not being able to open the store, kicking them randomly 60-360 seconds and blaming it on a ‘Datastore error’, etc.

I also add random extra parameters to whenever I fire stuff from the client to the server. I know they can easily detect what I’m firing and copy it, but exploiters using free exploits they found online won’t be able to detect it unless they’re that dedicated. Which if they are, chances are they’ll end up falling for other honeypots I have placed in my game.

Besides having these large amounts of honeypots in my game, my serverside anticheat (using raycasts + magnitude) won’t ban users/kick them or give them random kick messages disguised as Roblox or my own errors, it’ll just rubberband them if they’re detected as teleporting, speed hacking, etc.

It’s almost fun to create tons of honeypots/random things to throw off exploiters trying to reverse my game as a normal player that isn’t exploiting will never have to see/deal with it. It’s like adding spikes and landmines around your castle as only the people raiding your castle will have to deal with them.

But anyways, thank you for giving me so many ideas. :smiley:

And another thing I’m not sure if you saw me reply with, looking for scripts used against your games on exploiting sites is a great way to detect your vulnerabilities. Instead of patching the vulnerabilities, rewrite the client code and let exploiters think the vulnerability is still there, just to lag them out/crash them/give them random errors.

3 Likes