Fivem Lua Executor | Source

Fivem Lua Executor | Source

Inside the DLL, we set up hooks for luaL_loadstring or lua_pcall to intercept script execution.

// dllmain.cpp
#include <windows.h>
#include "minhook.h" // MinHook library
#include <lua.hpp>

typedef int(luaL_loadstring_t)(lua_State L, const char* s); luaL_loadstring_t original_luaL_loadstring = nullptr;

int hooked_luaL_loadstring(lua_State* L, const char* s) // Log or modify script before execution OutputDebugStringA(s); return original_luaL_loadstring(L, s);

DWORD WINAPI MainThread(LPVOID lpReserved) // Wait for FiveM to load Lua engine while (!GetModuleHandleA("lua53.dll")) Sleep(100);

MH_Initialize();
// Hook luaL_loadstring inside FiveM's Lua module
void* target = GetProcAddress(GetModuleHandleA("lua53.dll"), "luaL_loadstring");
MH_CreateHook(target, &hooked_luaL_loadstring, (void**)&original_luaL_loadstring);
MH_EnableHook(target);
return 0;

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) if (reason == DLL_PROCESS_ATTACH) CreateThread(NULL, 0, MainThread, NULL, 0, NULL); return TRUE; fivem lua executor source


| Category | Details | |----------|---------| | Ban risk | FiveM uses automatic detection for external injection – bans are common and can be hardware ID based. | | Malware | Many “free executor sources” include hidden RATs, keyloggers, or miners. | | Instability | Hooking into FiveM incorrectly causes crashes, save corruption, or OS instability. | | Legal | Reverse engineering game clients violates ToS and, in some regions, computer misuse laws. | | Outdated | FiveM updates break executor hooks quickly; sources are often abandoned. |


To execute custom scripts, we need our own Lua state or reuse FiveM's existing one. Here we create a console that accepts user input and runs it.

// lua_engine.cpp
#include <lua.hpp>
#include <iostream>
#include <string>

lua_State* g_LuaState = nullptr;

// Custom print for our executor int executor_print(lua_State* L) int n = lua_gettop(L); for (int i = 1; i <= n; i++) std::cout << lua_tostring(L, i); if (i < n) std::cout << "\t"; std::cout << std::endl; return 0; Inside the DLL, we set up hooks for

// Example: trigger game native (simplified) int trigger_native(lua_State* L) const char* native = lua_tostring(L, 1); // Call native via pattern scanning (omitted for brevity) lua_pushboolean(L, true); return 1;

void InitializeLua() g_LuaState = luaL_newstate(); luaL_openlibs(g_LuaState);

// Register custom functions
lua_register(g_LuaState, "print", executor_print);
lua_register(g_LuaState, "TriggerNative", trigger_native);
// Run a test script
const char* testScript = R"(
    print("Executor loaded!")
    local result = TriggerNative("PLAYER_PED_ID")
    print("Player ped handle:", result)
)";
if (luaL_dostring(g_LuaState, testScript) != LUA_OK) 
    std::cout << "Lua error: " << lua_tostring(g_LuaState, -1) << std::endl;

void ExecuteString(const char* code) if (luaL_dostring(g_LuaState, code) != LUA_OK) std::cout << "Error: " << lua_tostring(g_LuaState, -1) << std::endl; lua_pop(g_LuaState, 1);


The injector finds the FiveM process and loads our DLL.

// injector.cpp
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>

DWORD GetProcessIdByName(const char* procName) HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32);

if (Process32First(snapshot, &entry)) 
    do 
        if (!strcmp(entry.szExeFile, procName)) 
            CloseHandle(snapshot);
            return entry.th32ProcessID;
while (Process32Next(snapshot, &entry));
CloseHandle(snapshot);
return 0;

int main() DWORD pid = GetProcessIdByName("FiveM_GTAProcess.exe"); if (!pid) std::cout << "FiveM not found.\n"; return 1;

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
void* alloc = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT, PAGE_READWRITE);
char dllPath[MAX_PATH];
GetFullPathNameA("executor.dll", MAX_PATH, dllPath, NULL);
WriteProcessMemory(hProcess, alloc, dllPath, strlen(dllPath) + 1, NULL);
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, 
    (LPTHREAD_START_ROUTINE)LoadLibraryA, alloc, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
std::cout << "Injected.\n";
return 0;