High accuracy unbypassable anti walkspeed (+ noclip)

Hi, I made this amazing anti walkspeed, teleport, noclip. It should be very good at doing the 3 things listed but it isn’t the best (yet). The concept might be the best though.

I’m always open to take feedback and will update if there are any improvements to it. A new topic will be made when the update is major such as adding a verticality check, changing this into a module (though unlikely), etc.

Thanks @Hexcede for this post. os.clock() usage has greatly increased the accuracy allowing the anticheat to detect even a speed increase of 1.

It uses remote event but exploiters can’t do anything useful with it as there are many checks on the server to prevent them, don’t comment about it. Unless you can point out exactly what you can do to bypass with video evidence.

Pros against other similar anticheat:

  • High ping? No false positive. (tested with 1000 ping anyways even though I know it wouldn’t have false positive due to high ping)
  • Highly accurate detection. With some server side anticheat you can set your speed to 30 and it won’t trigger. This? Increasing from 16 to 17 makes it impossible to move.

Cons:

  • Takes more performance?
  • Doesn’t take account in physics, meaning a push from a part can trigger it

This script is useful to block auto farming. Exploiter tends to use tween to get from one place to another faster than a normal player would while not triggering the standard magnitude check, this prevents them from doing that. At least doing that to move horizontally.

There are explanations in the script.

Server Script

-- Create a new RemoteEvent
local remote = Instance.new("RemoteEvent")
local player = game:GetService("Players")

-- Location table
-- Used to get real, actual character position/teleporting the player
_G.Locations = {}

-- Time table, used for anti bypass
local timeTable = {}

