Knightmare Server-side Anti-Cheat Service [updated 3/25/2024]

I’ve noticed in my time playing lots of various Roblox games here that hacker cheating is pretty rampant among the top games. I have read about various client based anti-cheat resources here and I’m not going to wade into any political debate about client anti-cheat vs. server anti-cheat detection. What I am offering to the community is a server based anti-cheat system that covers most of the basic types of cheating with lots of tune-able settings and detailed explanations for how to use them. I understand that developers want to devote their time to “developing” and not so much to combating cheaters. With this resource, anyone can get some good, basic, anti-cheat service going for any game to spend more time doing what you love to do. I’ll post up some video examples, but this first post is just getting the code out and how to install it in your game.

This anti-cheat service detects (4) types of client based cheating and performs a “soft punishment” when detected. The first being Speed cheating. If a player is moving faster than they should, it will stop them in place until they stop. The second detection is Flying detection. If the player is up in the air longer than makes sense for your game, it will “ground” them; over and over until they stop. The third detection is Teleport cheating. Teleport through walls, extreme long distances, etc. will be punished by being force-teleport back to where they started; over and over until they stop. The final detection is Jump cheating. Players that are jumping higher than what you set will have their velocity sapped so they fall back down when detected. Check the “KnightmareConfiguration” script to configure for your game before use.
Don’t ask me about github, I’m going the easy route to maintain updates in this topic alone. :sweat_smile:

You can now just download a model on the marketplace that has all the latest code and separated into a section for configuration (so you can save between updates) and the main anti-cheat service code. I’ve also added an easy ability to create your own custom punishments that will also not have to be changed between upgrades. No more copy/paste, you can grab it directly from the marketplace now!

How to install this server based anti-cheat service:

  1. Download Model From Link Above
  2. After you download the model, it will have 3 scripts attached to it. The “KnightmareConfiguration” is where you want to start.
  3. The 4 types of cheat detection are disabled by default so you have to actually take the time to read all the configuration settings at the top before turning it on. :face_with_raised_eyebrow:
  4. If you want to create your own punishments, look for the “KnightmareCustomPunishment” file, it has examples for all of them, so you can be creative with your cheaters when caught. You have to turn off the default “soft” punishments for the custom ones to kick in.
  5. That’s it really. If I make any updates or bug-fixes to this service, you will only need to copy over “KnightmareAntiCheatService” file from the new downloaded model into your in-game object to overwrite and update the engine without having to redo the configuration file or custom punishments you created.
  6. Once everything is complete, just move the model sphere to anywhere in your map, it will self-delete the floating model after it has a chance to get itself up and running when your game starts.
  7. Finally, please give this “Model” anti-cheat service some stars or positive feedback to encourage others to use it or at least try it when combating game cheaters. :+1:

Auto-Updating Version:
If you want to download the model once and have it automatically download the latest version of the Anti-Cheat Service every-time your server starts, it’s possible. It just takes a little manual setup to avoid triggering Roblox hack detection by accident. :wink:

  1. On the Model you just downloaded, find the “KnightmareConfiguration” file set it for “Disabled” in Roblox Studio. It’s ok, you still do your configuration settings there, but it must be turned off so the auto-update can start first to check for code updates.
  2. Find the “StartKnightmareAntiCheatService” and “Enable” it.
  3. Open the file “StartKnightmareAntiCheatService” in Studio and search for this at the top:
local KMModule = require() -- <--Asset ID for Knightmare Anti-Cheat Service Code
  1. Where you see the require() part, change it to require(15738849753)
  2. Save and close the script file, that is all you need to change. :smile:
  3. This will direct your server to the correct AssetID of the Knightmare Anti-Cheat Service Code update model.
  4. Your done! :tada: Now, every-time your server starts, it will attempt to download the latest version of the Anti-Cheat Service and run that. If it is unable to download the latest version, it will fall-back to the local version you already have. Easy peasy. :melting_face:
52 Likes

Example Videos of Anti-Cheat Service vs. Client Exploits:
Running Speed Cheat:

Flying Cheat:

