Recently, Morphisec Threat Labs identified and prevented multiple sophisticated Lua malware variants targeting the educational sector. These attacks capitalize on the popularity of Lua gaming engine supplements within the student gamer community.
Introduction
In March 2024, OALabs reported on a new packed Lua loader aimed at the gaming community. This report was followed in April by additional threat insights by McAfee. In the months since, Morphisec Threat Labs observed its continued spread and evolution, with telemetry data indicating that this malware strain is highly prevalent across North America, South America, Europe, Asia, and even Australia. This post provides an analysis of the loader associated with this persistent attack.
Over the past year, the delivery of Lua malware appears to have undergone simplification, possibly to reduce exposure to detection mechanisms. The malware is frequently delivered using obfuscated Lua scripts instead of compiled Lua bytecode, as the latter can trigger suspicion more easily.
We would like to credit @Herrcore for their assistance in some of the deobfuscation efforts.
Technical Introduction
We have observed that users searching for game cheats often end up downloading files from platforms like GitHub or similar sources. Today, Lua malware is typically delivered in the form of an installer or a ZIP archive. The ZIP archive usually contains four components: a Lua compiler, a Lua DLL file, an obfuscated Lua script, and a batch file. The batch file executes the Lua script by passing arguments to the Lua compiler.
- Lua51.dll - LuaJIT Runtime interpreter
- Compiler.exe - a thin compiled Lua loader
- Lua script – Malicious Lua script
- Launcher.bat - Batch script used to run Compiler.exe with the malicious script as parameter
Post execution of the batch file, the loader establishes communication with a C2 server, sending details about the infected machine. In response, the server provides tasks divided into two categories: Lua loader tasks, which involve actions such as maintaining persistence or hiding processes, and task payloads, which focus on downloading new payloads and applying configurations to them.
We will get into more details throughout this post.
Delivery Techniques
The delivery techniques, such as SEO poisoning, remain largely unchanged from those previously described by OALabs and McAfee. Notably, we identified an advertisement for the Solara and Electron executors - popular cheating script engines frequently associated with Roblox—leading to various Lua malware variants hosted across multiple GitHub repositories.
Most of the download links are associated with github.com/user-attachments push requests.
Compiler.exe and lua51.dll
The lua51.dll is a widely recognized runtime interpreter for Lua, often employed as an “SDK” to extend the functionality of existing software through an accessible and flexible scripting engine.
The Compiler.exe acts as a lightweight loader, responsible for loading lua51.dll and invoking its “SDK” exported functions to process the specified script. In earlier campaigns, Compiler.exe was designed to load and execute Lua bytecode using lua51.dll. However, in the more recent campaigns, it loads a plain Lua script file instead, leveraging Lua's runtime capabilities to interpret the obfuscated script dynamically, allowing for greater flexibility in executing malicious logic.
Lua Script (config)
As previously identified by OALabs, the script is obfuscated using the Prometheus obfuscator. In their analysis, they needed to decompile the bytecode; however, in the recent campaigns described here, the parameter is no longer a bytecode file but rather a directly obfuscated script file.
Prometheus Obfuscator is a tool designed to enhance software security by employing advanced obfuscation techniques. Its primary purpose is to protect applications from reverse engineering and unauthorized access, making it significantly more difficult for researchers to analyze and understand the code. With capabilities such as code transformation and control flow obfuscation, Prometheus ensures that the underlying logic remains concealed from scrutiny.
The content of the Lua obfuscated script is seen below:
A simple beautification of the script will result in (similar string structure is identified at the bytecode file samples):
Post deobfuscation, we can easily dump the strings from memory:
Anti-reversing
The obfuscated code is initially written in a single line, and when using formatting tools to reorganize the code structure for readability, an error message “Tamper Detected!” appears during code execution.
The obfuscator's method involves line detection, where it deliberately triggers an error at least twice from different locations. It then verifies whether the line numbers are the same for both areas of the code.
An example that demonstrates the technique:
- The attacker defines a function that deliberately throws an error (division by zero).
- The function throws an error and parses the line of the error to know from which line in the code it occurred. The pcall function makes a call to another function and returns an array. The first element indicates success, and the second element contains the error message if it failed. In this case, the error format in Lua is structured as `filename:line_number:message`.
- An additional inline function is generated to ensure that the error is thrown from a different location in the code. Upon execution the function checks whether the line number in the error message matches the previous line number to determine if the code has been edited.
Prometheus obfuscator implementation for this anti-reformatting / anti-beautify functionality is well described here.
The attacker utilizes the `ffi` library for the direct execution of C code.
What is FFI?
The FFI library allows Lua code to call C functions and use C data structures directly without needing to write C wrapper code. This is particularly useful for integrating Lua with C libraries or for improving the performance of certain operations by leveraging native C functions.
Import Modules and Functions
The script imports the modules by traversing the PEB (Process Environment Block), and then uses the module's EXPORT table:
Module |
Functions |
shell32.dll |
SHGetFolderPathW , SHCreateDirectoryExW , PathFileExistsW |
advapi32.dll |
RegCreateKeyExW , RegSetValueExW , RegCloseKey , RegGetValueW , RegCreateKeyExW , RegSetValueExW , RegCloseKey , RegGetValueW , RegGetValueW , RegQueryValueExW , OpenProcessToken , GetTokenInformation , CryptAcquireContextW , CryptGenRandom , CryptReleaseContext , GetUserNameW |
shlwapi.dll |
PathFileExistsW |
winbrand.dll |
BrandingFormatString |
kernel32.dll |
WinExec , CreateMutexW , SetFileAttributesW , GetModuleFileNameW , CopyFileW |
wininet.dll |
InternetOpenW , InternetConnectW , HttpOpenRequestW , InternetOpenUrlW , HttpSendRequestW , InternetReadFile , InternetCloseHandle |
Mutex-based
The script uses a mutex using a long constant string
In some cases, this string includes a concatenated, predefined number.
Persistence
The script establishes persistence by generating a random task name from a predefined list using the following command:
`schtasks /create /sc daily /st %02d:%02d /f <Name> /tn <App> /tr <Path>`
Potential task name list:
Information gathering
In the first stage, the script sets the same name for the `UserAgent` as the one defined for the `mutex`, then initiates a GET request to `http://ip-api[.]com/json/` to retrieve information about the victim. During this process, the script validates network connection by attempting to communicate with `https://www.microsoft.com`.
Then the script retrieves the `MachineGuid` from the attacker's machine (located at `Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography`). This string is concatinated along with the `loaderId`, `GUID`, `computer name`, `user name`, `IP`, `country`, `city`, `timezone`, `operating system`, and `architecture`.
Afterward, the script encodes the string using a simple symmetric encryption method that combines a basic form of a stream cipher or XOR cipher with byte addition. After encryption, the script converts the bytes to Base64 format.
Finally, the script captures a screenshot of the compromised computer and sends the adversary C2, the collected data from the computer along with screenshots.
C2 communication
After the data is sent to the attacker's server, the server can respond in one of two ways:
- Blocked – indicating the request is denied.
- JSON Response – commands of the following categories; `loader` and `tasks`.
- Loader - These are actions for the "lua loader" to execute, such as hiding, restarting, maintaining persistence, etc.
- Tasks - These are meant to load additional payloads and define which configurations should be applied when loading them.
If the server returns a "blocked" response, the malware attempts to connect to an alternate predefined address. If that is also blocked, it accesses pastebin[.]com/raw/mmABULhh to retrieve a new address. If all attempts fail, the process terminates.
If a valid response is received, the `lua loader` saves the output in the `C:\Users\<User>\Pictures\` folder, using the machine’s `GUID` as the filename.
After saving the file, the loader executes the required tasks and then sends a response back to the server with the task ID (that was initially provided.
The payloads are CypherIT Loader / Crypter , Redline).
Loader Config
Command |
Description |
bypass_defender |
`powershell "Start-Process <#rand name> powershell <#rand name> -Verb <#rand name> runAs" -WindowStyle hidden -Argument 'Add-MpPreference -ExclusionPath $env:SystemDrive -ExclusionExtension .exe, .dll -Force` |
autorun |
Create task `schtasks /create /sc daily /st <time> /f /tn <generated name> /tr "<compiler file> <script file>"` |
relaunch |
implements a delay using a loop (`Sleep (1000);`) |
tablet |
pop up message with `MessageBoxW` |
hide |
Set `SetFileAttributesW` to flag `FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM` to files |
persistence |
The script copies itself files to the directory `C:\Users\john\AppData\Local\<folder>\` and creates a scheduled task using the following command: `schtasks /create /sc daily /st <time> /f /tn <generated name> /tr "<compiler file> <script file>"`
If the current process has elevated privileges, additional steps are taken to bypass Windows Defender. `powershell -WindowStyle hidden Add-MpPreference -ExclusionPath <path> -Force` |
Task Config
Command |
Description |
id |
Task number |
link |
Link to download additional payloads |
file_path |
which folder to write (`AppData,Desktop ..`) |
file_name |
File location to be written |
start |
Whether to run the file or not `exe` - create task and run `powershell -Command \"Register-ScheduledTask -TaskName 'task' -Action (New-ScheduledTaskAction -Execute '<task>') -Trigger (New-ScheduledTaskTrigger -At (Get-Date).AddMinutes(1) -Once) -Settings (New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable) -Force\""` or using `WinExec`
`DLL` - using `loadlibrary` and export function in `cfg` (run time) or run command `rundll32 <dll>, <export>`
`ps1` - `powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File <file>` `cmd` or `bat` - `cmd /c <file>` |
autorun |
execute the file with task |
hide |
Set `SetFileAttributesW` to flag `FILE_ATTRIBUTE_HIDDEN` to files |
pump |
increase the size of file |
dll_loader |
using for loading DLL file and specific export |
query |
If there is a query for the link |
Python code snippet for decoding the strings:
Conclusion
Based on our investigation, the malware ultimately leads to the deployment of Infostealers, notably Redline Infostealers. Infostealers are gaining prominence in the landscape as the harvested credentials from these attacks are sold to more sophisticated groups to be used in later stages of the attack. Redline notably has a huge market in Dark web selling these harvested credentials.
How Morphisec Helps
Automated Moving Target Defense (AMTD) from Morphisec effectively stops malware attacks at various stages of the attack chain. Morphisec doesn’t rely on signature or behavioral patterns. Instead, it uses its patented AMTD technology to prevent the attack at its earliest stages, preemptively blocking attacks on memory and applications, and effectively remediating the need for response.
Schedule a demo today to see how Morphisec stops Lua malware and other new and emerging threats.
IOCs
77.73.129[.]64 |
C2 Lua loader |
185.221.198[.]82 |
C2 lua loader |
146.19.128[.]146 |
C2 Lua loader |
212.193.4[.]66 |
C2 Lua loader |
185.236.228[.]12 |
RedLine |
185.208.158[.]36 |
RedLine |
Solaraexec[.]cc |
Fake website |
electronexec[.]com |
Fake website |
github[.]com/user-attachments/files/16201677/getter.json |
Task Payload
|
github[.]com/user-attachments/files/16968308/socket.json |
Task Payload |
github[.]com/user-attachments/files/17057089/SolaraV3.zip |
Lua Loader |
github[.]com/user-attachments/files/16737781/Electron.zip |
Lua Loader
|
`schtasks /create /sc daily /st <time> /f /tn <generated name> /tr "<compiler file> <script file>"` |
Persistent |
pastebin[.]com/raw/mmABULhh |
C2 lua loader |
`1crorgz4bo93e47pxiiyklanj0mfswyjtxeg56nahc5sm58` |
Mutex |
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography |
Registry |
Hashes
B3ecbe4132598ef746e2111ba29f46af06886677d18595b6845849577121707a |
CypherIT |
3B515469ABA46A0A08D8FCBD8FEB98CE9BCEBFA1A48D56BE586DC9AA4584C0C2 |
CypherIT |
308721F4DC7818AED5F0282A3EFA5944C1D16E97B0CB3BB5786009A186EA9791 |
CyperIT |
B3ECBE4132598EF746E2111BA29F46AF06886677D18595B6845849577121707A |
CyperIT |
98418f7079cc11970899a18098425d22414663301dbbad1c892a8c702b90223f |
Lua Loader |
9aacf8f59b8daff24161549378c95174dac40b2fb01d7b8a78b513d3d35f6411 |
Lua Loader |
Afd731bb658525845c8ee4216b05ce0c9c8b2e8b745884fbefeb01ef331163a1 |
Lua Loade |
8e59a9de633fc1e0a9da10268c606b898e7d5a6645ee21851465e027aefbaec9 |
Lua Loade |
AECDAA94885C3FCD856C3516311BF366AC5EE13B43C28560EADC1F637EFCF432 |
Lua Loade |
E09370c9adc09c15eb8d05301bd3c74ef76e98b8a2fa2089df9c4ec5d7b4e047 |
Redline |