Anticheat Help thread

This thread is a WIP

You may have thought to yourself that you needed an anticheat on your server at one point or another - but you might not have known what to do and what to check for… this thread’s goal is to inform you of what to look for in cheats to detect and how to actually right code to detect it.

0 Introduction and outline
1 What to look for in hacks so you can detect them
1.1 Anticheat bypassers
1.11 timer.Destroy(“blah”)
1.12 Detoured functions
1.2 Specific hacks
1.21 Ahack
1.3 Localizing
1.4 Ping pong
2 End

1.0 What to look for in hack so you can detect them

1.1 Anticheat bypassers
People sometimes specifically target specific anticheats and what they do in order to attempt to bypass them. You can attempt to cause a collateral when this is done to set off a detection.

1.11 timer.Destroy(“blah”)



timer.Destroy("hackcheck")


You can use this to your advantage and create a timer named "hackcheck" and send a message to the server whenever it runs; if it stops running, punish them.


--client:
timer.Create("hackcheck", 10, 0, function()
	net.Start("something");
	net.SendToServer();
end);
--server:
util.AddNetworkedString("something");
local tested = {};
local amt = {};
local 2much = 4;
net.Receive("something", function(len, ply)
	tested[ply] = true;
end);
timer.Create("testhacks", 14, 0, function()
	for i, ply in ipairs(player.GetAll()) do
		if(not tested[ply]) then
			amt[ply] = amt[ply] or 0;
			amt[ply] = amt[ply] + 1;
			if(amt[ply] >= 2much) then
				ply:Kick("anticheat bypass");
				continue;
			end
		end
	end
end);


1.12 Detoured functions
Some hacks like to detour GetConVar and GetConVarNumber to prevent sv_allowcslua and sv_cheats detections. This is an example detoured function:



local oldgcvn = GetConVarNumber;
function GetConVarNumber(str)
	if(str == "sv_cheats" or str == "sv_allowcslua") then
		return 0;
	end
	retrn oldgcvn(str);
end


You can detect this by doing a few things... 


--this only works because you can't dump a C function.
local s, r = pcall(function() string.dump(GetConVarNumber) end);
if(s) then
	ReportAndBanMe();
end

-- or

if(debug.getinfo(GetConVarNumber).short_src ~= "[C]") then
	ReportAndBanMe();
end


..and more

1.2 Specific Hacks

1.21 Ahack (http://pastebin.com/Z4Wr2nUk)
First, don’t rage at me because this is so easy to find that anyone that actually wanted to hack could get it without coming here.

Here's line 95:


AHack.Active = CreateClientConVar("AHack_Active", 1, true, false)


Heheheheh…



local func;
function func()
	RunConsoleCommand("AHack_Active", "0");
	timer.Simple(math.random(3, 8), func);
end
func();


Take a look at line 637:


hook.Add("RenderScreenspaceEffects", AHack.RandomName(math.random(10, 15)), function()


You can detect it by doing this:


--client:
for k,v in pairs(hook.GetTable()["RenderScreenspaceEffects"]) do
	net.Start("detected");
	net.WriteString(debug.getinfo(v).short_src);
	net.SendToServer();
end
--server:
util.AddNetworkedString("detected");
net.Receive("detected", function(len, ply)
	local str = net.ReadString();
	if(not file.Exists(str, "GAME")) then
		ply:Kick("HAXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: "..str);
	end
end);


1.3 Localizing
sometimes people override so many functions it is hard to tell something changed. Localizing the _G table is a great way to check for if something changed…
The bypass:



local oldgcvn = GetConVarNumber;
function GetConVarNumber(str)
	if(str == "sv_allowcslua") then
		return 0;
	end
	return oldgcvn(str);
end


You can try this:


local oldgcvn = GetConVarNumber;
local oldgcv = GetConVar;
timer.Create("\x01", 1, 0, function()
	if(oldgcv ~= GetConVar or oldgcvn ~= GetConVarNumber) then
		RunConsoleCommand("banme");
	end
end);


1.4 Ping pong
No, this is not the classic game you used to play in the basement of your friends house. This is when the client sends a packet to the server every few seconds to make sure it is still there and is working. Adding this into a timer is a great way of making sure no one destroyed the timer.
Client:



timer.Create("lol:)", 10, 0, function()
	--do some important checks here so that they can't just leave the timer stay.
	net.Start("ping");
	net.SendToServer();
end);


Server:


util.AddNetworkedString("ping");
local logged = {};
net.Receive("ping", function(len, ply)
	logged[ply] = true;
end);
timer.Create("lol ha ha :)", 15, 0, function()
	for i, ply in ipairs(player.GetAll()) do
		if(not logged[ply]) then
			ply:Kick("noping");
		end
	end
end);


2.0 End
This thread will be updated every now and then with more techniques of detecting people, and please note that these techniques ** will not ** detect every single hack.

If you want something added into here, PMing me usually works best - but you can also post in this thread.

Here is a very simple outline of an anticheat for you to build off of with techniques in this thread…: