How to properly create Anti-Exploits.


  • Requirements

    • You should have basic understanding of Filtering Enabled and have worked with it before.
    • You should know that spoon feeding isn't the way to go and you should be able to write the code yourself.
    • You should be able to test the anti-exploiting yourself via using exploits or having someone test it out.
    • You will be provided with test code to serve as a base for your anti-exploits.

    Understanding the concept

    Anti-Exploiting and it's limits:
    You should realize that there's always a workaround between your anti-exploiting regardless of the security.
    In general, the more successful effort you put in, the more you'll get out of the Anti-Exploit, this includes being lazy.

    Exploiting and it's limits:
    Exploiters would often use an 'explorer' to navigate through your game's files and attempt to find any vulnerabilities in it.
    Exploiters cannot access ServerScriptStorage or Scripts.
    Exploiters can access ModuleScripts and LocalScripts.

    Preventing Lag from Anti-Exploits
    Make sure to tick StreamingEnabled (Property of Workspace) to ON, this is a ROBLOX way to prevent lag.

    Beginner Tutorial

    Basic Anti-Exploits
    When making things like Anti-Speedhacks or Anti-Jumphacks, people would mistakenly directly navigate to the Humanoid never realizing that the exploiter is able to change the name of it, hence why it can be simply bypassed.
    You should also note that exploiters can hack their speed not just by changing the WalkSpeed in the Humanoid, but by changing their FPS (frames per second). We should start coding now:

    Script

    --[ Anti-Speedhack ]--
    Humanoid = nil -- Premake 'Humanoid' so that you can use it as a Global Variable.
    Max_Walkspeed = 16 -- This will be the max walk speed your player can walk.
    KickMessage = 'Kicked for SpeedHacking' -- This will be the message when the player is kicked.
    
    game.Players.PlayerAdded:Connect(function(plr) -- When a player joins, the player is saved as 'plr'.
        plr.CharacterAdded:Connect(function(char) -- When the player spawns in-game, the character is saved as 'char'.
            -- First, we're going to set the global variable, Humanoid.
            for _,object in pairs(char:GetDescendants()) do
                if object:IsA("Humanoid") then
                    Humanoid = object
                end
            end
            
            -- Secondly, we're going to do a ':GetPropertyChangedSignal' instead of a loop.
            Humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
                if Humanoid.WalkSpeed >= Max_Walkspeed + 1 then -- Add +1 just to make sure it doesn't bug out.
                    plr:Kick(KickMessage)
                end
            end)
        end)
    end)
    

    LocalScript

    KickMessage = 'Kicked for SpeedHacking' -- This will be the message when the player is kicked.
    
    -- Then, we're going to prevent the exploiter from changing their FPS.
    while wait() do -- This shouldn't affect lag/performance within the game.
        if game.Workspace:GetRealPhysicFPS() >= 65 then
            plr:Kick(KicKMessage)
        end
    end
    

    Summary

    Tips & Tricks
    You should also use my methods of using Local Variables conversion to Global Variables method by premaking a global variable and setting it within a statement in order to be used freely.

    Example:

    Variable = nil -- Premake the variable
    if Humanoid then
        Variable = true
    else
        Variable = false
    end
    print(Variable)
    

    If you're developing an Anti-Exploit that requires the Humanoid then feel free to use my method of getting the humanoid whilst preventing a name change from the client.

    Example:

    char = thePlayerCharacter -- Make sure 'char' is a variable set to the player's character.
    Humanoid = nil -- Premake the variable
    
    for _,object in pairs(char:GetDescendants()) do
       if object:IsA("Humanoid") then
           Humanoid = object
       end
    end
    

    Whilst developing an Anti-Fly, or an advanced Anti-Speedhack mechanism, you should definitely go for the player's position. Mess around and study the difference between the studs between a measured last position and current position and kick the player if they walked too fast (position-wise) or their Position.Y is too high (flying)

    Example:

    char = thePlayerCharacter -- Make sure 'char' is a variable set to the player's character.
    HumanoidRootPart = nil -- Premake the variable
    KickMessage = 'Flying' -- This is the message the player will get when they recieve it.
    
    for _,object in pairs(char:GetDescendants()) do
       if object:IsA("BasePart") and object.Name == "HumanoidRootPart" then
           HumanoidRootPart = object
       end
    end
    
    while wait() do -- Shouldn't affect performance/lag
       local LastPosition = HumanoidRootPart.Position.Y
       wait(1) -- Time measured before the next position
       local CurrentPosition = HumanoidRootPart.Position.Y
       ----
       if LastPosition-CurrentPosition >= 25 then
          plr:Kick(KickMessage)
       end
    end
    

    When you're developing an advanced Anti-Noclip (huge issue for a lot of games), you should safely do a raycast through the last position and the next position, and if there's a part in between, they're noclipping. Make sure to set it to a good time or else it'll be detected when you go around corners.


  • @HaloUlti It is named ServerScriptService, not ServerScriptStorage. You also should NOT be using wait() as your condition in while loops. And the fact that you check if their Y axis is too high...

    people can have tall buildings you know


  • @incapaz is right. There are a few other things I would like to make note of. ModuleScripts are not able to be accessed by a player if they are located somewhere secure. I have also been kicked from a game just because I was lagging really bad. In your example you say to use global variables. That is not what you are doing. Setting the initial variable with local is also encouraged. Here is an example

    local variable -- if you don't set it to something it is by default nil
    if Humanoid then
         variable = true
    else
         variable = false
    end
    

    Global variables are not encouraged nor is what you are using a global variable anyway. Global variables are set using _G. Also hackers can modify their local scripts. You should not be checking and kicking them in a module script. I think that you should think things through more thoroughly before posting them in the forum.

  • Global Moderator

    Ew, global variables. Don't do that. Don't use them. You should always use local variables, even in the top-level scope of the script. Usage of global variables is bad practice, it makes your code messy.

    @HaloUlti said in How to properly create Anti-Exploits.:

    Preventing Lag from Anti-Exploits
    Make sure to tick StreamingEnabled (Property of Workspace) to ON, this is a ROBLOX way to prevent lag.

    This is definitely not true. StreamingEnabled is not just some magical switch you can turn on to make lag go away. It completely changes the way Roblox works, similarly to FilteringEnabled. It can --- and will! -- break your whole game if it wasn't designed from the ground up to work with StreamingEnabled.

    Finally, as stated by @incapaz and @Phlegethon5778, your heuristics are not very good.

    Heuristics are "guessing" techniques or "hints" that are used to solve for something when there is no known algorithm or method. Another reason to use heuristics is if existing algorithms are too time consuming for one's needs. By following a good guess instead of performing the actual computations required to get an exact answer to a problem, one can save processing time, assuming you don't mind occasional false positives or lack of precision. Being just guess methods, heuristics are not very precise, but they are accurate ; they can give a good guess of the actual answer to a problem but can be a little bit off. An example of a heuristic is the FABRIK algorithm.

    Finding good heuristics to detect hackers is really the challenge in coming up with an anti-cheat. I suspect a lot of intermediate developers understand how an anti-cheat would work, and would totally write one, but are struggling with exactly this.

    Furthermore, to detect hackers you wouldn't base yourself on a single heuristic; you would get input from several different heuristics before determining if a player should be kicked or banned. The more heuristics that react positively, the more chances you have found a real hacker as opposed to a false positive.


  • @Link150 I agree. If this were some magical switch to prevent lag, it would be on by default for every Roblox game. In fact, there wouldn't even be an option to turn it off.

Log in to reply
 

Looks like your connection to Scripting Helpers was lost, please wait while we try to reconnect.