Exploiting and how to prevent it

Hello! This is my first topic and hopefully you like it.

This topic will explain what is exploiting, how to prevent exploiting, what are backdoors and different exploits! This is a bit long.

Let’s dive on the Roblox dangers!

What is Exploiting?
There are all kinds of exploits on Roblox. These exploits allow you to execute code, they are called script executors. You can execute different code. There are other different exploits too. These executors can be used to give the player infinite health or more unfair advantages. These inject on the client. These exploits are third-party programs.

Different types of exploiting

DLL Exploiting

DLL Exploiting is another type of exploiting, where you can inject a custom DLL file on the client, and these give the client unfair advantages and these scripts can do malicious action. A common way of injecting DLL files is through script executors, some of these work by injecting a DLL file on the game memory making it possible for the client to execute code. You can also use a DLL injector. These DLL files have data or scripts and some of their actions are: altering player stats, see through walls, walk faster and more. These can modify game behavior.

Backdoors

These are not exploits, but they are dangerous, these backdoors are found on malicious free models and malicious plugins. These backdoors are hidden scripts inside different models and plugins by attackers. Backdoors give the attackers administrative privileges and the ability to perform dangerous actions. These scripts can be obsfucated making it harder to find backdoors. A infamous example was the ROFL virus, which is found on free models. Backdoors can massively lag your game too.

Script Executors

This exploit allows the client (the client is the PC when playing, this client allows you to walk and chat) to execute Luau code on your client, it is possible for backdoors or in a really rare instance to execute code on the server, there are ways to execute scripts like Bytecode Conversion, Proto Conversion and other ways. Here is a example of a script executor:
Picture1

UI Script Executors

This is a custom script, it uses Script Executors to execute scripts, these have commands like flying, changing walkspeed and these are executed in the click of a button. You just click each different command. A example of this is the Ultimate Trolling Gui, these UI Script Executors can be executed by scripts using require() too. Here are videos of trolling Guis: click here, click here, click here, click here.

Lua wrapping

Lua wrapping is an exploit that manipulates the Lua virtual machine (VM) to execute code. This exploit can be done by taking advantage of vulnerabilities in the Lua runtime or by manipulating different aspects of the virtual machine (VM).

Remote exploitation

This exploit can log and fire RemoteFunctions, RemoteEvents and BindableFunctions. A popular exploit is RemoteSpy. There are security measures you can add, these include basic ones to advanced ones, like honeypots and encrypting.

Game exploration (Dex)

This is the last exploit, known as Dex Explorer, this can view game stuff, this is essentially the Explorer on Studio but for every game. Luckily, server-side scripts cannot be viewed or modified. Here is a video of the Dex explorer for educational purposes: click here

We learned different types of exploits. Now, we will learn how to protect ourselves against these exploits.

Exploit Protection

Before we start, keep in mind, scripts cannot be 100% secure, but this will make it more difficult for exploiters to exploit your game.

Backdoor protection

The most simple thing to do is simply not get free models/plugins.
But, what if you really need those for your game?
Well, here is how to protect yourself against backdoors:

When getting a model or plugin, look at the like/dislike ratio. When the model has a ton of dislikes, it may have a backdoor!

Look at the creator, is the creator an unknown and shady person or a trusted one? If the creator is shady, it is a red flag but when the person is a known exploiter and may have several other disliked models, do not trust the creator.

Let’s say you are looking for something that needs no script, like a sky image, but the model has a script, you should be suspicious.

When getting a model/script, always look at the scripts it has, look for any suspicious code, search up the lines require() and getfenv(), some models need these, but if a suspicious model have these somewhere in a part, model or somewhere else, you should be suspicious.

Also, be suspicious when you see obsfucated code, one example could be this: 101\411\501\711\311\101\411\, this is obsfucated, you can use a Beautifier for obsfucated code.

I do not recommend free models, if they have inappropriate hidden things like backdoors or other ToS breaking stuff, your account may get banned or deleted.

Secure your RemoteEvents/RemoteFunctions

