newcclosure
Wraps a Luau function inside a native C proxy to evade detection.
function newcclosure(f: function): functionSynopsis
How it works
Creates a new C closureClosureA function value that captures its lexical environment. In Luau, closures come in two types: LClosure (Luau bytecode + Proto + upvalues) and CClosure (native C function pointer + upvalues). (
CClosure) that wraps the provided Luau function. When called, the C closure internally invokes the original Luau function via lua_call, passing through all arguments and return values. The wrapper is indistinguishable from a native C function to introspection.VM internals — closure type system
Luau has two closureClosureA function value that captures its lexical environment. In Luau, closures come in two types: LClosure (Luau bytecode + Proto + upvalues) and CClosure (native C function pointer + upvalues). representations sharing a common
ClosureHeader:
// Common header for both types
struct ClosureHeader {
GCObject header; // GC linked list + type tag
uint8_t isC; // 0 = LClosure, 1 = CClosure
uint8_t nupvalues; // number of upvalues
Table* env; // environment table
};
// Luau closure (isC=0)
typedef struct LClosure {
ClosureHeader;
Proto* p; // bytecode + constants
UpVal* uprefs[]; // captured variables
} LClosure;
// C closure (isC=1)
typedef struct CClosure {
ClosureHeader;
lua_CFunction f; // native function pointer
TValue upvals[]; // embedded upvalue storage
} CClosure;
newcclosure(fn) allocates a CClosure with 1 upvalue (the original LClosure), and sets f to a trampolineTrampolineA wrapper function that bounces (redirects) calls to another function. In executor context, newcclosure creates a C closure trampoline that calls the Luau function stored in its first upvalue. that calls lua_call on the upvalue. Introspection sees isC=1.Why use it
Roblox's anti-cheatAnti-cheatGame-side Luau scripts designed to detect and prevent exploitation. Common checks: verifying closure types (iscclosure), checking metatable integrity, monitoring remote call patterns, and scanning for known executor globals. and hook-detection code checks the
isC byte on closures. Game metamethodsMetamethodA function in a metatable that overrides default behavior for operations like indexing (__index), assignment (__newindex), calling (__call), comparison (__eq), and arithmetic (__add, __mul, etc.). like __namecall and __index are always C closures — replacing them with a Luau closureClosureA function value that captures its lexical environment. In Luau, closures come in two types: LClosure (Luau bytecode + Proto + upvalues) and CClosure (native C function pointer + upvalues). flips isC from 1 to 0, immediately detectable. newcclosure disguises your Luau hook to keep isC=1. Checks like debug.info(f, "s") == "[C]" and iscclosure(f) both pass.Usage
Wrap a hook handler
local original = hookfunction(print, newcclosure(function(...)
"cc">-- Intercept print calls
original("[HOOK]", ...)
end))Parameters
f function The Luau function to wrap.
Returns
function A new C-type wrapper function that delegates calls to the provided Luau function.
Evasion Mechanism
The resulting function will return true for checks like debug.info(f, "s") == "[C]", making it look like a built-in Roblox function.