Detect every function hooked by exploiters (metamethod hooks included) with this one simple trick!

Ahoj všichni!

Today we will be releasing a very powerful lua hook detection for anti cheats. This detection can be used to detect any sort of lua function hooks, including instance metamethods.
Exploits can be detected on inject from this if they have a lua init script that hooks the game metamethods on inject. Many competent exploits may be safe from the on-inject detection, but this can still
prevent people from creating their own lua hooks for __index. Now you can have a good client anti cheat that checks humanoid walkspeed.

The method itself has to do with how the Lua stack works. We’ve all heard or had to deal with so-called “stack overflow” errors; they usually happen when we try to run an unconditional recursive function - simply put, Luau cannot handle more things onto the stack, and therefore it errors to prevent further issues. Exploits have historically been susceptible to metamethod hook detection vectors that involve checking the call stack for irregularities in one way or another. This approach is no different - it abuses a very niche aspect of the Luau engine in order to detect __index hooking. All lua hooks are detected by this.

If you are planning on using this, make sure you paste it in the top function scope of your script and don’t modify anything but the punishment behavior in the placeholder as the technique is very sensitive to even the slightest of change!
We wish you an exploit-free New Year!

BTW, This method has existed since exploits introduced hookfunction and game metatable hooking. No idea why some other developer did not discover this first.

-- Made by Fate

local AntiHook = function(Func)
  if (Func) then
      local Check;
      Check = function(int)
          if int < 16379 then
              Check(int + 1);
          else
              Func(workspace,"Name");
          end
      end
      local a, b = pcall(Check, 1);
      return not a and b:find('stack overflow')
  else
      return true
  end
end

local LocalPlayer = game.Players.LocalPlayer

local Index;
while wait(.1) do
  xpcall(function()
      return game["AAAAAAA"]
  end, function()
      Index = debug.info(2, "f");
  end)
  if (AntiHook(Index)) then
      LocalPlayer:Kick("Exploit");
      break;        
  end
end
78 Likes

WAOW! This thread almost made me CRASH THE BRAND NEW WHIP I WAS DRIVING!!
Thanks for this insane release, all exploit metamethod lua hooks are BTFO’d. I will definitely be adding this to my up-and-coming anime game.

6 Likes

Wow, crazy release, right around the corner of my up-and-coming horror shooter FPS game, which imo is a pretty orginal concept.
EDIT: Original* A sunray reflected off my Rolex and hit my eye, so I mistyped.

7 Likes

I wouldn’t use this for any serious projects. Ignoring the fact that it’s a client side check that can just be disabled, it’s also very unreliable because it depends on specific and undocumented client behaviour. This is behaviour that can change at any moment (and has likely before), and you could kill your game overnight when it does and no players are able to join or are otherwise punished.

Absolutely never rely on undocumented observations. At least when something is in writing somewhere you can expect it to reasonably stay the same, but if it’s not, there’s no such guarantee.

22 Likes

this behavior relies on a constant lua limit, so unless that changes this detection i don’t see why it would false flag. but yes, it does exploit an undocumented client behavior.

1 Like

Interesting on how this works, maybe I should really learn lua deeper to the point of the virtual machines and stacks

However has this been tested?

1 Like

it has, it detects krnl on inject flawlessly as of the time i’m posting this.

2 Likes

That UI doesn’t look like krnl, but okay

1 Like

it’s the beta ui, that’s why it looks different

3 Likes

WOW that looks really complex I havent even seen this type of scripting before! Great Job. I will surely use it for my games.

Works on synapse x with a script I made in 10 seconds. Pretty nice. Not adding this to my games since it will be patched in less than a week

3 Likes

While this is neat as a concept, no one should use this in practice- you’re relying on C closures to retain properties that aren’t explicitly defined anywhere and are subject to change with every new update. Developers who do use this might find their entire playerbase being kicked for exploiting because Roblox so much as re-organized some engine code.

1 Like

I’d like to mention the maximum stack depth has never been changed since the introduction of scripting. It’s almost like you’re only worried about people using this because it detects your popular remote spy exploit!

8 Likes

I’m sure a professional Game Security Expert like yourself will have no trouble finding another detection like this one. Right?

3 Likes

I mean this method worked before newcclosure got created which just removes the exploiters custom functions from the call stack.

unfortunately, while it did hide the custom functions from callinfo, it did not account for the stack size change

Thank you soo much! This is one of the best releases of the game

3 Likes

This seems like a good script, however, someone could just:

game.Players.LocalPlayer.PlayerScripts['AntiHook']:Destroy()
-- or with any other root. 

Unfortunetly DEX programmes cannot be fully stopped, and if a DEX programme gets in, it’s easy mode for the exploiter.

You can put LocalScripts in nil and if you set its name too just “LocalScript” and not “AntiHook” exploiters won’t think much of it. While still possible to disable it they wouldn’t know it was there until they tried to hook something.

Edit: One of my friends dmed on Discord about this reply saying “legit the first thing I think is there scripts in the nil.” So I just wanted to say you could also hide it in the default Animate script inside the character.

1 Like

Exploiters are likely to scan local scripts anyways.