ffi.vtable
Functions for reading, writing, and searching C++ virtual method tables (vtables). All addresses are plain Lua numbers (doubles). Memory-access failures from bad pointers are caught silently and return nil or false rather than raising an error.
Functions
ffi.vtable.base(obj)
Reads the vtable pointer from an object — that is, the value of the first pointer-sized word at obj. This is the standard layout for any C++ class with virtual methods.
Parameters
| Name | Type | Description |
|---|---|---|
obj | number | Address of the C++ object whose vtable pointer should be read. |
Returns
| Type | Description |
|---|---|
number? | The vtable pointer, or |
ffi.vtable.get(obj, index)
Reads the function pointer at slot index of the vtable belonging to obj. Internally dereferences the vtable pointer first, then indexes into it.
Parameters
| Name | Type | Description |
|---|---|---|
obj | number | Address of the C++ object. |
index | number | Zero-based slot index into the vtable. |
Returns
| Type | Description |
|---|---|
number? | The function pointer at that slot, or |
ffi.vtable.get_from(vtbl, index)
Reads the function pointer at slot index directly from a vtable pointer. Unlike get, this takes the vtable address itself rather than an object address — useful when the vtable pointer is already known.
Parameters
| Name | Type | Description |
|---|---|---|
vtbl | number | Address of the vtable (not the object). |
index | number | Zero-based slot index into the vtable. |
Returns
| Type | Description |
|---|---|
number? | The function pointer at that slot, or |
ffi.vtable.set(obj, index, func)
Overwrites the function pointer at slot index of the vtable belonging to obj. The vtable must be writable; if the memory is read-only the write will fault and false is returned.
Warning: Patching a vtable in place affects every object that shares that vtable. Use with care, or copy the vtable first.
Parameters
| Name | Type | Description |
|---|---|---|
obj | number | Address of the C++ object. |
index | number | Zero-based slot index into the vtable. |
func | number | New function pointer to write into the slot. |
Returns
| Type | Description |
|---|---|
boolean |
|
ffi.vtable.set_from(vtbl, index, func)
Overwrites the function pointer at slot index directly in the vtable at address vtbl. Unlike set, this takes the vtable address itself rather than an object address.
Warning: Patching a vtable in place affects every object that shares that vtable. Use with care, or copy the vtable first.
Parameters
| Name | Type | Description |
|---|---|---|
vtbl | number | Address of the vtable (not the object). |
index | number | Zero-based slot index into the vtable. |
func | number | New function pointer to write into the slot. |
Returns
| Type | Description |
|---|---|
boolean |
|
ffi.vtable.size(vtbl)
Estimates the number of slots in a vtable by walking entries until one fails a validity check. An entry is considered valid when it is non-null, in the range 0x10000–0x7FFFFFFFFFFF, and points to executable memory. The walk stops at the first invalid or inaccessible entry.
Parameters
| Name | Type | Description |
|---|---|---|
vtbl | number | Address of the vtable (not the object). |
Returns
| Type | Description |
|---|---|
number | Estimated number of slots. |
ffi.vtable.find(handle, name)
Locates the vtable for a named C++ class inside a loaded module using RTTI metadata. The search follows the standard MSVC RTTI chain:
- Scans
.datafor theTypeDescriptormatching.?AV<name>@@. - Scans
.rdatafor theCompleteObjectLocatorthat references it. - Scans
.rdatafor the vftable meta-pointer that references the locator. - Returns the address of the slot immediately after the meta-pointer, which is the first virtual method slot.
Note: Using this function on abstract classes like IClientMode will return a stub vtable of pure-virtual methods. You likely never want to find any class starting with I.
Returns nil if any step fails (class not found, stripped RTTI, or the module lacks .data/.rdata sections).
Parameters
| Name | Type | Description |
|---|---|---|
handle | lightuserdata | Module handle (e.g. from |
name | string | Undecorated class name as it appears in the RTTI type descriptor, e.g. |
Returns
| Type | Description |
|---|---|
number? | Address of the vtable's first slot, or |
ffi.vtable.find_instances(handle, name, multiple?, min_size?)
Finds live instances of a class by scanning memory for the vtable pointer. The vtable address is resolved first via RTTI (same as find). The scan proceeds in two phases:
- Module
.datasection — fast, covers most static/global instances. - Process-wide memory scan — falls back to this only when no results are found in phase 1. Scans all read-write, non-image memory regions that are at least
min_sizebytes large.
Each result is the address where the vtable pointer was found — i.e. the likely start of an object of that class.
Returns an empty table (never nil) when the vtable cannot be found or no matches exist.
Parameters
| Name | Type | Description |
|---|---|---|
handle | lightuserdata | Module handle (e.g. from |
name | string | Undecorated class name, e.g. |
multiple? | boolean | If |
min_size? | number | Minimum region size (bytes) for the process-wide phase-2 scan. Defaults to |
Returns
| Type | Description |
|---|---|
table | Array of addresses (numbers) where the vtable pointer was found, ordered by discovery. May be empty. |