High accuracy anti walkspeed (+ noclip)

Hi, I made this amazing anti-walkspeed, noclip. It should be very good at doing what was listed but it isn’t the best. The concept is really interesting though.

There will be no updates, what I want is to show people this interesting concept and how it works. It will be on them to make a better one.

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

Pros against other similar anticheat:

  • High ping? No false positive (Except teleporting).
  • Highly accurate detection. Triggers on ~5% speed increase.

Cons:

  • Takes more performance?
  • False positive from anything that can move you fast.
  • No vertical check. (Except for the magnitude check inside the anti-bypass)

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 a normal magnitude check, this prevents them from doing that. At least doing that to move horizontally.

There are explanations in the script.

Server Script

-- Get things
local remote = Instance.new("RemoteEvent")
local player = game:GetService("Players")
local physicService = game:GetService("PhysicsService")

-- 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
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
	local char = p.Character
	-- Raycasting
	raycastParams.FilterDescendantsInstances = {char, workspace.Camera, ignore}

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

	-- Check result
	if raycastResult then
		local a = raycastResult.Instance
		-- Check collision. long line of code
		if a.CanCollide or physicService:CollisionGroupsAreCollidable(physicService:GetCollisionGroupName(a.CollisionGroupId), physicService:GetCollisionGroupName(char.PrimaryPart.CollisionGroupId)) 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.1 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.1 or distance > speed/4 then
		return true
	else
		return false
	end
end

local function characteradded(v)
	-- For saving initial location
	task.wait()
	_G.Locations[v.Name] = v.PrimaryPart.Position
	print(v.Name.." spawned.")
end

local function playeradded(v)
	print(v.Name.." joined.")
	v.CharacterAdded:Connect(characteradded)
	-- Clone and give the client the remote event (This isn't required. It was a stupid part on my end, just use the same remote for all)
	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 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 exist before doing the calculations.
		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.") -- 
			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.
		-- Also acts as an vertical check so 20 studs allowance might not be high enough. Should be impossible to trigger depending on how you build your game.
		for i,v in pairs(_G.Locations) do
			if (player[i].Character.PrimaryPart.Position - v).Magnitude > 20 then
				player[i].Character.PrimaryPart.Position = v
			end
		end
	end
end)

To make sure it’s running, check the output when a player joins.
image

Local Script

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

local alive = false

Player.CharacterAdded:Connect(function(v)
	alive = true
	v:WaitForChild("Humanoid").Died:Connect(function()
		alive = false		
	end)
end)

local updatecharacter = Player:WaitForChild("RemoteEvent")

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

local deltatime = os.clock()

local pos = Player.Character.PrimaryPart.Position

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

-- Note: you can reduce the wait time.
-- ^  This increases what the server has to handle and causes false positives as the time is more inaccurate. Putting it at 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

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 (on anti walkspeed/tp) even at 1000ms ping.

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

Noclip

There is a false positive on respawn due to ping, won’t be noticeable.

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 somehow bypass it, please record a video and the script you used.

48 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

1 Like

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.

3 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…

4 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.

2 Likes

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

2 Likes

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.

1 Like

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.

3 Likes