To prevent tools like RemoteSpy, you should secure RemoteEvents and RemoteFunctions. Here is a video that may help you out: click here

Never trust the client

The client should never be trusted. You should store sensitive data on a server-side script, only aesthetic scripts can be trusted with the client. You should still take steps to secure your game scripts. The client can be a exploiter, not always a regular player.

Obsfucation

Make sure to obsfucate code, there are tools online to help you, but the most common obsfucation is renaming variable and function names, removing helpful comments. I always put all of my obsfucated code on Line 1 to confuse exploiters even further, I also use trash code insertion (putting fake comments). This is to prevent Dex Explorer users from understanding your code. Also, tools can drastically down performance, trust me, I got crashed because of one obsfucated code.

Anti-cheats

You should make a anti-cheat, it should be server-side, since client-side scripts can easily be deleted. There are several techniques used for these anti-cheats. It is your choice on what anti-cheat to make, but i recommend server-side anti-cheats.

Use HTTPS

Are you communicating to a API or website inside of your code? Make sure the website is HTTPS, this encrypts all data transmitted. This is a HTTPS website: https://devforum.roblox.com/ HTTP websites are not secure as HTTPS ones.

Regularly update your code

Exploiters are always finding new hacks, and Roblox is always trying to patch the new hacks. Keep your code up-to-date with the newest updates and patches.

Use anti-exploit measures

All of these combined would make a secure game. Always look for these measures and add them. They are important for your game.

About loadstring()

Enabling loadstring() poses a serious security risk as users can run code on the client-side. Only enable this, if needed, and secure this as much as possible when enabled. So, only enable it when fully needed and know the risk.

Honeypots

Before we start, keep in mind, honeypots are basic and should not be relied on and make sure to read this entirely for code and troubleshooting tips. Honeypots are fake RemoteEvents/RemoteFunctions with attractive names such as GiveMoney, KillPlayer or other names. The goal is to trick the exploiter to fire the honeypot. The honeypot will ban the user when fired. Boom! The exploiter got tricked!
Here is a honeypot that may work for you:

-- Made in IWasTaked0
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")

local bannedPlayersDataStore = DataStoreService:GetDataStore("BannedPlayers")

local something = Instance.new("RemoteEvent")
something.Name = "GiveClicks"
something.Parent = game.ReplicatedStorage

something.OnServerEvent:Connect(function(player)
    bannedPlayersDataStore:SetAsync(player.UserId, true)
    player:Kick("This experience is shut down. Please try rejoining")
end)

Players.PlayerAdded:Connect(function(player)
    local banned = bannedPlayersDataStore:GetAsync(player.UserId)
    if banned then
        player:Kick("This experience is shut down. Please try rejoining")
    end
end)

You need HTTP Requests and API Requests on!

This worked for me on Studio! This will ban your user ID even when rejoining! Test this on a test baseplate.

This script makes a RemoteServer called GiveClicks, parent of ReplicatedStorage and when fired, it bans the userID and saves their ID on a DataStore, when they to rejoin, they are still banned!

You need to make a script in ServerScriptService, and put this script, then fire the RemoteEvent using Command Line, here is a script that may work:

local remoteEvent = game.ReplicatedStorage.GiveClicks


remoteEvent:FireServer("lol", 1)

Did not work? Here are troubleshooting tips:

  1. Do the above steps exactly as mentioned.
  2. Run the code on Command Line, not Developer Console. Enable it at the View tab.
  3. Enable API Services and HTTP Requests on Game Settings
  4. Rename the honeypot to the actual name, you can change it on the script, just change something.Name = "YourNameHere"
    5. Lastly, make sure you are running it with your actual honeypot name. For example: if you have changed the name from GiveClicks to GiveMoney doing this: something.Name = GiveMoney then make sure and change the code to this for it to work:
local remoteEvent = game.ReplicatedStorage.GiveMoney


remoteEvent:FireServer("lol", 1)

The best part is that you can make more RemoteEvents by simply duplicating the script and changing the name!

