That’s cool! I think the direction this is going is good; but you should also consider adding something on the server that is checking if stuff is reasonable like @Ax3nx mentioned.
And yes, I’ve seen your reply. Adding something on the server is still good though.
The issue with this is that its all local and exploiters have pretty much full control
I noticed that you only get detected when the scripts are deleted from StarterCharacterScripts, parenting the anti cheat scripts to the character is a terrible way to make an anti cheat just because with a little bit of searching any skilled exploiter can find it within minutes.
I recommend hiding the main “anti” and “detected” scripts, potentially even make more copies and checks
I unfortunately cannot give any more tips on how to improve it because I’ve never made an anti-cheat so I wish you best of luck with your project!
The Remote tampering protection seems weak. The kick is performed on the client and could be bypassed.
if not remoteEvent then
localPlayer:Kick("[Flair AE] Tampering detected.")
break
end
A better solution would be for the server to expect a signal from the client every ~5 seconds. If the server doesn’t receive the signal, it suspects tampering and kicks the player.
Honestly, it’s best to do this on the server, anti-tampers aren’t likely to work most of the time.
On top of that this anti-cheat can be thwarted with a simple
local old; old = hookmetamethod(game, "__index", function(self, key)
if key:lower() == "Kick" then
return task.wait(math.huge)
end
return old(self, key)
end)
local function disconnect(signal)
for _, connection in ipairs(getconnections(signal)) do
connection:Disable()
end
end
disconnect(humanoid.RootPart.ChildAdded)
disconnect(humanoid:GetPropertyChangedSignal("WalkSpeed"))
disconnect(humanoid:GetPropertyChangedSignal("JumpHeight"))
disconnect(humanoid:GetPropertyChangedSignal("JumpPower"))
disconnect(humanoid:GetPropertyChangedSignal("Health"))
disconnect(humanoid:GetPropertyChangedSignal("MaxHealth"))
all client acts to those things(base character) are replicated to the server anyways (its the only way they can notice a change) so idk why theyre doing it on the client but thats a really bad idea
I fully support using the client, but please have some protection against simple hooks and also use the server for checks that the client doesn’t have to do for-example everything in this anti-exploit can be done fully on the server using magnitude and ray cast checks.
Also, I still don’t know why people use two scripts to check if they’re both alive; you can disable both at the same time. This is one of the worst methods that exist; try using a handshake.
A handshake is basically when the client sends a remote event to the server with an encrypted key, and the server resets a time variable for the user. If the key is incorrect or the server doesn’t receive a remote event in a valid amount of time, the script is disabled or destroyed, or the remote event was blocked/destroyed.
Flair Bypasses
local Old
Old = hookmetamethod(game, "__namecall", newcclosure(function(self, ...)
if getnamecallmethod() == "FireServer" and type(self) == "Instance" and self.Name == "PropertyChangedEvent" then
return
end
return Old(self, ...)
end))
local function DisconnectSignal(Signal) --> Lazy Function
for Index, Connection in next, getconnections(Signal) do
Connection:Disable()
end
end
DisconnectSignal(HumanoidRootPart.ChildAdded)
DisconnectSignal(Humanoid:GetPropertyChangedSignal("Health"))
DisconnectSignal(Humanoid:GetPropertyChangedSignal("MaxHealth"))
DisconnectSignal(Humanoid:GetPropertyChangedSignal("WalkSpeed"))
DisconnectSignal(Humanoid:GetPropertyChangedSignal("JumpPower"))
Give these a read:
PS: Also, if a user joins after the game has already loaded, the blacklisted words check will not work for him.
It isn’t done on the server, it’s just listening for property changes on that client, in fact this can even harm innocent players or cause a hassle to the customer who used this asset (because this hinders the server from freely changing the walkspeed, jump power and such or client-sided actions like sprinting, highjumps, etc)
local isAllowed = remoteFunction:InvokeServer("JumpPower")
and alike can easily be hooked to always return true
local old; old = hookmetamethod(game, "__namecall", function(self, ...)
if getnamecallmethod() == "InvokeServer" and self.Name == "CheckAntiCheat" then
return false -- because the code expects isAllowed to be true to fire the kicking part
-- return false instead
end
return old(self, ...)
end)
And then just doing
workspace["Flair AE"]:Destroy()
is enough to break your anti-tampers; and again, this code is enough to thwart 90% of your anti-cheat
local function disconnect(signal)
for _, connection in ipairs(getconnections(signal)) do
connection:Disable()
end
end
disconnect(humanoid.RootPart.ChildAdded)
disconnect(humanoid:GetPropertyChangedSignal("WalkSpeed"))
disconnect(humanoid:GetPropertyChangedSignal("JumpHeight"))
disconnect(humanoid:GetPropertyChangedSignal("JumpPower"))
disconnect(humanoid:GetPropertyChangedSignal("Health"))
disconnect(humanoid:GetPropertyChangedSignal("MaxHealth"))
well you dont need specific property changes for the client because since the entire character is replicated using network service, the humanoid is included… right?