This post will have some of the detection methods I’ve found that I’ve decided to post publicly, if detection isn’t mine, the author will be credited. I will be updating this post whenever I add a new detection.
Extra
Define AntiCheat functions properly
If your anticheat has any functions, make sure you define them using local func = function() instead of function func(). Defining a function the first way will not reveal the function name to the exploiter, keep in mind they can still decompile and detect functions by checking constants and arguments.
How to combat hooked RemoteEvent/RemoteFunction
Method 1: Teleport Cheaters to certain coordinates incase your remote that handles bans is hooked. Make sure you use different threads for that.
Examples:
Client Code
local player = game:GetService('Players').LocalPlayer or game:GetService('Players').PlayerAdded:Wait() -- Incase you use ReplicatedFirst
local Detected = function()
if player and player.Character and player.Character:FindFirstChild('HumanoidRootPart') then
-- Fire the ban remote in a different thread
local hrp = player.Character.HumanoidRootPart
local clock = 0
while clock < 5 do
hrp.CFrame = CFrame.new(101337, 1337, 1337)
hrp.Anchored = false
clock += task.wait()
end
hrp.Ancohred = true
print('Crash the client')
-- Crash the client
else
print('No character, crash the client')
-- Crash
end
end
-- Test
task.wait(10)
Detected()
Server Code
local Players = game:GetService('Players')
local BanPos = Vector3.new(101337, 1337, 1337)
while task.wait(.5) do
for _, player in Players:GetPlayers() do
if player.Character and player.Character:FindFirstChild('HumanoidRootPart') then
if (BanPos - player.Character.HumanoidRootPart.CFrame.Position).Magnitude < 25 then
print('Ban', player.Name)
end
end
end
end
The following code can be used to protect any kind of signals, for example OnClientEvent. Be careful if you disconnect any of your signals though.
AntiCheat Code:
local player = game:GetService('Players').LocalPlayer or game:GetService('Players').PlayerAdded:Wait()
local Connection = player.Idled:Connect(function(idleTime)
local randomVariable = idleTime
end)
while task.wait(.5) do
if not Connection.Connected then
print('AntiAFK script detected, ban')
end
end
Script Example:
-- Ultra simple anti afk kick script
for _, connection in getconnections(game.Players.LocalPlayer.Idled) do
connection:Disconnect()
end
Video Example:
__tostring trap
If you store some kind of data in ModuleScripts, you can modify __tostring method in order to detect exploiter printing out the table, keep in mind that it’s still possible to loop through it or index it without any problems. This detection is pretty rare, however it won’t have any false positives unless you print out your tables.
Module Code:
return setmetatable({
Damage = 25,
Cooldown = 0.15,
ReloadTime = 2,
OtherStat = true
}, {
__tostring = function()
print('Table was printed, ban')
local val1 = 'table'
local val2 = ': '
local val3 = '0x'
local val4 = '82fcfd59c8a044d1'
return val1 .. val2 .. val3 .. val4
end,
})
Script Example:
local AkStats = require(game.ReplicatedStorage['AntiCheat Scratches'].Ak47)
print(AkStats)
They probably figured out how to do it them selfs. Also just because the names are the same etc I recommend linking each executors docs due to them potentially being a bit different.
Its also poor practice to link old documentation for something that’s not been operational for the last ~2 years.
that is a good resource to detect exploiters without false positives
while it can still be bypassed, exploiters may mess up when trying to cheat and then get banned and if they tried to cheat on another account, they would have to read all the scripts in case of another trap and they can still mess up and get banned
Fun fact: Nihon developers got lazy originally, and their documentation was written by AI, it has changed some since then; however, I’d not particularly rely on their docs or Wave’s, since things like getactors were documented to return string instead of { Actor }, which says a lot of the quality of documentation.
The Synapse X, UNC and RbxStu V3 documentation (as you used the RbxStu V3) are probably your best choice for the documentation; although the latter are still being written and probably have one or two mistakes, the first two are safest bets as they have stood for years now.
All positive words but RBXStu doesn’t make sure the .Connected is set to true when it disconnects, wave, synapsez, and awp all do this so you could do this
local Connection
local player = game:GetService('Players').LocalPlayer or game:GetService('Players').PlayerAdded:Wait()
local ConnectionFunction = function(idleTime)
local randomVariable = idleTime
end)
while task.wait(.5) do
if not Connection then
Connection = player.Idled:Connect(ConnectionFunction)
return
end
if not Connection.Connected then
print('hooked')
end
Connection:Disconnect()
end
It shouldn’t be set to true, that is the whole reasoning for the Disable function to exist. The disconnect function is intended to entirely kill off the connection.
I think your misunderstanding. The disconnect function does terminate the connection, but an executor would hook the metamethod of the .Connected to always return true.
I know this, but dottik believes that the behaviour he implemented is correct ( I agree ). If disconnect kept .Connected as true then there would be no need for Disable to exist realistically.
Exploits usually use connection:Disable(), which is different from connection:Disconnect(). It leaves the connection “connected” but prevents it from firing.