Nothing on the client is 100% safe. It might be very difficult to identify where the IDs are stored in the stack during runtime, but itâs not impossible. The Roblox client exists in memory on an exploiterâs computer and exploiters have full access to their computerâs memory. Iâm not aware of whether there are existing tools that can find the memory that the Roblox client uses, but itâs theoretically possible (albeit probably not a huge concern if Iâm being honest).
I tried doing that but since I donât know how to get the id myself, cloning the local script or toggling the enable property changes the id so the server would know the id got changed
The client check is like this:
RemoteFunction.OnClientInvoke = function()
return id
end
the client can simply read the value from the first localscript and insert a new script and change the âidâ variable to be a string from the first script
Essentially all you have to do is read the client event and once you can read it you create your own fake client event and from there you can completely bypass this method of anti cheat so yeah Iâve already seen someone bypass the server to client to server model that I made. I wouldnât call it âeasyâ but to an experienced exploiter it definitely falls into the âeasyâ category unless it has lots of solid encryption layers. I was told about 100 layers would be enough to completely stop an exploiter from using a bypass
They can read this and create their own version of it that can entirely bypass anything you are trying to do inside of the client event as well as sending fake information back to the server of their choice
This kind of wonât work.
The exploiter will intercept the remote event arguments and copy the id.
Then they can disable your local script and fire the remote event from their own script.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local AnticheatRemotes = Remotes:WaitForChild("AnticheatRemotes")
local playersData = {}
local function Check(player)
local playerData = playersData[player]
if playerData and playerData.Active then
for i,v in ipairs(AnticheatRemotes:GetChildren()) do
if v:IsA("RemoteFunction") then
if not playerData.Ids[v] then
local success, result = pcall(function()
return v:InvokeClient(player)
end)
if success and result and playerData.Active then
playerData.Ids[v] = result
end
else
local success, result = pcall(function()
return v:InvokeClient(player)
end)
if not success or result ~= playerData.Ids[v] and playerData.Active then
player:Kick()
end
end
end
end
end
end
game.Players.PlayerAdded:Connect(function(player)
playersData[player] = {
["Active"] = false,
["Ids"] = {},
}
local playerData = playersData[player]
player.CharacterAdded:Connect(function(character)
playerData.Active = true
Check(player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Once(function()
playerData.Active = false
playerData.Ids = {}
end)
end)
end)
game.Players.PlayerRemoving:Connect(function(player)
playersData[player] = nil
end)
while task.wait(2) do
for _, player in ipairs(game.Players:GetPlayers()) do
Check(player)
end
end
exploiters can modify the behaviour of scripts on the client and also make changes to variables theres 2 ways how exploiter could bypass this
they could hook GenerateGUID function
they could get generated GUID from the game scripts or game itself and use it
client anticheats are usually waste of time and i would suggest focusing on server checks because all it takes for exploiter to bypass it is just decompiling game and reading scripts
When I used a fast loop like this it was notorious for causing false flagging. Really bad. If you are going to use a method like this donât fire it so often and the kick shouldnât be instant so it confuses the exploiters