Preventing/Detecting Metatable Hooking?

There are plenty of checks you can do to verify information coming from the client can be considered “valid”, plenty of games have taken to this approach (ex Phantom Forces).

I actually would not like to have a delay. It is a rather fast paced game and it would not benefit the game overall. So, I am trying to find solutions that don’t hinder gameplay.

Then you’re going have to compromise by checking the melee’s handle size locally and by adding server-sided distance checks just to make sure someone isn’t stabbing someone else 10 miles away.

I am doing that already. However, exploiters are tricking the server into thinking the value is the normal value.

That is the solution I’ve seen most games use when using Touched events on melee weapons. You can simply check if the distance is no more then the length of the part on the server plus some for latency reasons. This would require cheaters to teleport in order to make the hit valid, of which you can also detect.

Okay, so a lot of dumb exploits like “ProtoSmasher” and “SynapseX” cannot “Disable()” GetPropertyChangedSignal events. So you can simply do this (just make sure you’re not changing the handle’s size with your LocalScripts):

local Handle = ToolHandleHere

Handle:GetPropertyChangedSignal"Size":Connect(function()

while wait() do

    for i = 1,100 do

        while true do end

    end

end

end)

Handle.Changed:Connect(function(Change)
if Change == “Size” then
while wait() do

for i = 1,100 do

    while true do end

end

end
end
end)

Actually, they can hook that function, making it useless. Edit: Using metatables.

Most typical exploiters lack intellectual prowess. So they probably wouldn’t figure it out so easily. Also, this is where the server-sided distance checks come into play.

The thing is I already have GetPropertyChanged signal and the server sided distance check. Many of the exploiters still manage to exploit the sword hitbox and be able to hit everyone in their radius without moving.

Also, on top of that, you can use deprecated properties like lowercase “size” to check things because most fail to check for those. I also recommend you obfuscate LocalScripts.

Oh, I did not know about that! Should I use lowercase “size” in GetPropertyChangedSignal or part.size? Also, I do not have any obfuscators, know any?

Obfuscators like “IronBrew” work quite well and actually mess with decompilers in decompiling code. I also recommend you hide these LocalScripts in nil, as typical exploiters don’t even bother checking nil.

Also, you could probably check for both just because a lot of these “metatable hooks” fail to account for deprecated variants.

All they do is wait for a new script release on their favorite website / server and take.

Nice! So… where would one find this “IronBrew” and how would you hide scripts in nil?
Edit: .Changed doesn’t work with “size”?

I don’t know what you did with the .Changed thing, so I can’t help. Also, I found IronBrew just by looking it up https://github.com/DefCon42/ironbrew-2

And there’s probably some tutorial to hide scripts in nil. I forgot how to do it.

All I did was part.size.Changed:Connect(NameOfFunction)

Oh no, for Changed you gotta do it like this

Part.Changed:Connect(function(ChangedProp)
if ChangedProp == “size” then
while true do end
end
end)

@Math_Solvers The answer to your question in your original post, which is to prevent or detect metatable hooking, is that you can’t and shouldn’t. Client-side anti-exploit can be bypassed, so do your security from the server. To flag exploiters changing their walkspeed, there are various solutions offered around the forums, such as checking character velocity.

