Over the summer i’ve taken up reverse engineering and strengthened my C skills. I tend to see a lot
of misinformation in threads regarding exploits, and now knowing how they work I felt it was time to make everything clear and help developers in preventing them.
Firstly to clarify:
yes, I have reversed Roblox to write an exploit to mess around with their Lua to get a feel for how it works. I don’t plan on ever publicly releasing my exploit nor using it for cheating in actual games. I just wrote it simply for learning purposes.
First: what types of exploits are there?
There’s a lot of exploits that exist for Roblox. The most popular are script executors, since they allow you to do almost anything you want without restrictions.
There’s 3 main types of ways that exploiters achieve script execution, but they’re not too important to helping you develop counter measures.
Second: why doesn’t Roblox do more to prevent exploiters?
After seeing their security measures, I know they implement as much as they can to prevent exploiters. The only reason there’s so much exploits
is because of smart and dedicated people in the community who work together to bypass Roblox’s checks, such as louka, eternal, defcon, ect.
Roblox doesn’t do more to prevent exploiters simply because they can’t without risking breaking a lot of games, or it would require sketchy UAC privelages, which might make people think that Roblox is a virus.
The anti-exploit development mostly comes down to you, as the developer. You understand your game the best and therefore can prevent exploits the best on your game.
To clarify some things before moving on:
1. It’s near impossible to detect an expliot by just injecting it. Roblox does do this, but it’s actually not the hardest to get around.
Some exploits are however detectable upon injection, we’ll cover that in a bit.
2. Roblox actively tries to stop exploiters. That’s why theres updates every week, to basically shuffle important info that you’d need to get an exploit working.
3. Roblox can’t just check if an exploit’s window is open. It does check for certain windows, but most exploits will just randomize their window name.
4. You have to write your anti-exploit around detecting scripts instead of exploits themselves.
5. Filtering Enabled is not a one fixes all solution. All this does is prevent exploiters from replicated stuff to the server without revsere engineering anything.
6. Asset & script stealing is near impossible to prevent. Remember: anything that the client uses can be seen by exploiters, so don’t be dumb about what you let them see.
7. Exploiters CANNOT see server script code. It’s not replicated to them, so you can hide a lot of check inside them.
Section 2: different types of exploits
There’s 2 main types of ways that exploiters can mess with your game.
Firstly: client script executors. These are the most common. These are the ones that just run only on your client and have to find a way to actually exploit your game. Some examples are Synapse X, Sentinel, Tempest, JJSploit
Second: server script executors. These are often abbreviated as “SS”, short for server-side. These ones are much more rare, and typically only happen through developer stupididty. If you take a look at the front page models in the catalog, you’ll see pages full of SS’es, or “backdoors”.
Backdoors work by having a server script that listens to the client, and typically will execute commands, or even full on scripts. These are much more dangerous since they don’t have any filtering, and can easily get your game locked if you don’t prevent them, like what we saw with MeepCity and tubers93
Backdoors are usually hidden away far inside some script, so this is why you should check over every script a free model uses if you’re using FMs.
Exploiters often try to conceal their backdoors behind obfuscated code, but i’ve never seen one be actually smart about it. An easy way to tell if something is backdoored is if you see obfuscated code, or just Ctrl + F and search for “require” and it’s hidden away.
To prevent backdoors/SS’es is very simple, be sure the free models you use are clean, and the plugins you install are from actually verified developers.
Preventing client exploits is a bit more complicated, but i’ll explain how to below.
Section 3: how to write your anti-exploit
As i stated previously, Roblox puts most of the anti-script execution work on you. This is because only you understand your game’s workings best, and therefore know what a player should and shouldn’t be doing.
You want to start by relying on the server almost ENTIRELY for your anti-exploit. I’ve seen way too many people just paste an anti-RC7 script into the client, which an exploiter could literally just delete and then be off the hook.
However, if they don’t have a backdoor, an exploiter cannot delete a server-sided anti exploit.
You should start by error logging. We’ll use this to our advantage in a bit to detect a lot of poorly written scripts.
We need to connect an event to log whenever an error occurs. We then can use the message and script parameters that it passes to determine if it’s an exploit. However, we need to use this on the client because of Roblox’s replication boundary, so be sure to hide this code deep inside some large client scripts you use!
game:GetService("ScriptContext").Error:connect(function(message, stack, scriptFrom) game:GetService("ReplicatedStorage").ConsoleError:FireServer(message, scriptFrom:GetFullName()) end)
Then you need to create a remote event in ReplicatedStorage called ConsoleError. This will now log whenever somebody errors. To prevent false positive bans, you should send the errors to some server and manually review it to determine if they should be banned.
The scriptFrom parameter uses getFullName, because most scripts that exploits execute will be parented to nil, so look out for that.
Now, let’s make a lot more scripts that exploiters use error!
This is fairly simple, but should be done before you write anything else for your game as it could break your own scripts on accident.
We’re going to randomize the names of a lot of DataModel children that scripts use. This will require a bit of work to write your game’s scripts with, but it’s worth it. (i promise)
You can put this script in either a server or client script, it doesn’t really matter. But if you put it inside the client, be sure to destroy the script after it runs.
game:GetService("Lighting").Name = tostring(math.random()) game:GetService("Workspace").Name = tostring(math.random()) game:GetService("ReplicatedStorage").Name = tostring(math.random()) game:GetService("Players").Name = tostring(math.random()) game:GetService("ReplicatedFirst").Name = tostring(math.random())
This will now randomize the names of commonly used services in exploit. However, this could easily break your entire game if your scripts aren’t correctly written.
To fix this, you should use game:GetService(“ServiceName”) instead of game.ServiceName. It’s good practice too anyway
Now, if an exploiter executes a script that uses game.ServiceName, it’ll error, and you can catch it much easier!
But, what if they execute something such as:
game:GetService(“Players”).LocalPlayer.Character.Humanoid.WalkSpeed = 100
Wow, that’s not good. We shouldn’t check the walkspeed on the client, because remember that an exploiter could just delete a client sided anti-exploit.
We should write a distance checker on the server. Every time interval, we check how far a player’s moved. If they move further than they should’ve in a certain amount of time, they’re probably using some sort of speed hack.
game:GetService("Players").PlayerAdded:Connect(function(plr) spawn(function() -- open a new thread so we don't waste stuff on the playeradded connection repeat wait() until plr.Character -- Give the character some time to load wait(2) local normalWalkspeed = 16 -- This is your player's normal walkspeed, which Roblox defaults to 16. If you use something different, be sure to change this. local lastPosition = plr.Character.HumanoidRootPart.Position while wait(4) do local newPosition = plr.Character.HumanoidRootPart.Position local distTravelled = (newPosition - lastPosition).magnitude -- See how far the player's walked. local distError = 2 -- Allow some error in the distance if just for some reason the player does this -- We check every 4 seconds, so the player should have AT MAX, travelled 4 * 16 studs if ((distTravelled - distError) > 4 * normalWalkspeed) then -- Check if the distance - error is further than they should've walked. warn(plr.Name.." is probably speed hacking, they travelled", (distTravelled - (4 * normalWalkspeed)),"studs more than they should've!") end end end) end)
This should lead as an example of what you should do to prevent exploits for your games.
Some other examples are:
If you have a money remote, did the player award themself an insane amount of money?
If you have a money remote, make sure that it will only affect the player who fired it, and nobody else.
If you have a cup/item giver, make sure that a player can only give themself the item a certain amount of times per second.
This concludes my guide on how exploits work & how to prevent them. I’ll update the thread later with more examples and in-depth descriptions, but I hope this can guide you to making your Roblox game more secure against exploiters.
Remember that most people who’ll exploit your game are script kiddies who just paste stuff off of V3rmillion, and hardly know what they’re doing, so you’ll probably have an advantage.
Leave any feedback in the replies, I hope to hear how I can help you or improve this thread.