Nowadays, more malware developers are using unconventional programming languages to bypass advanced detection systems. The Node.js malware Lu0Bot is a testament to this trend.
By targeting a platform-agnostic runtime environment common in modern web apps and employing multi-layer obfuscation, Lu0Bot is a serious threat to organizations and individuals.
Although currently, the malware has low activity, the attackers are likely waiting for the right moment to strike.
To be prepared for any future scenario, a team of analysts conducted an in-depth technical analysis of one of the recent samples of Lu0Bot and published an article documenting their process.
Here’s an overview of their research.
Static analysis of the Lu0Bot sample
The sample under investigation used an SFX packer, a self-extracting archive that can be opened with any archive utility. Its contents were explored individually.
|The content of the BAT file
The first line in the file contained a comment that remained unclear and was not referenced later.
Next, the EXE file bundled multiple files, including a Node interpreter called fjlpexyjauf.exe.
Then, the interpreter received a file with bytes and a number (%1% in the screenshot) that likely served as the encryption key for the byte file.
2. eqnyiodbs.dat files
The file was divided into byte blocks, which were then merged to create the Node interpreter.
|Contents of eqnyiodbs files
3. lknidtnqmg.dat file
This file had encrypted bytes in Base64, which could be decrypted using the given input number.
|Contents of the lknidtnqmg.dat file
4. gyvdcniwvlu.dat file
This driver allowed 32-bit programs on x64 systems to convert key scan codes into Unicode characters, likely used for keylogging functionality in the main process.
Dynamic malware analysis of Lu0Bot in ANY.RUN
The next step involved investigating the EXE file and lknidtnqmg.dat in the ANY.RUN interactive malware sandbox to monitor their behavior and either decrypt the bytes or locate them decrypted in the process memory.
The analysis revealed that, upon execution, the main process started a BAT file that launched an EXE file. The code accepted encrypted JS input and gathered system data using WMIC, including information about process execution location, which aligned with the T1047 MITRE technique.
|The process tree during sample execution
It was discovered that the interpreter was copied to the startup folder. The connection to the domain continued after the system restarted, allowing the bot to remain operational.
Additionally, the malware demonstrated a unique approach to domain connection by assembling various parts into a single entity within the JS code.
Technical analysis of Lu0Bot malware using a disassembler and debugger
To access the main JS code, the team:
- Unpacked the SFX archive
- Ran a command to collect the Node.js file
- Launched fjlpexyjauf.exe in x32dbg, entering the incoming data into the command line
- Got to the point where JS code execution started
- Located the code in memory and saved a dump
To see how the unpacking and dump extraction processes were conducted, refer to the original article. For this overview, let’s focus on the code analysis.
Analyzing the JS code
|Result of code transformation
The code began with an array of encrypted strings. Then, specific elements were moved to the end of the array through manipulation. After that, a function was implemented to decrypt the array strings using an alternative form of BASE64 (T1132.002), followed by URL encode-decode, and finally, RC4.
This function was called using two variables:
1. An element from the array.
2. The RC4 key.
With the help of a special script, the lines were decrypted, revealing that portions of the domains were hard-coded into the sample.
|After code deobfuscation
Following that, the section of the code responsible for assembling the domain was discovered.
To debug, the team used Node.js with its inspect-brk parameter (node.exe –inspect-brk *obfuscate dump without garbage bytes*), placing a breakpoint on the “var” keyword and observing the output generated by each line.
It was found that the first function (ginf) gathered system information and produced a 15-element array with system details.
|An array containing the output of the ginf function
The second function (hwco) used the 15-element array from the ginf function as input, which generated an output comprising the tail-end of the domain until the dot. Further analysis revealed that this output was a hash of the gathered system data.
|String output from the hwco function
The port, number, and domain segment after the dot were extracted from the acc array and then assigned to variables.
|Extracting elements from the acc array
A random number was added to the domain segment after the dot. The next line selected an alternative domain if certain conditions were met.
|Choose domain after the point
After several other operations, the domain was fully assembled, and all necessary elements were packed into a JSON object.
After executing, the malware searched for an address for data transmission. Once the server received the traffic, it sent JS code.
As part of their effort, the team managed to uncover a wealth of intelligence and IOCs, as well as wrote YARA, Sigma, and Suricata rules. You can access it in the article.
All of the findings were incorporated into ANY.RUN, enabling the service to quickly identify any Lu0Bot sample and reveal C2 domains after decrypting strings.
Lu0bot is an unusual malware that combines Node.js and executable JS code. It possesses a unique domain structure and uses custom encryption methods for strings.
Although it currently exhibits a low level of activity, Lu0bot can pose a significant risk if its campaign scales and the C2 server starts actively responding.
Protect your organization from this and other malware by using ANY.RUN to quickly analyze any suspicious files or links and get a conclusive verdict in seconds.