How can I make a good honeypot?

  1. Convincing error message
    For me, this method is good. If the error messge said: “You have been banned for cheating!”, the exploiter will know the honeypot and come back on a alt, but with a error message like “Game closed for update”, the exploiter is more likely to believe the fake error message.

  2. Convincing name
    The goal is for the exploiter to fire it? A name like GiveMoney can attract the exploiter, events with names that promise to give them in-game currency are likely to be fired.

Client-side/Server-side Validation

Let’s say you have a shop. In your shop, there is 1 Rebirth that costs 20 Coins. But, you do not validate the purchase, so the server is like “Yes, this user has enough coins to buy this rebirth.” and gives it to the client. But, the user actually had no coins. The client has managed to manipulate the server. We need to validate these purchases.

Here is a script with no validation:

-- Made by IWasTaked0
local RebirthNVButton = script.Parent

local function onRebirthNVButtonClicked()
	local player = game.Players.LocalPlayer
	local leaderstats = player:WaitForChild("leaderstats")

	leaderstats.Rebirths.Value = leaderstats.Rebirths.Value + 1
end

RebirthNVButton.MouseButton1Click:Connect(function()
	onRebirthNVButtonClicked()
end)

You probably knew this did not check the user balance when clicked. There are other not validated scripts out there. You should never use this for purchases. Anyone will get 1 Rebirth free without paying 20 Coins.

Here is a example of the script:

Here is a simple validated script:

-- Made by: IWasTaked0
local RebirthVButton = script.Parent

local function onRebirthVButtonClicked()
	local player = game.Players.LocalPlayer
	local leaderstats = player:WaitForChild("leaderstats")

	
	local coins = leaderstats.Coins.Value
	if coins < 20 then
		warn("You don't have enough coins to purchase a rebirth.")
		return
	end

	
	leaderstats.Coins.Value = coins - 20

	
	leaderstats.Rebirths.Value = leaderstats.Rebirths.Value + 1
end

RebirthVButton.MouseButton1Click:Connect(function()
	onRebirthVButtonClicked()
end)

This now checks the Coins to make sure the user has 20 or more before rebirthing. If less than 20, the user gets warned.

Want to learn more? Join a test game here

Script Using

Using this? Make sure to keep my comment! Put the LocalScript as a Child of the button. Please note that this is a button clicking script and may need to be modified for your game. Here are troubleshooting tips:

Troubleshooting tips

Not working?
Make sure to change leaderstats name to your leaderstats name.
Put this exactly as mentioned.
Change the button name on Line 1 from RebirthVButton to your button name.

Working, but only takes 20?

local coins = leaderstats.Coins.Value
	if coins < 20 then
		warn("You don't have enough coins to purchase a rebirth.")
		return
	end

	
	leaderstats.Coins.Value = coins - 20

Change 20 to the amount that you will buy.

Test your code

Let’s say you have finished a massive project for your game. This is a important aspect of your game. Before uploading the new changes, make sure to always test the new aspect, not only for workingness but for security too. Do things that a exploiter would do, do not exploit inside of your game, it is bannable.

For aspects of your game that give one-time rewards like codes:

Can people redeem the code more than one time?

Can people abuse the system to get more rewards?

Can people redeem the code more than one time WHEN REJOINING?

What has Roblox done against these exploits?
I know some of you do not like Roblox when it comes to preventing exploits. But, this will prove you wrong.

Roblox anti-exploit efforts

Roblox has done a lot against exploits. The include FilteringEnabled, a dedicated security team to patch exploits, continuous updates and fixes, their Byfron anti-cheat and more security measures.

Roblox is working on exploit patching and other issues about exploits. When a new vulnerability is discovered, a team of engineers should develop a fix to address the issue.

Once a fix is released, a dedicated exploiting team always attempts to bypass the fix and exploit the vulnerability again. This exploiting team is made up of hackers and experienced hackers. The team has tons of resources, a lot of people and experienced people quickly bypass the fix.

