Remote Security [Other than Checks]

Hey all!

So recently I’ve made a new game and it works great and all, but the issue is exploit security, as is with most games. The reason this is so crucial in the scenario of my game is that a lot of the gameplay is based on sending data over events. I’ve got checks on all sides and what not, but I can’t prevent an exploiter from destroying my game in seconds through making an automatic playing script. My game is that of a clicker in which you buy items to get more money per click (sort of like Cookie Clicker), thus meaning that a lot of cross-communication is needed. I already have checks in place, I just need to be able to physically stop them from firing my events / invoking my functions.

Does anyone have any suggestions for security? If so, please leave them here.

Many thanks,
Empulsion.

2 Likes

Solution: improve your checks / add more checks.

For example, keep track of the last time someone fired a remote, and if it is fired again for that player within X time then reject the request. Another example is if they need to click on a physical object, but their character is miles away from it, you could also ignore the click.

Not possible. They are in full control of their client and can invoke whatever remote they want with whatever parameters at any time.

5 Likes

You could check the intervals between each remote that’ll tell if they have something auto going on so if it doesnt look like a human could make those intervals kick them or kill them, whatever floats your boat.

I like the idea of logging; however, I was reading some other posts and was sure I saw something about preventing it (not necessarily permanently stopping them, but rather delaying them and preventing the less-experienced exploiters). I’ll hold off on the solution for now, I’ll mark it later if noone comes up with anything.

1 Like

What you can also do is check for a remote spy by using the LogService and string.find

Do you have any examples of how I could go about doing this? Exploit protection is where I’m most inexperienced, I only run checks at the moment.

Every exploit prevention requires a different solution. In your case your best protection would probably be making a cap of the maximum registered click rate. Go for like 10 - 15 clicks per second - anyone clicking faster than that wouldn’t even notice this cap much.

local click_budget = 15

local function CanClick()
  if click_budget > 0 then
    click_budget = click_budget - 1
    spawn(function()
      wait(1)
      click_budget = click_budget + 1
    end)
    return true
  else
    return false
  end
end

This kind of code should be run server-side, individual budget values for each player.

Yeah I considered doing this but I feel like there’d be issues with the client and server boundaries being slightly delayed. I’ll probably go ahead and implement it anyway as there’s no such thing as too much security.

local LogService = game:GetService("LogService")
LogService.MessageOut:connect(function(String,Type)
    if Type == Enum.MessageType.MessageOutput and string.find(string.lower(String),"remotespy") ~= nil then
	    --kick crash or whatever floats your boat when remote spy is found
    end
end)

This would be a local script it’d be best to hide it in nil

1 Like

Does that really work? Would some exploiters really have the audacity to include “remotespy” in any of their scripts? Sorry if I’m wrong here I have no clue when it comes to this, a lot of this is new to me and I plan on using it to better myself.

Well the most common remote spy script prints “remotespy” when it finds a remote being called you can always change the check to find like remote names being printed like if BuyItem is printed out in the dev console you can kick them or whatever

Wouldn’t hiding a script in nil still be visible for exploiters?
I personally prefer the method of checking if the script still exists with the use of remote functions, pcalls, and delays to keep things running smoothly.

1 Like

I’ll try it - thanks for the help!

Depends on the exploit some exploits have their own functions like FindInstancesInNil

Do you have an example structure of the best way to do this? I’d love to learn how to.

I knew as much already as exploiters could access nil, hence why I’m interested in your proposal here.

Don’t waste time on hacky solutions to detect exploits. An exploiter can just change the output not to include whatever keyword you’re looking for, and they can go about as they please.

These are wastes of your time:

  • Scanning output for keywords related to exploits
  • Scanning for certain objects to be present in certain locations to detect exploits
  • Encrypting remote traffic
  • Using random numbers as keys for remotes
  • Hiding your scripts/remotes in weird locations at run-time
  • Renaming remotes/objects to random strings

All of the above are security through obscurity and can be easily overturned because the exploiter has full control of their own client.

Server-sided checks stop all kinds of exploiters and are the only thing that give you real security, because these checks run on the server which the exploiter cannot touch.

There’s no free lunch. Implement proper server-sided checks, it’s the only way to truly prevent exploiting.

15 Likes

Sure thing, lemme grab an example from one of the games I’m working on…

Local script named “Player Set Up”:
image
Naming things as plainly as possible to confuse any snoopers

Code
--scripted by GreekForge
local access = game.ReplicatedStorage.Remotes.ClientAccess --most important this is a RemoteFunction
local coms = game.ReplicatedStorage.Remotes.ClientEvent
local plr = game.Players.LocalPlayer
local char = workspace:WaitForChild(plr.Name)
local hum = char:WaitForChild("Humanoid")
local noUse = { --for the rest of my script
	Enum.HumanoidStateType.Flying,
	Enum.HumanoidStateType.None,
	Enum.HumanoidStateType.PlatformStanding,
	Enum.HumanoidStateType.Swimming,
	}


local function oof()
	return true --this can be anything, just return something
end

access.OnClientInvoke = oof
--insert the rest of what you need

Server Script (Can be named anything):
image
The exploiter cannot do anything to change the server, it only has full access to client

Code
local function playerClientScan(v)--v is player
	--check if the client script still exist
	wait(0.1) --dunno why
	local succ, x;
	spawn(function()--make sure the thread doesn't stop
		succ, x = pcall(function() return access:InvokeClient(v) end)
	end)
	delay(9, function() --once again, no stopping the thread
		if not succ or x == nil then
			spawn(function() succ, x = pcall(function() return access:InvokeClient(v) end) end) --yeah...
			delay(3, function()
				if not succ or x == nil then --just in case of slow loading
					succ, x = pcall(function() return access:InvokeClient(v) end)
				end
			end)
		end
	end)
end

spawn(function() --main scan
	wait(scanDelay)
	while wait(scanDelay) do --added a wait at beginning because this runs once before actually waiting
		for _, v in ipairs(game.Players:GetChildren()) do
			local char = workspace:WaitForChild(v.Name, 5)
			if v then
				playerClientScan(v)
				slowPositionCheck(v)
			end
		end
	end
end)

Whenever creating an anti-exploit with multiple checks, always make sure that the player hasn’t been kicked or removed before doing the check.
Of course, if you really want to obfuscation on client scripts can severely impair any exploiter.

3 Likes

I see how it works, good to know.

Thanks for the example!

Why do you invoke the client 3 times? I could just destroy the script and overwrite the callback of the RemoteFunction from an exploit.

1 Like

Well that would work but if the script doesnt have “RemoteSpy” but “RemoteLogger”, that check wouldn’t work.

I have a method of crashing most RemoteSpy scripts the moment you run them. However it is a very easy fix for them, soo yeah.

1 Like