How can I stop exploiters from disabling connections?

  1. What do you want to achieve? Keep it simple and clear!
    I would like to improve my script so the exploiters can’t disable connections.
    If you want some infos about how they do that, they use getconnections(signal: RBXScriptSignal): {Connection} from the UNC library (exploit library).
    More informations here: NamingStandard/instances.md at main · unified-naming-convention/NamingStandard · GitHub

  2. What is the issue? Include screenshots / videos if possible!
    The issue is that, I made a script which kicks/crashes the players if it gets deleted, but it can be bypassed by disabling the script.Destroying connection.
    here’s an example of what my script looks like

local function kick()
	game:GetService("Players").LocalPlayer:Kick(kickmessages[math.random(1,#kickmessages)])
	while true do end
end
script.Destroying:Connect(function()
	kick()
end)

And here’s how it can be bypassed:

local connections = getconnections(game.Players.LocalPlayer.PlayerScripts._youtried.Destroying)
for _, connection in ipairs(connections) do
	connection:Disable()
end
wait()
game.Players.LocalPlayer.PlayerScripts._youtried:Destroy()
  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    Well, I’ve tried making a script which can detect a connection deactivation but I think it’s impossible.

Note: Please stop saying this post is against the ToS because it’s not. Thanks
Note~2: Don’t respond to this message if you just want to tell me exploiters can simply disable the anticheat. I know what I’m doing.
Note~3: Sorry for the bad grammar. It may hurt your eyes

1 Like

Hey there!

OP has a great question with exceptional results. I’ve decided to replicate the functionality, and this is what I’ve came up with.

The most secure it’ll get, is obfuscating the script (making it hard to read), and/or check at intervals + recreate the script if disabled.

My Approach

-- Define your function that performs the action you want to protect (in this case, kicking the player)
local function kick()
	game:GetService("Players").LocalPlayer:Kick(kickmessages[math.random(1,#kickmessages)])
	while true do end
end

-- Define a random, hard-to-guess name for your connection
local connectionName = "abc" .. tostring(math.random(100000, 999999))

-- Create the connection and store it in a table so we can reference it later
local connections = {}
connections[connectionName] = script.Destroying:Connect(kick)

-- Define a function that we'll use to disable the connection if necessary
local function disableConnection()
	if connections[connectionName] then
		connections[connectionName]:Disconnect()
		connections[connectionName] = nil
	end
end

-- Hide the connection in a table with a random, hard-to-guess name
local hiddenTable = {}
local hiddenTableName = "def" .. tostring(math.random(100000, 999999))
hiddenTable[hiddenTableName] = {["Disable"] = disableConnection}

-- Define a function that we'll use to disable the hidden table if necessary
local function disableHiddenTable()
	if hiddenTable[hiddenTableName] then
		hiddenTable[hiddenTableName] = nil
	end
end

-- Wait a few seconds, then disable the connection and hidden table to make it harder for exploiters to find them
wait(5)
disableConnection()
disableHiddenTable()

But, if the connections are disabled/disconnected, the original “script.Destroying:Connect(kick)” becomes useless, right ?

Yes, if the script.Destroying:Connect(kick) connection is disabled, then the kick function will not be called when the script is destroyed. This is why we need to protect the connection from being disabled in the first place.

By storing the connection in a table and giving it a random, hard-to-guess name, it becomes more difficult for exploiters to find and disable it. Additionally, by hiding the connection in a separate table with another random name and defining a function to disable it, you add an extra layer of protection.

Finally, by waiting a few seconds before disabling both the connection and the hidden table, you make it even harder for exploiters to locate and disable them before the desired action (in this case, kicking the player) is taken.

Also, naming connections with a random name is completely useless since they just use

local connections = getconnections(game.DescendantAdded)

for _, connection in ipairs(connections) do
	connection:Disable()
end

Here, they literally don’t care about the connection name

Edit: they can also get all the stored tables in the game

You’re correct that a random connection name doesn’t provide much protection against exploiters who can easily disable all connections using the getconnections function. However, naming your connections with a random, hard-to-guess name can still make it more difficult for exploiters to find and disable your connections manually, which may deter some less skilled exploiters.

Not a way to “stop”, however can be prevented minimally.

Stop focusing on the client anti-cheat so much. Add the basics if you must, but anything beyond that is going to break your brain because any exploiter capable of disabling connections by themselves will always win against whatever implementation of a client anti-cheat you have. You’re wasting your time trying to fight people who have a higher level of access to the Lua internals than you do on ROBLOX.

It seems like we have client anti-cheat related posts on this forum all the time…

1 Like

You’re wrong. Some games detect exploits injection, saveinstance, decompile, darkdex, IY, etc WITHOUT checking the memory. BTW, their anticheat CAN NOT be deleted or disabled.