Preventing/Detecting Metatable Hooking?

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.