Giving my players the best experience with a safe game

Context: So I just had a interesting talk with my friend today. We were talking about about game netcode. Something that came to my mind is how Roblox relates to thing with how you essentially communicate between a server and a client with RemoteEvents/Functions which kind of act like packets in real netcode. One big difference beside obvious things is how packets are encrypted with the game’s own method to keep the packets safe. In Roblox we always worry about somebody with a script executor firing our events with their own arguments. Maybe this has been done before, but what if we could make a way of encrypting data sent through RemoteEvents/Functions (e.g. sending a string that the client can decrypt and get a table with values out of it).

As said above, is it possible to do? Would it be worth doing? In theory it would protect the RemoteEvents/Functions because a cheater would have no way of knowing how to decrypt it. When they send this key that is incorrect we could kick them. If they found out how, you could just push an update changing the encryption method. Even if all the arguments of the RemoteEvents/Functions aren’t encrypted we could have the first one be a validation code that has to be correct to go through.

Any replies are appreciated!

3 Likes

Of course it would be possible to encode data before submitting it to the client, and then decoding it on the client, but this would be a bad practice. It will only make your life harder while debugging and an exploiter could still exploit your functions.

It is way better and more secure to make sure that you have proper checks in place on the server-side of your events. I would rather focus on this.

3 Likes

True, but what about this structure for the arguments of a (for example) RemoteFunction:

  • Arg 1: a string that is encrypted with the game’s own system
  • Arg 2: a table of random values that you are requesting or whatever value

The server (not as often the client as it wouldn’t be need) would check that first argument to be the correct code then if so, the server would use the values given after the argument #1.

Would that be more optimal?

EDIT: Also, how would exploiters still be able to breach the functions?

1 Like

The idea is, if your script can do it then so can an exploiter.
Let’s say you have something like this:

function network:Fire(...)
    remote:FireServer(Encrypt(...))
end

An exploiter can simply grab your network.Fire function and call it with what they want to fire. Doesn’t matter if it’s a method in a table or a dynamically-created local function.

1 Like

Oh, my bad. I meant like actually activate the functions and have them read/judged by the server rather than being denied at the start by their authentication code on the request being wrong.

I don’t really understand what you mean. The server cannot access nor check another peer’s functions.

Currently my system has (for example) a function fire an event to the server with some random arguments and, even though there isn’t a problem, I want to make it so if a cheater fires one of those functions, without even having success, it would punish them. The RemoteEvent would require the first argument to be a special key that only the server and some scripts on the client know. Every time the client needs to send data (via a RemoteEvent/Function) the server, instead of checking what the arguments are, would first check what the requests first argument was. In this proposed system, it would be that authentication key. If it is a real game process running the scripts would know the key and move along with reading the rest of the arguments. But if a cheater fires the function it would kick them no matter what if their key wasn’t correct. Even if the process they are trying to trigger has no outcome they’d want to happen. I want to achieve the best level of security I can and I haven’t seen this suggested, so I wanted to know if this was a bad idea. So far so good, I assume?

What I said still applies here: if your script can do that, then so can an exploiter.
You cannot check what script fired a remote either. You can only know that it’s been fired and see the args. There is no way to tell whether an exploit or a normal LocalScript did that.

I don’t think I’m understanding. Just to clarify: this key that the server would check the exploiter wouldn’t know. Even if it ins’t encrypted, if this key is stored in the code nothing can get it. I’m 90% sure if an exploiter found a way to copy your game (this has happened in the past ex: hilton hotels group place…?) it doesn’t save the scripts and if this key that is stored inside of a script at only some scripts at that can get to I don’t think it would be a problem. Exploiters can still fire the RemoteEvent, but when the server reads what the request was, it would check for that first argument being the correct key.

You’re wrong. An exploiter can read and modify all your local variables, global variables, table values, even roblox functions like print or warn (as long as they are on the client).

Let me give you an example to help you understand.
Let’s say you do this in your localscript:

local Key;
remoteFunc.OnClientInvoke = function(data)
    Key = Decrypt(data)
    return "secretpass"
snd

local inc = 0 --verified by the server
local function Fire(...)
    inc = inc + 1
    return remoteFunc:InvokeServer(inc, Encrypt(...))
end
local function Something()
    Fire("hello from the other side")
end

What an exploiter could do is something like this:

local Fire

for i,v in pairs(getgc()) do
    if type(v) == "function" and islclosure(v) do
        local upvals = debug.getupvalues(v)
        if upvals.Fire then
            Fire = upvals.Fire
            break
        end
    end
end

Fire("look, im a legit call!")

Note this is just an example. It wouldn’t ecactly work atm because luau strips local variable names. It’s just so you get the idea.

Oh I think I’m not explaining this correctly (sorry)!

Here’s how I imagined it would work. Imagine this is are functions in both scripts called Encrypt and Decode.

LocalScript:

game.ReplicatedStorage.Example:FireServer(Encrypt("wOwThIsIsAkEy"), "Example print!")

Server Script:

game.ReplicatedStorage.Example.OnClientEvent:Connect(function(key, printThing)
    if Decode(key) == "wOwThIsIsAkEy" then --Checks to see if the client has the correct key
        print(printThing) --Does whatever a normal event would do now
    end
end

EDIT: When writing this I remembered clients could spy on what their RemoteEvents/Functions were sending and print it. That is the reasoning for the encrypting.

That is almost exactly what Jailbreak does.
An exploiter can do the following things depending on whether you use the same key in multiple places or if it ever changes on the fly:

  • Grab your Encrypt function and the string you pass to it, then call it with the string and receive your key
  • Hook your Encrypt function to always intercept the newest key
  • Intercept FireServer/InvokeServer to do the same

and probably more.

Not saying this is a bad idea, but don’t expect it to be full hackers-proof.

1 Like

It is theoretically impossible (and practically too) to completely “encrypt” anything from a client to protect that information from the same client, since you can assume that client has access to all the same memory, functions and abilities that your own code does. It’s sort of like trying to trick your own brain by talking in code only you and the other party understands.

There is no point to this other than slowing down your netcode and making it harder to debug.

2 Likes

That stinks, well thanks for the help though. Now, I’m thinking there should be a property for LocalScripts to have a hidden source that only that own script can read. That would greatly improve the security of many Roblox games and possibly the method here could become very popular for 100% blocking out cheaters.

Again, even if this was included, it would be very easy for exploiters to read the contents of this hidden source container. The exploiter has the ability to read, modify, or send anything.

True. Quick question though: How do other games not experience what Roblox gets. Like for heavens sake, people can attach a 3rd party program to their Roblox process and start executing code at the client side. Why can’t Roblox do what other games do. You don’t see people in TF2, for example, being able to teleport around the map.

Actually, these games are still able to have code injected (though they’re considerably higher budget, keep in mind).

Likewise, the same freedom Roblox gives us to develop whatever we want is the reason that it is so open for exploiters to teleport, noclip and such. Other games don’t have to deal with all of these edge cases and can fine tune anti exploit detections far more precisely.

Please read these threads which I think will be explanatory:

4 Likes