Teleport Cheat:

Jump Cheat: (Default Jump Power 13, then switched to 100, then 1000)

Finally, how much server CPU does this use? This screen-shot below is from a public server running all cheat detections with 10 active players. Basically, it depends on how active the players are, but when watching it myself, it would fluctuate between 0.5% and 0.3% CPU. That’s half a percent or less depending how on much movement the players were doing. So, you can take a linear guess at what load to expect in your game if you want to support 20 players, 50 players, 100 players, etc. I made a simple linear calculation below:
10 players – 0.5% CPU
20 Players – 1% CPU
50 Players – 2.5% CPU
100 Players – 5% CPU
200 Players – 10% CPU
400 Players – 20% CPU
700 Players – 35% CPU

11 Likes

This seems pretty good, gotta say it tho, when the running anti-cheat is running it just seems like the Player has bad Internet :rofl::rofl::rofl:

8 Likes

I have a tip, move all of the configuration to a ModuleScript so the script is cleaner

5 Likes

I was going to have it in parts for each type of detection because I wanted to be able to have people update without having to re-do the configuration every update but decided to put it all in one big script for ease of installing with one copy/paste action. Unless I find a really major bug in the logic or a bug that causes way too many false detection events despite tuning, the configuration for most will probably be one and done. These detection events are based on what I see most in-game when players are cheating. It can’t be the end all to cheating, but it’s a good start for anyone wanting to stop the most blatant cheaters. :grin:

3 Likes

Yes I know, but if you move the Configuration to a ModuleScriot and put it there you will not have to scroll down for 5 minutes to get to the actual code, but if you want to keep it like this then you’re good

4 Likes

If it gets positive attention, I could go that route just for the sake of update ease. I don’t plan on doing lots of changes to it unless Roblox has some features in the future that mimic what this does that is helpful or if I find a better way to detect checking that doesn’t require a very complex system that just eats server CPU. Right now, it’s a big pile of code that someone can look through and decide what they want to use or maybe build off of it as it might need to be tailored more to how their game works, etc.
I just hate to see so many games ruined by blatant client hacking, so I figured I would do my part to at least help. :sweat_smile:

4 Likes

Yeah I agree, hopefully this gets a lot of attention and you will be able to make less Games be cheated

3 Likes

I didn’t seem to see any setting about changing the HumanoidRig, does this mean this anti-cheat only works with R15?

5 Likes

It works with both by checking for R6 parts and R15 parts in case a sever had a mix of players.

7 Likes

Nice rubberbanding, but why not reset their walkspeed by changing it server-side also? Noobie exploiters will be very confused why their walkspeed is not working because the server is replicating the original walkspeed back to the client.

4 Likes

The client exploiter I was testing with doesn’t work that way. It basically locks in the client speed, so setting this on the server had no effect in my testing. I’m not sure why Roblox designed the client/server this way, but it seems to work like this:
Normal Way:
Server → Client “Hey, use walkspeed 16”
Client → Server “Ok”

Client Hack
Server → Client “Hey, use walkspeed 16”
Client → Server "Ok, still using walkspeed 900 :stuck_out_tongue_winking_eye: "

The server has no sanity checks for the client on movement for some reason. :sob:
You don’t even need a client hack to test this, just clicking the title bar on the Roblox program (which freezes the program while you move it around the desktop) will freeze your player in mid-air until you let go of the window. The server is 100% trusting what the client sends it, for a lot of things, not everything. :wink:

5 Likes

Hm, from my testing, resetting WalkSpeed works and replicates, I know more experienced exploiters can ignore RakNet changes; In which you’d use the rubberbanding method.

At least we have FE now :wink: (Because someone thought having the server allow Client to Server replications without any restrictions would be a good idea)

6 Likes

