Exploit Prevention (Version 1)

This topic briefly describes exploit prevention measures.

This sentence was translated using Google Translate. If there is something wrong with the text, please DM me.


What is an exploit?

Roblox developers, anyone who has played Roblox for a long time will know.
Exploits make this possible:

  1. Teleport hack.
  2. Speed hack.
  3. No clip hack.
  4. Money farm.

What can do with an exploit?

Exploits can execute local scripts.
So you can change the WalkSpeed property of Humanoid.

But with that, All this can be prevented by program.

How to prevent?

1. Use magnitude to prevent Teleport hack and Speed hack

magnitude is a function of Vector3.
You can use magnitude to monitor the speed of the player.

Sample code

function CheckTeleport()
	if HumanoidRootPart == nil then return Kick() end
	
	local PositionFirst = HumanoidRootPart.Position
	
	delay(1, function()
		local PositionSecond = HumanoidRootPart.Position
		
		if (PositionSecond - PositionFirst).magnitude >= 140 then return Kick() end
	end)
end
while wait() do
	CheckTeleport()
end

I recommend creating this script for each player.

There is a point to note here.

Do not run this in a local script.
Local scripts can be deleted with an exploit.

2. Use anti-exploit for prevent noclip hack

But never insert anti-exploit from the toolbox!

The anti-exploit present in the toolbox is likely a backdoor.
Search on devforum and use the code you find.

3. don't misuse RemoteEvent (RemoteFunction) for prevent money farm

It is no exaggeration to say that all games use RemoteEvent.
However, there may be holes in this RemoteEvent.

Code example:

--Server side code

local AddMoneyEvent = Instance.new("RemoteEvent",game.ReplicatedStorage) --Create RemoteEvent
AddMoneyEvent.Name = "AddMoney"

AddMoneyEvent.OnServerEvent:Connect(function(Player)
	Player.leaderstats.Money.Value = Player.leaderstats.Money.Value + 100 --Add money to Player
end)
--Client side code
local MoneyBagClickDetector = workspace.MoneyBag.ClickDetector --MoneyBag is assumed to be created on the client side

MoneyBagClickDetector.MouseClick:Connect(function()
	game.ReplicatedStorage.AddMoneyEvent:FireServer()
end)

Don’t use code like this!

The exploiter can execute the client code.
The exploiter uses this code in this case:

for i=0,100 do
	game.ReplicatedStorage.AddMoneyEvent:FireServer()
end

There are ways to prevent this.

  1. Measure the distance to the Money Bag.
  2. Check if the event is spammed.
  3. Issue an ID on the server side when the player joins the game, send the ID as an argument when sending an event, Kick if wrong (if possible)

I created this because the tutorial did not exist when I searched for exploit prevent in Devforum.
If you have any questions, feel free to reply.

12 Likes

I did some searching and found an existing thread about this: How you should secure your game - A beginner guide for secure networking and developing anticheats

Please don’t do this, it’s very easily bypassable and inflates network usage.

But a real player could spam the event by clicking really fast, this would leave to false positives.

2 Likes

If someone is spamming something that can only be used once, it’ll work just fine.
Actual players won’t be able to click every render stepped (Every frame) or even every stepped (Every 2 frames I think), so as long as its a pretty small cooldown you shouldn’t run into false positives.

Or just add a client-sided debounce since you don’t often want people to spam stuff.

1 Like

The only thing that you need to check on server is if the player did meet the requirements. In this case is if player is close enough. You should also consider not to use ClickDetector on client unless it’s attached to object that was created by the client.

Like @LexiDog5 said, id based checking is pointless and easily bypass-able, don’t waste time on doing that, it does only 2 things, which is consuming your time and network usage.

Checking if the event was spammed is pointless too, as player could’ve lagged while clicking on around 10 money bags, which would cause false positives, don’t do that either.

So conclusion is, use Script instead, money bags are usually collect-able by all players.

local MoneyBag = script.Parent -- your money bag
local ClickDetector = Instance.new("ClickDetector", MoneyBag) -- a new click detector
ClickDetector.MouseClick:Connect(function(Player) -- listen for clicks on money bag
	Player.leaderstats.Money.Value += 100 -- add 100 money to the player
	MoneyBag:Destroy() -- remove the money bag
end)

And another reason why you should not make money bags client sided, is that they can be easily teleported to the player, and server would think that player is close enough to the money bag. So exploiter could just easily teleport all client sided money bags to himself and get money for all of them.

If you want to have good protection against exploiting and you want only a certain player to see the money bag. Hide the bag and prevent click detection on other clients, this will still make money bag seem non-existing to other players while server will have full control over the money bag while keeping exploiters away, as they can’t do anything server sided. And also mind checking if the player that clicked was the one that was allowed to.

1 Like

If you will not use the click connection than disconnect it bc it takes memory

It won’t take the memory as the ClickDetector gets destroyed, and the connection does too. Correct me if I am wrong.

No, it doesn’t disconnect the event that was already connected and fire

I am pretty sure that connections get disconnected automatically once the object gets destroyed.

Yes, as long as you actually use :Destroy().

Don’t use delay() or wait() in your code, it’s considered code smell / bad practice. Instead, you can do a throttled RunService.Stepped loop:

local Step = game:GetService("RunService").Stepped

local function throttle(n, func)
    local iterations = 0
    return function(...)
        iterations += 1

        if iterations >= n then
            iterations = 0
            func(...)
        end
    end
end

local connection
connection = Step:Connect(throttle(20, function(total, delta)
    -- once player leaves, make sure to do connection:Disconnect()
end))

This way, you also have access to the time between each frames. (I chose Stepped because it fires before the physics happens each frame. However, you can replace it with Heartbeat if you want.)

2 Likes

Yes, since ClickDetector is child of MoneyBag, all children of MoneyBag will be destroyed as well the connections that were made. So that concludes this misunderstanding here.

No…
It doesn’t gets disconnected once it gets destroyed


check output…

Because the script is still running, and why we are still arguing about this?

Because I am right, and it has nothing to do with the script wth, you don’t know anything clearly
Putting it inside will print the same.
image

local con
con = workspace.Part.Touched:Connect(function()

	workspace.Part:Destroy()
	print(con,type(con))
end)

Please don’t say that I don’t know anything. Don’t mention my knowledge. You are not me, so you don’t know what I know and what I don’t know.

I’ve asked @Legoracer, and he had agreed. I am not sure why it still printing it, but I am sure that the connection is still removed at some point.

This isn’t proving anything.

That is not correct, the connection does get disconnected.

local con
con = workspace.Part.Touched:Connect(function()

	workspace.Part:Destroy()
	print(con.Connected) -- false
end)
5 Likes

No I am sure it doesnt disconnects

1 Like

Why are you still arguing?
3 people are telling you that what you saying isn’t correct. Read some posts and rethink your argument. I won’t continue arguing with you.

im not arguing I am just saying that it doesnt gets disconnect