SmartLoader reverse engineering: LuaJIT loader with Polygon smart-contract C2 resolver tied to LummaStealer delivery
SmartLoader is a commodity loader in active deployment, attributed to Malware-as-a-Service infrastructure linked to LummaStealer delivery in recent campaigns. Reverse engineering shows it is built almost entirely from off-the-shelf parts: a stock signed LuaJIT 2.1.0-beta3 interpreter, a commercial Lua VM obfuscator from the game-cheat scene (Prometheus/IronBrew/Luraph lineage), a hand-written Win32 FFI binding layer, and a Polygon smart contract used as a dead-drop C2 resolver. The design favors breadth over depth, targeting consumer systems rather than hardened corporate environments with mature EDR. The analyzed sample's hardcoded dependency on polygon-rpc.com has been broken since February 2026, so the stage-2 URL is never returned in normal execution. The analyst used symbolic execution to reach the downstream logic. The article is truncated before the persistence stage, which pulls stage-3 payloads from rotating GitHub repositories.
Detalhes técnicos
- Delivery/execution: a ZIP with four files: a batch launcher (
start luajit.exe lang.txt), a clean LuaJIT interpreter, its runtime DLL (lua51.dll) and a 354 KB obfuscated Lua payload. Execution is borrowed from a signed third-party runtime, which shrinks the static-detection surface. - Obfuscation: a VM-based packer with an encrypted constant table and dispatch loop. Integrity checks (self-checksum detecting INT3 breakpoints, aborting with
Tamper Detected!) are an obfuscator feature, not custom code. PEB flag checks (BeingDebugged, NtGlobalFlag, heap flags) are also present. - Win32 access: a single
ffi.cdefblock declares PE, PEB and GDI structures and API prototypes. A 10-byte RWX x64 shellcode stub (mov rax, gs:[0x60]; ret) retrieves the PEB pointer. The loader walksPEB.Ldr.InMemoryOrderModuleList, resolves exports by hash and loads wininet, shlwapi and shell32 viantdll!LdrLoadDll. It uses no direct or indirect syscalls, so all calls remain hookable user-mode APIs. - Reconnaissance: computer name, screen resolution, architecture (IsWow64Process), OS version, admin status (TOKEN_ELEVATION) and geo-IP via ip-api.com. A single-instance mutex
xp30pub1tze8uisjis created. A full-desktop screenshot is captured via GDI and POSTed as an uncompressed BMP (multipart/form-data) tohttp://178.17.59.88/api/<fingerprint>, where the fingerprint is comma-separated hex bytes, base64-encoded. - C2 resolution: an
eth_callJSON-RPC request to polygon-rpc.com targets contract0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdc(selector0x3bc5de30,getData()), returning the stage-2 URLhttp://89.169.12.241. The dead-drop model is asynchronous and unidirectional, suited to broadcast tasking across many victims. The contract creator wallet shows 9setData()updates, and the article estimates roughly $0.10 for a four-month resilient C2. - Persistence/stage 3: the article states that stage-3 payloads are pulled from rotating GitHub repositories, but the available text does not cover this section.
Remediação
The article states its IOCs are listed at the bottom, but they are not in the truncated text. From the available content, defenders can hunt for luajit.exe / lua51.dll running from user-writable paths with a .txt script argument, outbound requests to polygon-rpc.com from non-blockchain hosts, the listed IPs and the mutex name. Because the loader relies on hookable user-mode APIs, properly configured EDR and ETW telemetry should be able to observe its activity.
Linha do tempo
-
SmartLoader reverse engineering: LuaJIT loader with Polygon smart-contract C2 resolver tied to LummaStealer delivery
ler a análise desta fonte ocultar
SmartLoader is a commodity loader in active deployment, attributed to Malware-as-a-Service infrastructure linked to LummaStealer delivery in recent campaigns. Reverse engineering shows it is built almost entirely from off-the-shelf parts: a stock signed LuaJIT 2.1.0-beta3 interpreter, a commercial Lua VM obfuscator from the game-cheat scene (Prometheus/IronBrew/Luraph lineage), a hand-written Win32 FFI binding layer, and a Polygon smart contract used as a dead-drop C2 resolver. The design favors breadth over depth, targeting consumer systems rather than hardened corporate environments with mature EDR. The analyzed sample's hardcoded dependency on polygon-rpc.com has been broken since February 2026, so the stage-2 URL is never returned in normal execution. The analyst used symbolic execution to reach the downstream logic. The article is truncated before the persistence stage, which pulls stage-3 payloads from rotating GitHub repositories.
Technical Details
- Delivery/execution: a ZIP with four files: a batch launcher (
start luajit.exe lang.txt), a clean LuaJIT interpreter, its runtime DLL (lua51.dll) and a 354 KB obfuscated Lua payload. Execution is borrowed from a signed third-party runtime, which shrinks the static-detection surface. - Obfuscation: a VM-based packer with an encrypted constant table and dispatch loop. Integrity checks (self-checksum detecting INT3 breakpoints, aborting with
Tamper Detected!) are an obfuscator feature, not custom code. PEB flag checks (BeingDebugged, NtGlobalFlag, heap flags) are also present. - Win32 access: a single
ffi.cdefblock declares PE, PEB and GDI structures and API prototypes. A 10-byte RWX x64 shellcode stub (mov rax, gs:[0x60]; ret) retrieves the PEB pointer. The loader walksPEB.Ldr.InMemoryOrderModuleList, resolves exports by hash and loads wininet, shlwapi and shell32 viantdll!LdrLoadDll. It uses no direct or indirect syscalls, so all calls remain hookable user-mode APIs. - Reconnaissance: computer name, screen resolution, architecture (IsWow64Process), OS version, admin status (TOKEN_ELEVATION) and geo-IP via ip-api.com. A single-instance mutex
xp30pub1tze8uisjis created. A full-desktop screenshot is captured via GDI and POSTed as an uncompressed BMP (multipart/form-data) tohttp://178.17.59.88/api/<fingerprint>, where the fingerprint is comma-separated hex bytes, base64-encoded. - C2 resolution: an
eth_callJSON-RPC request to polygon-rpc.com targets contract0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdc(selector0x3bc5de30,getData()), returning the stage-2 URLhttp://89.169.12.241. The dead-drop model is asynchronous and unidirectional, suited to broadcast tasking across many victims. The contract creator wallet shows 9setData()updates, and the article estimates roughly $0.10 for a four-month resilient C2. - Persistence/stage 3: the article states that stage-3 payloads are pulled from rotating GitHub repositories, but the available text does not cover this section.
Remediation
The article states its IOCs are listed at the bottom, but they are not in the truncated text. From the available content, defenders can hunt for
luajit.exe/lua51.dllrunning from user-writable paths with a.txtscript argument, outbound requests to polygon-rpc.com from non-blockchain hosts, the listed IPs and the mutex name. Because the loader relies on hookable user-mode APIs, properly configured EDR and ETW telemetry should be able to observe its activity. - Delivery/execution: a ZIP with four files: a batch launcher (