That’s the main reason why I didn’t do any walkspeed changes because the server has no way to tell what kind of exploit the client is using. A normal user should never see the rubber-band effect, even with lag as the walkspeed should have the same drift regardless of lag. If the character is walking at speed 16, even with lag, that will cover the same distance in 0.25 seconds for both the server and client. Of course, no two devices run at exactly the same speed, that’s why I put that fudge factor into it just to balance that part out. That means one could exploit the speed to perhaps 16.5 instead of 16 and maybe still skate by the server detection, but the flat out double, triple, insane speeds that most try to use will be easy to catch. It will never be perfect as one could simply “speed” for a short moment and then wait for the cool-down and then speed again, but the averaging of doing that just makes it harder for the exploiter to play a normal game. :melting_face:

2 Likes

I made some really horrible code to “estimate” the walkspeed based on magnitude and current server-sided walkspeed:

repeat
		local rootcframe = humanoidroot.CFrame
		local resolvedvector = rootcframe.LookVector:Dot(humanoidroot.Velocity) / rootcframe.LookVector.Magnitude
		local result = math.round(math.abs(resolvedvector))
		
		if result > (humanoid.WalkSpeed + 5) and humanoid.Health ~= 0 and ply:IsDescendantOf(game) and humanoid.Sit ~= true then
			warn(ply.Name .." might be changing their WalkSpeed")
			local serverView = humanoid.WalkSpeed
			humanoid.WalkSpeed = 0
			task.wait(0.1)
			print(ply.Name .."'s WalkSpeed was reset to ".. serverView)
			humanoid.WalkSpeed = serverView
		end

		task.wait(3.5)
	until halt == true

It has a few redundant checks, it’s old code, nothing much to write home about but I’d thought I would share :cry:
result > (humanoid.WalkSpeed + 5) is used as a buffer

4 Likes

Why don’ t you just use math.floor and a Part’ s Magnitude, if it’ s normal it should return the actual player’ s WalkSpeed! Also the setting humanoid WalkSpeed to 0… I don’ t know about that since well they can just change their velocity to their MoveDirection * HackyNumber, so why don’ t you neutralize their velocity if that happens?
Edit: The waits are really unnecessary :sob:

4 Likes

In my testing, if you try to extrapolate the speed from the magnitude of the velocity, then you rely on the “client” to be sending truthful information about the velocity which can be hacked to report false numbers. The only “hack-proof” way I’ve discovered to measure the speed is the player position. The player position can also be “hacked” because the client can send any position also (that’s how the teleport hacks work) but doing a rolling position compare is not hack-able because it depends on the logic checking it. The moment the player enters the server, it’s location is recorded and compared to the previous after a short delay. This rolling path of movement can be checked logically by the server for speed cheating (among other things). Anything that depends on the client being “truthful” such as walkspeeds, etc. won’t work when the client has full control over this.
As far as the task.waits, I’m not sure of what other way a server can “track” time? Using server frames isn’t reliable because those go down as the server gets busy, but the way I’m using the task.waits also has a drift calculator that keeps the speed calculations in-line with the actual player speed.

If there is a more efficient way to calculate player speed that doesn’t depend on the client sending “true” information, I’m all for it. :smiley:

2 Likes

Sprint systems are most likely on the client.

It would be smart to treat all exploiters like the smartest exploiters. I wouldn’t rely on hope that the exploiter is dumb!

4 Likes

There is a problem because when falling it triggers speed cheat, not fall cheat

4 Likes

Yeah, that part can be tricky. In the configuration section this part below (in code section). The default freefall time is 2.0 seconds. This has to be tweaked against the “highest” possible fall in your game. An easy way to check what is working, enable the debug output for speed cheating and watch the values as you test jump off your highest possible points in your game. If your game has points to jump off that are so high that the player is spending a long time in freefall (accelerating the entire way) the freefall default might have to be so high that it makes it difficult to detect the difference between falling fast and just moving too fast. If those really high “falling” events are rare, then using a very high freefall time might not be an issue. It will vary from game to game.

--[[
How long to ignore Free Fall in seconds when ignoreFreeFalling is set to false above.
Once the timer expires, the speed will be tracked again to check for speed cheat
detections even when falling.
Default = 2.0 seconds
--]]
local debugSpeedCheatDetection = false

local maxFreeFallTime = 2.0
4 Likes