This thread is outdated and promotes bad practices, use informationally only.
Introduction
I feel like Roblox Developers’ biggest problem is when someone discovers a way to trick the system into doing an unwanted action. This is mostly done by logging remote event calls, which is possible with exploits.
This thread will in no way secure your Remote calls, and following it blindly will still leave opening spots for exploiters in your game. To ensure your game is safe, you shouldn’t ever trust the client, and should always make sure to do everything that matters on the server.
1. How do Remote Event loggers work?
Remote Event Loggers (or Remote Spies) work by setting the game’s metatable.
The game usually has locked metatable, but exploits can bypass it.
Remote Spies take advantage of __index
and __namecall
metamethod. Whenever object function is called, it gets indexed and executes whatever __index
function returns.
Exploiters change __index
function to display the Remote Event arguments and then call the original function to get the return values which are passed back to the client.
2. How to prevent?
There are a few ways that I know of:
1. Indexing the function
One way would be to index the function at the start.
The only down-side is only the fact you can’t call the remotes using :
, but you have to pass the remote as the 1st argument (self
). This method works for most exploits, but sadly not all of them, as new exploits have new ways of logging like binding functions to it without using metatables. As far as I know, some games use this method already.
Example :
local RemoteEvent = game:GetService('ReplicatedStorage'):WaitForChild('RemoteEvent')
local FireServer = RemoteEvent.FireServer
FireServer(RemoteEvent, Arguments) --> Won't trigger most loggers
RemoteEvent:FireServer(Arguments) --> Will trigger most loggers
2. Checking whether the function has changed
Another way would be to check whether the function has changed since the start of the game.
The downside to this method is the fact that the client can remove the script and therefore pass the security.
The workaround would be to have two scripts which check when another one gets removed.
Example :
local RemoteEvent = Instance.new('RemoteEvent')
local FireServer = RemoteEvent.FireServer
while wait(1) do
if FireServer ~= RemoteEvent.FireServer then
-- The function has changed, the player is logging remote events.
end
end
If you have any questions or suggestions, feel free to comment and I’ll try to answer.