-- Anti Noclip function
-- Not ideal as you can skip corners + the raycast can go into a 0.001 stud hole (that's on you to prevent)
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist

local function noclip(p, old, pos, ignore)
	-- Get direction with the correct length
	local a = pos - old
	local direction = a.Unit*a.Magnitude
	-- Raycasting
	raycastParams.FilterDescendantsInstances = {p.Character, workspace.Camera, ignore}

	local raycastResult = workspace:Raycast(old, direction, raycastParams)

	-- Check result, if nothing exist then it hit air we should just continue
	if raycastResult then
		-- Check collision, if false then continue raycasting while ignoring that part it hit.
		if raycastResult.Instance.CanCollide then
			return true
		else
			return noclip(p, raycastResult.Position, pos, raycastResult.Instance)
		end
	else
		return false
	end
end

-- Horizontal check
local function horizontal(distance, dt, p)
	-- *1.07 because the time is still inaccurate (even with os.clock). Increase it if you have false positive
	local speed = p.Character.Humanoid.WalkSpeed
	if distance > dt*speed*1.07 or distance > speed/4 then
		return true
	else
		return false
	end
end

local function playeradded(v)
	print(v.Name.." joined.")
	local function characteradded(v1)
		--Saves initial location
		task.wait()
		_G.Locations[v.Name] = v1.PrimaryPart.Position
		print(v1.Name.." spawned.")
	end
	v.CharacterAdded:Connect(characteradded)
	-- Clone and give the client the remote event so each player gets handled by a different thread (performance)
	local newre = remote:Clone()
	newre.Parent = v
	-- The function used to do horizontal magnitude check + anti noclip function
	local function check(p,dt, pos)
		-- Check if time is a negative/NaN value
		if dt <= 0 or not dt == dt then
			p:Kick("very smart") -- This should be a ban
		end
		-- Add the time
		timeTable[p.Name] = timeTable[p.Name]+dt
		-- Check if character/pos exist
		if p.Character then
			-- Check if pos exist and is it a Vector3 and does it have a NaN value
			if pos and typeof(pos) == "Vector3" and pos == pos then 
				-- Get old location
				local old = _G.Locations[p.Name]
				-- The checks
				if horizontal(((old-pos)*Vector3.new(1,0,1)).Magnitude,dt,p) or noclip(p, old, pos) then
					-- They moved too far/They clipped through wall, reset their location
					warn("Detected")
					p.Character.PrimaryPart.Position = old
				else
					-- They passed the checks and successfully updated their location
					_G.Locations[p.Name] = pos
				end
			else
				p:Kick("Position is nil/not a Vector3 or is a NaN value.") -- Another ban
			end
		end
	end
	newre.OnServerEvent:Connect(check)
	-- This is to get the initial time only when the remote first fire. Prevent some bugs.
	-- If they don't fire, their location can not update. They wouldn't be able to move.
	local onetime
	onetime = newre.OnServerEvent:Connect(function(p)
		if p == v then
			timeTable[p.Name] = os.clock() - 1
			print(p.Name.."'s initial time taken.")
			onetime:Disconnect()
		else
			p:Kick("Firing another's remote.") -- Ban
		end
	end)
end

player.PlayerAdded:Connect(playeradded)

local function playerremoving(v)
	timeTable[v.Name] = nil
	_G.Locations[v.Name] = nil
end

player.PlayerRemoving:Connect(playerremoving)

-- The anti bypass
task.spawn(function()
	while task.wait(1) do
		local a = os.clock()
		-- Get all players time
		for i,v in pairs(timeTable) do
			-- If somehow their time passed the server time by 1 seconds or slower than 30 seconds
			-- We ban/kick them
			if v > a + 1 then
				player[i]:Kick("HAS TOO MUCH TIME HOW") -- Ban
			elseif a - v > 30 then
				player[i]:Kick("Ran out of time") -- Normal kick as it is possible to trigger without exploits
			end
		end
		-- Magnitude check to prevent not firing the correct location/not firing at all for the server to get time
		for i,v in pairs(_G.Locations) do
			if (player[i].Character.PrimaryPart.Position - v).Magnitude > 20 then -- Change 20 to your allowed distance
				player[i].Character.PrimaryPart.Position = v -- This (should be) impossible to trigger depending on how you build your game. Note that the script doesn't have a vertical check and this acts as a vertical check.
			end
		end
	end
end)

To make sure it’s running, see does it output this when a player joins.
image

Local Script

--This script is pretty self explanatory
local Player = game:GetService("Players").LocalPlayer

local updatecharacter = Player:WaitForChild("RemoteEvent")

repeat wait() until Player.Character and Player.Character.PrimaryPart

local deltatime = os.clock()

while task.wait(0.1) do
	if Player.Character then
		local a = os.clock()
		updatecharacter:FireServer(a - deltatime, Player.Character.PrimaryPart.Position)
		deltatime = a
	else
		local a = os.clock()
		updatecharacter:FireServer(a - deltatime)
		deltatime = a
	end
end


-- Note: you can reduce the wait time
-- ^  This increases what the server has to handle, 0.1 is good enough?
-- Increasing the wait time will cause false positive as you're giving people more time to move behind a wall, triggering anti noclip. Also allowed distance is capped at walkspeed/4.

There are no vertical checks as jumping, ladder, and many things that can increase your verticality extremely fast exist. This will be on the game developer to deal with as making an out of bounds check doesn’t seem hard.

Here are an example of anti walkspeed and an example of anti noclip, look at the logs.
Tested at 60ms ping but will not have false positives even at 1000ms ping.

Server character walkspeed: 16
Client character walkspeed: 16,17

Noclip

Sometimes you get false positives on anti walkspeed. (definitely Roblox engine pulling tricks on you. Not ping)

To make it actually works please use _G.Locations to get character position (and use it to teleport people as teleporting the normal way will not work).

That’s all.
If you have any improvements, optimization, bypass, please tell me about it in the comments. I will reply if the comment was correct about their opinion.

29 Likes

what if the exploiter change walkspeed while mid-air, this will make him stuck in the air?

If he keeps moving, yes
If not, he will just fall normally

depending on the game, it should kick the player after some time because if in a fps shooter game, he will be in mid-air killing others “for example”
( 10 seconds detecting that the player has the status : “SusWalkspeed” for example a boolvalue)

2 Likes

Feels like a good idea so I’ll put it on the to-do list for tomorrow, thanks

2 Likes

what if the exploiter destroy the remote event?
(the cloned one)

If you read the server script, there is a time check at the end. If the remote is not fired for 30 seconds, the game will kick you.

2 Likes

Yeah didn’t saw the timer and the kick.
Thanks for sharing this usefull script!

I just bypassed this.

An exploiter just has to save their spawn position and send that in the remote.

1 Like

Their initial location is taken whenever their character loads on the server side.
Doing that is pointless.

It works, I can show you my methodology:

1 Like

Oh now I understood what you’re talking about.
Well, yes you can do that but what if the games are using the location in _G.Locations to do things instead? It will be pointless
Adding on, developer can use it with a standard magnitude check on the server side with _G.Locations to prevent you from going further/ban you instantly

1 Like

Just edited, now you shouldn’t be able to move more than 20 studs away without being teleported back

Any anti walkspeed, teleport, or noclip, etc that relies on a remote event is bypassable… Remote events, by nature, are insecure, you can’t rely on them, they can send fake data through it, block all the other requests going through it, turn off the local script, etc…

3 Likes

They can’t fake data here.

The time determine how far they could move, if it’s too high, they get kicked (actually a ban as it is impossible to trigger the detection without cheats)

If they don’t send the normal time, they will slowly get kicked.

Faking character doesn’t do much here aswell, the time determine how far could that move.

1 Like

Sorry to burst your bubble, but exploiters could disable the remote firing, as well as disable the LocalScript firing it entirely, bypassing it in literally 1 line.

tl;dr - bypass = exploiter disables local script

EDIT: oh, and from the looks of it, this doesn’t take in account the ping of players so there’s likely to be false positives

I guess that one line script will also make them unable to get out of their last saved location and also get kicked after 30 seconds…

Did you read the last part of the server script?

Also player ping doesn’t matter here, as long as their connection doesn’t stop the data from reaching the server for 30 seconds they are fine with whatever ping they have

Making an anticheat like this is very easy, the issue why games don’t have this sort of anticheat, is because it’s extremely inefficient. This sort of constant serverside checking will cause server lag and make the game unplayable for any average player.

I don’t think so though, it’s a check every 0.1 second. Not to mention it’s on different threads.

But I guess we will never know.

1 Like

Checking stuff server side that the server already can see such as Position, CFrame etc will not cause
“server lag”. Maybe if you need to check 100 players every 1/30th of a second yeah, but in most cases you are perfectly fine doing server side sanity checks.

2 Likes