Securing local anti-cheat

Hi,
I have an local anti-cheat which will fire a remote every 10s to verify that it hasn’t been disabled. That works fine. But on the actual server I don’t know how to verify that it has been sent once in 10 (15 for the lag?) seconds.

Yes I know this is a bad practice, but you could call the anti-cheat a honeyspot

1 Like

Hello, could you use a RemoteEvent.

Umm I use remote events but I say remote for quicker communications

On the server, store the tick() at the time the last remote was fired and compare it to the tick() of the next one.

--pseudo
if tick() > ( lastTick + interval) then --late remote, possible lag

(i wouldnt recommend this)

1 Like

This idea won’t work. When you send a message to the client and checking if the script is still there, people can easily counter this by changing the script to make it so the client always tells the server that the script is there, when in reality it isn’t. You must rely on server side detection for this to work.

He isn’t checking on the server side if the script is disabled. He’s firing a RemoteEvent in a LocalScript which the server checks the time since the last fire.

Yes but you do not understand. Anything on the client can be changed. People can easily delete the script and just fire the remote event every x seconds anyways. Client sided anti cheat just doesn’t work.

I think he’s aware that this isn’t perfect, but he’s using it as a method to get rid of inexperienced exploiters

Yeah that would be a good solution, but how would I go about actually storing the ticks

I suppose that this would trouble inexperienced exploiters, but he should know this won’t work for people who know what they are doing.

You could give the player a table perhaps which stores them

I’ll try doing that. Thanks for the help.

You could create a table and iterate through the players every second

local lastChecks = {}
local plrs = game:GetService("Players")

while true do
     wait(10)
     for _, plr in pairs (plrs:GetPlayers()) do
          couroutine.wrap(function()
               -- check if last time is over 10 else
               local lastTime =  lastChecks[plr.UserId] or tick()
               local result = remoteFunction:InvokeClient(plr)
               lastChecks[plr.UserId] = tick() - startTime
          end)()
     end
end

plrs.PlayerAdded:Connect(function(plr)
     lastChecks[plr.UserId] = tick()
end)

1 Like

You are going to get a lot of false positives imo, you should avoid that. If you insist have an unusued event that if fired is bannable? If you want to objectify time against latency check out Quenty’s time service.

I know. When the honeyspot is triggered. I would mark them as “sus” which would give the server more confidence to take action.

I’d also recommend storing a “strikes” value in the player table, one gets added every time it fails to validate

This is not very reliable. In addition, exploiters can use metables and fire that remote event and prevent it from being fired with certain arguments, or even disable/spoof checks as a whole… or maybe an inexperienced exploiter could delete the script, and just continue firing the event via exploit… I would suggest just making a basic local anti cheat instead as it is basically a lot for nothing.