If the team did not care, the exploiting problem would get infamous, but they have made it more difficult with FilteringEnabled and with other security mesures. Very nice. If any Roblox team member/staff sees this, thank you for your hard work. :cowboy_hat_face:

FilteringEnabled

This filters out any action by the server. This makes it more difficult for the client to abuse the server. Luckily, this is enabled by default.

This took me a long time to make! Thanks for reading!

Make sure to point anything wrong or any suggestions on the comments!

Updatelog
Update 1. Release.
Update 2. Small text changes.
Update 3. Honeypots added and small text changes.
Update 4: Small text changes on honeypots.
Update 5: Some links included to help people know more about exploits, more soon including a image added.
Update 6: Poll added
Update 7: Attracting honeypot tutorial added
Update 8: Server-side/client-side validation added and tags added
Update 9: Roblox security measures added
Update 10: Testing your game for exploits added

Should I keep updating this? (when I have free time)
  • Yes
  • No

0 voters

Should I keep this on Community Tutorials
  • Yes, keep it
  • No, change it to Community Resources

0 voters

Did I explain honeypots and validation well?
  • No, the explanation sucked!
  • Yes, good job!

0 voters

44 Likes

You need a DLL injector for Backdoors and for exploiting in general plus most script executors use a DLL injector.

1 Like

Yep, just decided to add it separately for organization, what do you think of this? This is my first topic and opinions are appreciated. Please point out any errors I have made, not an exploiting god here.

1 Like

Its pretty nice, and very organized.

1 Like

Thank you! I would have added more, but I was lazy haha! Took hours. lol

1 Like

Thanks to everyone for their support!

1 Like

Where should I put this? Is this the right place to put this topic into?

1 Like

this has a few flaws,

  1. only having a server-sided anti-cheat isn’t the best, you can detect so much more on the client and it takes 1 line of code to stop exploiters from deleting the script
  2. the loadstring thing doesn’t make sense since exploiters can run any code they want on the client even if loadstring isnt enabled
  3. renaming variables in your script to random stuff won’t do anything since all exploiters see variables names as when decompiling is “v1, v2, v3”

other than this it seems alright

1 Like

not sure if community tutorials might be better

3 Likes

It’s funny that people that are reusing this ridiculous claim are the ones that are creating a client anti-cheat. You cannot hide anything on the client, not sure where you got this from but it’s not true. A simple script.Parent = nil can easily be bypassed by a getnilinstances() call.

Hello there, honestly, it was my opinion, but you can do it however you want, about the loadstring(), the command is dangerous, since it allows arbitrary code to be run when not secured properly, and lastly naming your variables v1 is better than naming it purposefully (When obsfucating, thank you for reading though)

2 Likes

loadstring() is perfectly safe unless you literally have a remote that calls it from the client, it can only be used on the server so there’s really nothing to worry about. Just make sure there’s no backdoors and you’re fine.

script.Parent = Instance.new("FunctionalTest")

¯_(ツ)_/¯
Client-side anti-cheats work perfectly well you just gotta know what you’re doing, a good start would be looking into metamethods and how hooking works

1 Like

If you would like me to actually believe you then provide evidence. Not trying to be mean but I always see client anti-cheat developers spreading this random propaganda about methods to hide local scripts. Again, it wouldn’t be so hard to create a client modifier to let me see everything locally. Not going to do that but it’s very possible.

synapse only gets nil instances not parented ones lol

1 Like

Then why a FunctionalTest? You literally missed my point.

idk just chose that randomly lol

1 Like

Then it won’t work. I suggest doing some research on how the client-server model works.

I’ve tested it and it works, it hides the script from both dex and getnilinstances() unless syn patched it alr

The FunctionalTest is parented to nil, so here’s some code to bypass it quickly.

local instances = getnilinstances()

for index, value in instances do
	if value:IsA("FunctionalTest") then
		for _, antiCheat in value:GetChildren() do
			if antiCheat:IsA("LocalScript") or (antiCheat:IsA("Script") and antiCheat.RunContext.Name == "Client") then
				antiCheat:Destroy()
			end
		end
	end
end