[Solved] Getting a lot of false positives on this anti exploit I made

local positions = {}
local workspaceStuff = game.Workspace:GetDescendants()
local hackDetection = game.ReplicatedStorage:WaitForChild("ClientHackDetection")
repeat wait(1) until game:IsLoaded()

wait(20)

for _, part in pairs (workspaceStuff) do
	if part:IsA("BasePart") then
		positions[part] = part.CFrame
	end
end

local skipWait = false

while true do
	wait()
	for part, originPos in pairs (positions) do
		if part == nil then
			-- part has been deleted!
			print("Part has been deleted - set checking frequency to really low")
			hackDetection:FireServer("BTools")
			skipWait = true
		end
		if skipWait == false then		
			wait(0.3)
		end
		local succcess, message = pcall(function()
		if (part.Position - originPos.p).magnitude > 10 then
			skipWait = true
			print("Part is in the wrong place - set checking frequency to really low")
			hackDetection:FireServer("BTools")
			print("Reported to server")
			part.CFrame = originPos
		end
		end)
		if succcess == false then
			print(message)
		end
	end
end

So basically - I know this is client side but its designed to be a barrier to very basic exploits / exploiters who dont really understand how roblox or exploits work and have building tools. Problem is it seems to detect pretty much anyone on a laggy device… seems, obviously the people kicked very rarely admit to me that they were infact using exploits, but it seems to me that the bulk of people it’s kicking for ā€˜btools’ are innocent.

Please try to refrain from copying my code :slight_smile:

I assumed this was to do with loading which is why there is the ā€˜wait(20)’ and repeat wait(1) until game:IsLoaded()

3 Likes

May have found the issue, probably with indexing the dictionary with a part of the same name.

Try renaming all of your parts differently.

As for the code, I think you need to use a recursive function instead of a single if-statement to get a quality name key generator.

Example:

function GetRandomKey(Name)
    local Key = Name..math.random()
    
    if Dictionary[Key] then
        return GetRandomKey(Name)
    else
        return Key
    end
end

Also, if this game is FE, building tools won’t affect anyone but the player.

I’ve managed to rule that out through this addition:

	if positions[valueValue] ~= nil then
			repeat
				wait()
			ranName = math.random(15023)
			valueValue = part:GetFullName()..ranName
			until positions[valueValue] == nil
		end

For the FE thing: I know that but it can effect the play experience for others when players are glitching around and hovering in the air etc.

In this case you can make it a lot easier for everyone if you just look at the player’s character - this will also get rid of basic speed/jump/fly hacks instead of just building tools.

There are tools in my game and therefore I can’t just kick anyone who has tools - especially as they could very easily be named the exact same thing as the tools that I allow

(Also I am confused as to why this is giving false positives)

No, that’s not what I meant. I mean doing what you are now (checking the position of parts) except only in the character.
There’s no need to go through the entire workspace when the only thing that replicates is the player.

Also, I recommend using the part object as the key instead of a randomly generated name. This is because dictionary[object] works, so you don’t need to waste lots of time making a random key generator.
Additionally you could also use (StartPosition-EndPosition).Magnitude, as it gets the distance between the two positions for you.

And it appears, like you said, that the issue was comparing different parts instead of a single one.

3 Likes

Thanks for the help in all of those areas - I think I’ll stick with comparing part positions clientside but will definitely use magnitude, the reason I wasnt is because I was originally comparing if the X axis of both was the same, then it sort of devolved into what you see there

I also set the index as the object which is much better - will update you and mark you as the solution if it works!

3 Likes

Still doing it :frowning:

(It actually kicked ME this time)

This is probably an issue with the exploit detection part. Try doing prints and other debugging techniques to see what’s being compared with what, etc.

Also try changing the threshold for kicking.

Hold on I’ve made a few dumb mistakes here that I’m checking

I’ve marked this as right because this is definitely a suitable fix - it turns out I removed the if statement checking if the parts were anchored or not at some point while scripting it and that’s the reason. Sorry for wasting everyones time!

1 Like
for _, part in pairs (workspaceStuff) do
	if part:IsA("BasePart") then
		positions[part] = part.CFrame
	end
end

Won’t character parts be included in this? Also:

     if part == nil then

This is not the right way to detect if a part is destroyed. Check if its Parent is nil instead. Besides, this is impossible because this would mean that there is something indexed to nil in your positions table.

Lastly:

if (part.Position - originPos.p).magnitude > 10 then

Since character parts are included in a list, this would trigger if a character moves too fast (e.g. because he/she fell or glitched)

2 Likes

The character parts come under this - thanks for pointing it out though :slight_smile: (Sorry again for wasting time)

Just a tip, hackers can read your code and make it so your ā€œhack detectionā€ remote does nothing. while true do end is the de facto client side cheat stopper.

You can have it be both (crashing after a delay and making sure you setup the delay before attempting to fire the remote so you don’t error if they destroy it), just make sure it’s not just ā€œhack detectionā€ remotes.

1 Like

I’m fully aware :slight_smile: This will be used in conjunction with server side exploit prevention too.

2 Likes

What I would do:

  1. Check if any GUI’s are added to PlayerGui that aren’t yours
  2. Set player walk speed and jump power on a bindtorenderstep
  3. Check if players travel massive amounts of distance with little velocity (aka, teleporting). Check with server to see if this teleport was authorized by having the server log all teleports that are SUPPOSED TO HAPPEN so no false positives.
  4. Check if the FPS is > 70. Most exploits have an UnlockFPS option.
  5. Check if any parts are deleted, and just like the teleport, be sure to log all intentional deletes so no false positives.
1 Like

This seems pretty inefficient - why not just check every second or two and then kick them if it’s been changed. Changing it every RenderStep is unnecessary lag.

You can do that, but I prefer to prevent rather than kick.

Even then you should check every second and then if the walkspeed has been changed you then check every renderstepped - otherwise you’re punishing innocent players.