Exploiters and how they spoof stuff in your own game

What script? the metatable script?

Yes, the metatables script

Since the Humanoid.Running gets the client speed its this code:

local mt = getrawmetatable(game)
local oldindex = mt.__index
setreadonly(mt,false)

mt.__index = function(indexed,property)
	if indexed == "Humanoid" and property == "WalkSpeed" then 
		return 16 -- or whatever speed value
	end
	return oldindex(indexed,property)
end

setreadonly(mt,true)
1 Like

oh I’m an idiot, I could’ve just straight copied the sample code from the tutorial.

Lol, true. It’s on the top by the original author.

1 Like

Can Exploiters change attributes?

anything you can do an exploiter can do plus alot more

You need to learn more about how to use module correctly

Wrong:

function self:SafeKickClient(Message)
	local Success, Error = pcall(function() game:GetService("Players").LocalPlayer:Kick(Message) end)
	local StatsService = game:GetService("Stats")
	
	RunService.RenderStepped:Wait()
	
	if not Success or StatsService.DataSendKbps ~= 0 then
		repeat until true ~= true
	end
end

Lead function located named self? Huh.
Also useless using RenderStepped as wait/sleep

Correct & Better:

local Module = {}
Module.__index = Module
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Storage

if RunService:IsServer() then
if not Storage or not script:FindFirstChild("Folder") then
Storage = Instance.new("Folder", script)
else
Storage = script:WaitForChild("Folder", 15)
end
else
Storage = script:WaitForChild("Folder", 15)
end


function Module.init()
return setmetatable({}, Module)
end

function Module:findObject(name: string, withInstance: boolean)
-- prevent error by exploited
assert(typeof(name) == "string", "Invalid type of player name.")

if Storage and Storage:IsA("Folder") and Storage:FindFirstChild(name) then
if withInstance then
return {true, Storage:WaitForChild(name)}
end
return true
end
if withInstance then
return {false, nil}
end
return false
end

-- decated function only for server
If RunService:IsServer() then
function Module:Add(playerName: string)
-- prevent error by exploited
assert(typeof(playerName) == "string", "Invalid type of player name.")
assert(playerName:len() > 0, "Invalid minimum player name length")

if not self:findObject(playerName) then
Instance.new("IntValue", Storage).Name = playerName
return self:findObject(playerName)
end
return false
end)

function Module:Remove(playerName: string)
-- prevent error by exploited
assert(typeof(playerName) == "string", "Invalid type of player name.")
assert(playerName:len() > 0, "Invalid minimum player name length")

local GetObject = self:findObject(playerName, true)
if GetObject and GetObject[1] == true then
GetObject[2]:Destroy()
return true
end
return false
end)

end

function Module:SafeKickClient(playerName: string, Message: string)
-- prevent error by exploited
assert(typeof(playerName) == "string", "Invalid type of player name.")
assert(typeof(Message) == "string", "Invalid type of message or message is required.")
if RunService:IsClient() and Players.LocalPlayer then
assert(Players.LocalPlayer.Name == playerName, "Are you trying to using other person name?.")
return
end

local GetObject = self:findObject(playerName, true)
if GetObject and GetObject[1] == true then
if Players:FindFirstChild(playerName) then
	local Success, Error = pcall(function()
Players:WaitForChild(playerName):Kick(Message) end)

	if not Success then
warn(Error)
	end
GetObject[2]:Destroy()
end
end
end

-- for client only
if RunService:IsClient() then

local _lastchecked = tick()
RunService.Hearbeat:Connect()
if (tick() - _lastchecked) >= 1/60 then
if Players.LocalPlayer and self:findObject(Players.LocalPlayer.Name) and Players.LocalPlayer.Character and Players.LocalPlayer.Character:FindFirstChild("Humanoid") and Players.LocalPlayer.Character:FindFirstChild("Humanoid").WalkSpeed > 16 then
-- Players.LocalPlayer.Character:WaitForChild("Humanoid").WalkSpeed = 16
self:SafeKickClient(Players.LocalPlayer.Name, string.format("Caught change default walksped [%s]", Players.LocalPlayer.Character:WaitForChild("Humanoid").WalkSpeed))
end
_lastchecked = tick()
end
end)

repeat task.wait() until Players.LocalPlayer and Storage and self:findObject(Players.LocalPlayer.Name) == true

local GetObject = self:findObject(Players.LocalPlayer.Name, true)
Storage.ChildRemoved:Connect(function(child)
if child and child:IsA("IntValue") and child.Name == Players.LocalPlayer.Name then
Instance.new("IntValue", Storage).Name = Players.LocalPlayer.Name
end
end)

end

return Module

Sorry if there any wrong or typo and not formated i was coded it on phone

Important Note: this may able to be bypassed, have bug/glitch and need to be improved

:wave: Ah, this might be worth more if it was said two years ago when I made this post.


I’ve both forgotten this resource page and what I have said, so you may be correct or incorrect; However I do want to iterate this :-

Please, don’t waste your time trying to solidify your “Client” AntiCheat it is simply put; A waste of both resource and developer time being invested into solidifying the client.

It’s better if you set your sights on the server and how to combat exploits in your own game! :smile:

Exploiters can manipulate attributes but they’re still constricted to the rules of FilteringEnabled. Attributes changed on the client will not replicate to the server unless you have some sort of vulnerability in your game architecture that allows exploiters to make sever-sided requests to manipulate attributes through an unprotected remote.

Not sure if this was directed towards @AsynchronousMatrix or OP, but regardless there is very little benefits to trying to detect/prevent exploiters from exploiting in your experiences. Server validation is the only reliable way to minimize the effects of exploiting as a whole.

Instead of checking if they’re walking or falling, I like to separate checking the X and Z distance vs the Y distance. This way I can check their walking and their jumping/whatnot separately.

1 Like