Zscalerのブログ
Zscalerの最新ブログ情報を受信
購読するNodeLoader Exposed: The Node.js Malware Evading Detection
Introduction
Zscaler ThreatLabz discovered a malware campaign leveraging Node.js applications for Windows to distribute cryptocurrency miners and information stealers. We have named this malware family NodeLoader, since the attackers employ Node.js compiled executables to deliver second-stage payloads, including XMRig, Lumma, and Phemedrone Stealer. Node.js is a well-known framework for building web-based services such as chat applications, online gaming platforms, and live collaboration tools. However, it is less frequently used to build native client-side applications for common desktop platforms. As a result, there are very few antivirus signatures for Node.js based malware. In this blog, we dive into the details of NodeLoader and explore the novel techniques used by the threat actors.
Key Takeaways
- ThreatLabz has observed threat actors deploying NodeLoader using the Node Package Manager (NPM)
pkg
module to turn Node.js code into standalone Windows executable files for malicious purposes. - The threat actors employ social engineering and anti-evasion techniques to deliver NodeLoader undetected.
- NodeLoader uses a module called
sudo-prompt
, a publicly available tool on GitHub and NPM, for privilege escalation. - The malware delivered by NodeLoader includes cryptocurrency miners and information stealers.
Attack Chain
As game streaming has gained in popularity, threat actors are increasingly abusing community platforms like YouTube and Discord to spread malware. Threat actors are creating videos where they show alleged game hacks. However, instead of directing gamers to the game hack, the threat actors are providing links to websites that lead to malware. These websites closely resemble other legitimate gaming websites to avoid raising suspicion, and entice visitors to download a ZIP archive file, extract, and run a malicious executable that we have named NodeLoader. These NodeLoader executables are developed in Node.js and compiled using the pkg
module. NodeLoader downloads a PowerShell (PS) script named script.ps1
which in turn, proceeds to download and execute second-stage payloads such as a cryptocurrency miner or information stealers.
The figure below illustrates the entire attack chain.
Figure 1: High-level diagram for the NodeLoader attack chain.
ThreatLabz discovered two YouTube channels with several videos embedding the malicious links in their descriptions. These videos have garnered thousands of views. Some YouTube video descriptions include links to download the malware from popular software distribution services like MediaFire, while others contain links to websites set up by the threat actors themselves.
The figure below shows the malicious links in several YouTube video descriptions:
Figure 2: Example malicious links embedded in YouTube video descriptions that lead to NodeLoader distribution sites.
The malicious website bears a strong resemblance to Korepi (a popular game utility website), as shown in the figure below.
Figure 3: Example malicious website imitating the Korepi game utility website that delivers NodeLoader and ultimately second-stage malware payloads.
Technical Analysis
The threat actor relies on the user to download, extract, and run the malicious NodeLoader executable file from the fake website. NodeLoader’s code is written in Node.js using JavaScript. The code imports the sudo-prompt
module to run commands with elevated privileges. The Node.js code, along with all necessary dependencies, is compiled into a binary executable using the pkg
module. This step packages everything needed to run the Node.js code, including the V8 JavaScript engine library.
When the user runs the NodeLoader executable, the V8 JavaScript engine initiates the execution of the Node.js code. Any input/output (I/O) operations are managed by libuv
, a multi-platform support library used by Node.js to handle asynchronous I/O tasks. In the compiled NodeLoader executable, the payload and prelude are written in the overlay. The payload is the main source code in bytecode form, which is later executed by the V8 JavaScript engine.
NodeLoader downloads the next stage PS script. Using sudo-prompt
for privilege escalation, NodeLoader creates a directory located at C:\ProgramData\SystemInfo
and sets the attributes to hidden using the attrib
command. NodeLoader then downloads script.ps1
, writes the file into the newly created SystemInfo
directory as add_exclusion.ps1
, and executes it.
User account control (UAC) prompt using sudo-prompt
On the Windows platform, the Node.js sudo-prompt
package escalates privileges by leveraging the built-in user account control (UAC) system. By default, the Windows UAC prompts the user to allow or deny running tasks as administrator. When NodeLoader is run, sudo-prompt
writes the batch command into a file named execute.bat
in the user’s temporary directory, then runs this batch file using PS with the -Verb RunAs
option.
- If UAC is configured to not display a prompt, the batch file will be executed in elevated mode without user consent.
- Otherwise, the batch file will execute in elevated mode if the user grants permission in the prompt.
In one example, sudo-prompt
was included as a package in the Node.js code but was not used to gain administrator privileges. This meant NodeLoader relied on the user to manually run it as an administrator to work correctly.
In another example, when sudo-prompt
is used, the process works differently. It creates a batch file named execute.bat
in the temporary folder and runs it automatically using PS.
Defense evasion
For defense evasion, NodeLoader runs the tasklist
command to check for the following process names:
chrome.exe
opera.exe
operagx.exe
firefox.exe
steam.exe
spotify.exe
discord.exe
telegram.exe
gamingservice.exe
lightshot.exe
epicgameslauncher.exe
For each process name in the array, NodeLoader calls a function that checks if the given process name is present in the output of the tasklist command using the JS functions includes()
and some()
. The result of some()
(true/false) is then passed to another function, which determines whether the process should continue running or be terminated.
If none of these specified processes are running, NodeLoader terminates. However, if any of these processes are detected, NodeLoader proceeds to the next stage, which involves downloading and executing a PS script via an HTTP GET request.
PowerShell (PS) script
The PS script downloads drop1.exe
and drop2.exe
from the same web server and executes these scripts. In all the cases we observed, drop2.exe
was saved as driver.exe and drop1.exe was saved as taskhost.exe
, both being downloaded to the previously created directory C:\ProgramData\SystemInfo
.
We observed different versions of the PS script. A simpler version was used at first, with additional functionalities being incorporated in later versions. In the later versions, the script included functionality to retrieve and hide the main window of NodeLoader. The malware also added the capability to check if a process is running with administrative privileges.
Payload execution
The PS script downloads the payloads into the directory C:\ProgramData\SystemInfo
and executes them. In all the cases we observed, the script downloads an XMRig cryptocurrency miner and an information stealer. The specific information stealer varied in different instances.
XMRig cryptocurrency miner
The drop2.exe
executable is a malware dropper that delivers XMRig, an open source cryptocurrency miner. This executable drop2.exe
also performs a number of evasion techniques including the following:
- The malware adds the directory
C:\ProgramData
to the Windows Defender exclusion path to avoid detection. - The malware attempts to uninstall Windows updates related to the Windows Malicious Software Removal Tool (KB890830).
- The malware sets the registry key
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\MRT\DontOfferThroughWUAU
to prevent Windows from offering this update even if it is available. - The malware attempts to stop the Windows Event Log Service (
EventLog
), which is responsible for maintaining a record of system, security, and application events on a Windows system.
In order to establish persistence, the malware creates a service named PHVUTTIO
using the sc
command, with the binary path set to C:\ProgramData\utblsmnncewd\bbecxurdegum.exe
and with the parameter start=”auto”
meaning that this service will automatically start when the system boots.The malware then creates a copy of itself in the directory specified in the binary path.
We discovered that the transactions associated with the attacker’s cryptocurrency address were very recent as shown in the figure below.
Figure 4: Recent transactions of the cryptocurrency address associated with the attack.
Phemedrone Stealer
Phemedrone Stealer was downloaded from the web server using the name drop1.exe
. Phemedrone steals data, like history, cookies and login credentials from Google and Microsoft browsers, and uploads it to Telegram.
Lumma Stealer
- In addition to downloading Phemedrone, the threat actors utilized a separate malicious URL to deliver a loader for Lumma Stealer. This loader, named
taskhost.exe
, was downloaded to theC:\ProgramData\SystemInfo
directory using a PS script. - The initial loader is a .NET executable, which contains a shellcode and the Lumma Stealer payload, both stored in RC4 encrypted form. The loader decrypts the shellcode and the Lumma Stealer payload. Post decryption, the shellcode is written into its own memory space with
PAGE_EXECUTE_READWRITE
permissions and executed as a thread, with the base address of the Lumma Stealer payload passed as an argument. The shellcode dynamically resolves APIs by traversing the process environment block (PEB), with the API names stored as plain text strings. - Once the APIs are resolved, the shellcode creates a process named
RegAsm.exe
in a suspended state, writes the Lumma Stealer payload into the memory of this newly created process, and then executes the payload's entry point, thereby activating Lumma Stealer. - During our analysis, we observed that the threat actors were periodically changing the stealer malware hosted on the web server.
Low antivirus detection rates
When compiled using the pkg
NPM module, a single line of code results in a large Windows binary exceeding 35 MB. This large file size complicates detection for some security products. In addition, there are far fewer signatures for malicious JavaScript-based code. As a result, many of the NodeLoader binaries associated with this campaign currently have zero antivirus and EDR detections. The appendix provides indicators of compromise including sample hashes.
Conclusion
As game streaming and community platforms continue to rise in popularity, threat actors will seek new ways to abuse them. This underscores the critical importance of educating those who may fall victim to such attacks and reveal novel techniques for malware distribution to improve detection rates.
Zscaler plays a vital role in thwarting such attacks through full SSL inspection at scale, browser isolation, and policy-driven access control. The Zscaler Cloud Sandbox has consistently proven successful in detecting the malware involved in this campaign and its numerous variants. Zscaler ThreatLabz remains committed to monitoring and tracking these campaigns, sharing valuable insights with the wider community.
Zscaler Coverage
Zscaler’s multilayered cloud security platform detects indicators related to this campaign at various levels as shown below.
Figure 5: Zscaler Cloud Sandbox report for NodeLoader.
Indicators Of Compromise (IOCs)
Host indicators
Type | Stage | IOC | Description | Threat Name |
---|---|---|---|---|
MD5 | Stage 2 |
| NodeLoader executables | |
MD5 | Stage 3 |
| PS script | |
MD5 | Final payload |
| Phemedrone Stealer | |
MD5 | Final payload |
| Phemedrone Stealer | |
MD5 | Final payload |
| XMRig coin miner | |
MD5 | Final payload |
| Lumma Stealer |
Network indicators
Type | Stage | IOC | Description |
---|---|---|---|
URL | Stage 1 | korepi[.]xyz | Fraudulent website |
URL | Stage 2 | hxxps://chillers.com[.]ar/temp/lotrik.exe | URL to download Lumma Stealer |
IP | Stage 2 | 195[.]10[.]205[.]253 | Open directory |
URL | Stage 4 | condedqpwqm[.]shop | Lumma C2 |
URL | Stage 4 | locatedblsoqp[.]shop | Lumma C2 |
URL | Stage 4 | stagedchheiqwo[.]shop | Lumma C2 |
URL | Stage 4 | stamppreewntnq[.]shop | Lumma C2 |
URL | Stage 4 | millyscroqwp[.]shop | Lumma C2 |
URL | Stage 4 | caffegclasiqwp[.]shop | Lumma C2 |
URL | Stage 4 | traineiwnqo[.]shop | Lumma C2 |
MITRE ATT&CK Techniques
Type | Technique Name |
---|---|
User Execution: Malicious File | |
Command and Scripting Interpreter: PowerShell | |
Impair Defenses: Disable or Modify Tools | |
Impair Defenses: Disable Windows Event Logging | |
Create or Modify System Process: Windows Service | |
Exfiltration Over C2 Channel |