I’ve recently started noticing that people on the devforum are unaware of the true power exploits have and in this tutorial i wanna educate you on how powerful they really are.
So let’s start from a recent post i saw about walkspeed. People were doing walkspeed checks by just doing like:
if Humanoid.WalkSpeed>16 then
LocalPlayer:Kick("Cheater")
end
Now there are 3 problems with this script. Let’s start with the easiest one:
The exploiter could delete the script - this is true but if you hide this deep in one of your casual scripts, they can’t delete it without breaking anything else.
Now this is where it gets complicated:
The exploiter could spoof the WalkSpeed - Many developers are unaware of spoofing with exploits. So i’m gonna explain it right now.
The exploiter has access to the games metatable. Now with that, you can actually spoof many returns. The exploiter could set the WalkSpeed to 20 but when a script indexes it, it will return 16. Here’s how they do it:
local mt = getrawmetatable(game) -- This gets the game's metatable
local oldindex = mt.__index -- This saves what it does normally when you index a property
setreadonly(mt,false) -- makes it so you can edit the games metatable
mt.__index = function(indexed,property) -- detects if a part is indexed (Referring to Humanoid.WalkSpeed)
if indexed == "Humanoid" and property == "WalkSpeed" then -- checks if the part indexed (Humanoid) is a humanoid and checks if the property is walkspeed
return 16 -- returns a fake value of 16
end
return oldindex(indexed,property) -- if the indexed isnt humanoid and the property isnt walkspeed then do what it does normally
end
setreadonly(mt,true) -- locks the metatable again
Now what the exploiter could do is just set the walkspeed to whatever, and it will always return 16. Now this is always gonna be like this and sadly with the tools roblox gives us you can’t detect this.
Okay fine ill use a velocity check and then do LocalPlayer:Kick() - Now this is another mistake people do, kicking on the client. As i just showed you, you can spoof anything really. That happens to also include calling functions on parts.
Here’s a simple antikick you can make within a minute:
local mt = getrawmetatable(game) -- This gets the game's metatable
local oldnc = mt.__namecall -- This saves what it does normally when you call a part's function
setreadonly(mt,false) -- makes it so you can edit the games metatable
local LocalPlayer = game:GetService("Players").LocalPlayer
mt.__namecall = function(self,...) -- detects if a part's function is called
local method = getnamecallmethod() -- gets the method that's called (Like :Kick or :FindFirstChild)
if method == "Kick" and self == LocalPlayer then -- checks if the function called is :Kick and its called on LocalPlayer (so it detects if its LocalPlayer:Kick())
return -- this will just return and do nothing (making it so the player actually doesn't get kicked)
end
return oldnc(self,...) -- if it isnt kicking the localplayer then it does what it casually does
end
setreadonly(mt,true) -- locks the metatable again
Now do you see how easy it is for a cheater to spoof anything?
There’s also upvalues but that’s a bit more complicated and i’m not gonna talk about it in this thread.
Conclusion:
Client-Sided anticheat is unreliable, i suggest not wasting time on one, a decent cheater can bypass it within minutes.