@nulllifeleft, please do research before posting. You’ve provided a large amount of misinformation, bad practices and generally should-not-do information which can easily confuse new developers. I’d like to also address these responses and some of the falsities they have in them.


  • DO NOT USE DEPRECATED ITEMS. You should be using Touched if you need any physical interaction with the world. Just because deprecated items work, doesn’t mean you should use them. Deprecated means that it can be removed at any time, with or without warning, and can cause gamebreaking issues if your code relies on it. Deprecated warnings are NOT nonsense and should NOT be ignored, be it Roblox or another platform/language.

  • Exploiters are capable of firing any signals exposed to them. If Touched can be fired, so can LocalSimulationTouched. Do you have a citation that exploiters can’t? And even if you do, it wouldn’t really matter: there are other ways to perform security checks on melee/speed systems.

  • The assumption that exploiters can’t disable events is incorrect. Your functions can be redirected, disconnected and tampered with, as well as called with falsified arguments. The same goes with remotes and sending tampered data. The concept of “exploiters can’t”, if it’s not related to the server, is a DANGEROUS mindset to hold. Always assume they can do whatever they want on their machine (and they can in the first place).

  • Do not use while wait loops.

  • Don’t use while to combat exploiters at all. ScriptContext.SetTimeout exists and they can just time out any attempts to crash with that. A simple call to this function renders this solution useless. The proper way to get rid of an exploiter is through Player.Kick from the server with server-side security checks.

  • I don’t have any comment regarding commenting on the state of an exploiter’s “intellectual prowess”, other than that it’s ad hominem and inappropriate to be saying.

  • Obfuscation is security through obscurity which is not real security. Obfuscation just makes debugging and maintenance of your code an absolute pain, plus you lose out on even performance in some cases. Never suggest obfuscation as a legitimate security option against an exploiter especially if it’s just your own game’s code. Collaborators, likewise, will also have trouble. And lastly, deobfuscators exist.

  • Client-side code can still be decompiled and seen. Obscuring what you write doesn’t stop an exploiter from seeing what you’re doing on the client and developing a countermeasure against it. A la, see above, SetTimeout.

  • Round two: do not use deprecated items.

  • Again, you CANNOT assume that an exploiter won’t do something and should be assuming that they WILL. It is almost standard for exploiters to check nil and there is even a function in some exploit programs dedicated to retrieving nil instances. It’s a gross assumption to say “exploiters don’t bother checking nil”. And while I can’t confirm this, I don’t even think LocalScripts run in nil to begin with.

  • Don’t use Changed if you’re checking for a single property, use GetPropertyChangedSignal. It will only fire a signal when the specific property you’re checking for changes. This is more performance-friendly than checking for all changes and then only doing something if it’s the specific property you want. You should have virtually no reason anymore to be using Changed unless in some off chance you need to check when anything changes or if you’re working with a ValueObject, as it uses a specialised version of Changed.

12 Likes

The thing about ScriptContext.SetTimeout is that it doesn’t work on trash exploits like Synapse X, so you can crash exploiters using Synapse X just fine. It does work for other exploits, however. So you gotta watch out for that. Also, the thing about the deprecated functions is that those literally never get removed unless it’s something really stone-age old (LoadLibrary). Example: camel-case functions are still alive, even though they clog up the API.

What exploit someone is using doesn’t matter. So long as they are capable of bypassing the security context level and are able to call it successfully, SetTimeout is enough to prevent a loop from crashing the client. This is an in-engine way to prevent crashing, though other methods exist as well. Completely preventing it from running is another option over allowing it to run until its timeout.

Deprecated items don’t get removed for backwards compatibility reasons or for whatever reason Roblox still has for keeping them around. Despite that, it’s no excuse to ever touch them if a modern or alternate way to exists something[1]. Deprecated means that they can be removed or cease functioning with or without notice. Telling others to rely on things like that is just bad advice, period.

Regarding camelCase properties and methods: those too are the same way. They can be removed at any time and have their functionality changed to an alias. Safe to say that they themselves are now aliases and the actual functionality belongs to the modern method. Example:

local MyInstance = {}

function MyInstance:FooBar()
    print("frobnicate")
end
MyInstance.fooBar = MyInstance.FooBar

[1]: I concede, despite what I say, there are rare exceptions where I (and other developers) don’t care for deprecations. For example, I will still use CFrame.new’s lookAt parameter despite its deprecation and PromptProductPurchaseFinished because it’s not actually deprecated.

1 Like

Thanks for clearing things up. Your reply has been incredibly informative. I, too, use Players.NumPlayers since it’s deprecated but also incredibly convenient. But I guess they’re deprecated for a reason. But, sometimes, they’re convenient to use and/or help out with some niche use.