ffi.hook
Installs inline x86-64 detours via MinHook and libffi closures. Each created hook intercepts calls to a target address and routes them through a Lua callback. The callback can inspect or modify arguments and optionally call the original function. Hook objects returned by create and create_bind are garbage-collected userdata: when the last Lua reference is dropped the hook is automatically disabled and all resources are freed.
Functions
ffi.hook.create(target, signature, callback)
Creates an inline detour on target using the given type signature and installs it immediately. The hooked function is intercepted at the machine-code level; every call to target will invoke callback instead.
Signature format: a string whose first character encodes the return type and whose remaining characters encode each argument type in left-to-right order. Type codes:
| Code | C type |
|---|---|
v | void (return only) |
i | int32_t |
u | uint32_t |
l | int64_t |
f | float |
d | double |
b | bool / uint8_t |
p | pointer (passed as number) |
s | const char* (passed as string, or 0 if null) |
Callback signature: function(original: number, arg1, arg2, ...) -> return_value?
The first argument passed to the callback is the trampoline address as a raw number. You can call the original function by passing it to ffi.call (or an equivalent bound call). The remaining arguments are the intercepted function's arguments, marshalled to Lua according to the signature. The callback's return value is marshalled back to C; if the callback raises an error, the original function is called via the trampoline automatically.
Returns nil (no values) on any failure (bad signature, MinHook error, duplicate hook on the same target address).
Parameters
| Name | Type | Description |
|---|---|---|
target | number | Address of the function to hook. |
signature | string | Type signature string. First character is the return type; remaining characters are argument types. See the type-code table above. |
callback | function | Lua function called in place of the hooked function. Receives |
Returns
| Type | Description |
|---|---|
userdata? | A hook handle. The hook is active immediately. Holds a strong reference to |
ffi.hook.create_bind(bound_fn, callback)
Creates an inline detour using a bound closure produced by ffi.call.bind. The target address and type signature are extracted automatically from the closure's upvalues, so you do not need to supply them separately.
Unlike create, the original function is passed to the callback as a callable bound closure (identical in shape to what ffi.call.bind returns) rather than as a raw trampoline address. This makes it convenient to call the original without a separate ffi.call invocation.
Callback signature: function(original: function, arg1, arg2, ...) -> return_value?
Returns two values on success, or nothing on failure.
Parameters
| Name | Type | Description |
|---|---|---|
bound_fn | function | A bound closure previously created with |
callback | function | Lua function called in place of the hooked function. Receives |
Returns
| Type | Description |
|---|---|
userdata? | A hook handle (same semantics as |
function? | A bound closure wrapping the trampoline (original function). Has the same calling convention as a |
ffi.hook.remove(hook)
Disables and permanently destroys the hook, freeing the libffi closure and releasing the Lua callback reference. After removal the hook handle is inert; calling any function on it will return false. Equivalent to dropping all Lua references to the handle and forcing GC, but immediate.
Parameters
| Name | Type | Description |
|---|---|---|
hook | userdata | The hook handle returned by |
Returns
| Type | Description |
|---|---|
boolean |
|
ffi.hook.enable(hook)
Re-enables a hook that was previously disabled with disable. Has no effect (returns false) if the hook is already enabled or has been removed.
Parameters
| Name | Type | Description |
|---|---|---|
hook | userdata | The hook handle returned by |
Returns
| Type | Description |
|---|---|
boolean |
|
ffi.hook.disable(hook)
Temporarily disables the hook so that calls to the target address pass through to the original function. The hook object and its callback reference are kept alive; call enable to reinstate interception. Has no effect (returns false) if the hook is already disabled or has been removed.
Parameters
| Name | Type | Description |
|---|---|---|
hook | userdata | The hook handle returned by |
Returns
| Type | Description |
|---|---|
boolean |
|