/
← Voltar ao feed
medium

SmartLoader reverse engineering: LuaJIT loader with Polygon smart-contract C2 resolver tied to LummaStealer delivery

1 fonte(s) · 1 atualização(ões) · publicado 18/05/2026 16:54 · coletado há 4 dias

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.cdef block 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 walks PEB.Ldr.InMemoryOrderModuleList, resolves exports by hash and loads wininet, shlwapi and shell32 via ntdll!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 xp30pub1tze8uisj is created. A full-desktop screenshot is captured via GDI and POSTed as an uncompressed BMP (multipart/form-data) to http://178.17.59.88/api/<fingerprint>, where the fingerprint is comma-separated hex bytes, base64-encoded.
  • C2 resolution: an eth_call JSON-RPC request to polygon-rpc.com targets contract 0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdc (selector 0x3bc5de30, getData()), returning the stage-2 URL http://89.169.12.241. The dead-drop model is asynchronous and unidirectional, suited to broadcast tasking across many victims. The contract creator wallet shows 9 setData() 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

  1. yokai.hakaisecurity.io ↗ · pub. 18/05/2026 16:54 · coletado 19/10 18:03 primeiro registro

    SmartLoader reverse engineering: LuaJIT loader with Polygon smart-contract C2 resolver tied to LummaStealer delivery

    ler a análise desta fonte

    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.cdef block 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 walks PEB.Ldr.InMemoryOrderModuleList, resolves exports by hash and loads wininet, shlwapi and shell32 via ntdll!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 xp30pub1tze8uisj is created. A full-desktop screenshot is captured via GDI and POSTed as an uncompressed BMP (multipart/form-data) to http://178.17.59.88/api/<fingerprint>, where the fingerprint is comma-separated hex bytes, base64-encoded.
    • C2 resolution: an eth_call JSON-RPC request to polygon-rpc.com targets contract 0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdc (selector 0x3bc5de30, getData()), returning the stage-2 URL http://89.169.12.241. The dead-drop model is asynchronous and unidirectional, suited to broadcast tasking across many victims. The contract creator wallet shows 9 setData() 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.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.