Lumma Stealer, also known as LummaC2 Stealer, is a customizable malware written in C/C++ that allows for efficient and low-level access to system resources. It uses extensive obfuscation and anti-analysis features, making it highly effective and hard to detect. It is distributed as a Malware-as-a-Service (MaaS) model, with several plans available on underground forums and Telegram channels. This malicious software regularly gets updates that improve and expand its functionality, making it a serious threat.
Lumma Stealer is designed to steal sensitive data from compromised devices. It targets private browser data, cryptocurrency wallets, email credentials, financial information, and more. To evade detection, it uses sophisticated techniques like encryption and event-controlled operations. Lumma Stealer specifically targets Windows operating systems from Windows 7 to Windows 11.
This blog post demonstrates how Wazuh can detect and respond to Lumma Stealer on a monitored Windows endpoint.
Behavioral analysis
- Lumma Stealer employs an anti-sandbox technique (trigonometry) that monitors cursor movements to detect genuine human activity, delaying its execution until such behavior is observed. This approach allows it to effectively evade detection in many malware analysis environments that don’t simulate mouse actions realistically.
- Once Lumma Stealer detects cursor movement, indicating human activity, it records the next five cursor positions by executing
GetCursorPos()
, with a 50-millisecond pause between each capture. This checks that the movements are human-like, ensuring it is not running in a sandboxed environment designed to mimic basic user activity. - Lumma Stealer evades detection by using event-controlled write operations, enabling it to write data only under specific conditions, which helps it mimic legitimate processes and avoid triggering alerts.
- Lumma Stealer typically employs AES-256 encryption to obfuscate its payloads and exfiltrated data, concealing malicious activities from security tools and complicating reverse-engineering efforts.
- The malware detects the presence of a debugger by using functions like
IsDebuggerPresent
andOutputDebugString
. - The malware creates a suspended
BitLockerToGo.exe
process and allocates memory using theVirtualAllocEx
function. This allows Lumma Stealer to be executed within a trusted Windows process and evade detection through process masquerading. - The malware escalates privileges by locking its memory pages to stay in RAM, preventing writing to the disk. It then sets its token to
SeDebugPrivilege
, using a Microsoft debugging tool to elevate its process privileges. - The malware injects itself into random processes, consistently targeting
svchost.exe
,aspnet_wp.exe
, andlsass.exe
, to maintain stealth and manipulate registry keys and files without raising suspicion. - The malware uses the
RtlUserThreadStart
function to initialize the injected processes, load the required Windows DLLs, and send a DNS query to resolve the domain names of various hardcoded malicious addresses. Once the communication to the first domain is resolved, the information is encrypted usingTLS v1.2
. - In the final stage, the malware sends messages and receives obfuscated responses from the C2 server. It then begins collecting and exfiltrating sensitive data from the victim’s endpoint, encrypting it, and using custom obfuscation to conceal the stolen data during transmission.
- The malware scans the compromised system for files with keywords like
seed.txt
,wallet.txt
, and*.pdf
to target and collect sensitive information such as private keys, wallet addresses, and login credentials.
Analyzed file
Below is the indicator of compromise (IoC) for the specific Lumma Stealer variant analyzed in this blog post.
Hash type | Value |
MD5 | cf9a2518d062283a422f243273f7094f |
SHA256 | b9c71471d52e93c38eeb069082dcdea935f928024b6db3fce153c63d4af1b27c |
Infrastructure
We use the following infrastructure to demonstrate the detection of Lumma Stealer with Wazuh.
- A pre-built, ready-to-use Wazuh OVA 4.9.1 Follow this guide to download the virtual machine.
- A Windows 10 endpoint with Wazuh agent 4.9.1 installed. We call this the victim endpoint. Refer to the following installation guide to install the Wazuh agent.
Wazuh detection
We use the following methods to detect the Lumma Stealer activities on a monitored Windows endpoint:
- We use Sysmon to monitor system events and create rules on the Wazuh server to detect the behavior of Lumma Stealer on the victim endpoint.
- Perform file signature scanning using VirusTotal integration with Wazuh.
- Remove malicious files using the Wazuh Active Response module.
Configuration
Perform the following steps to configure Sysmon on the victim endpoint and forward logs in the Sysmon event channel to the Wazuh server for analysis.
Victim endpoint
1. Download Sysmon from the Microsoft Sysinternals page.
2. Extract the compressed Sysmon file to your preferred location.
3. Download the sysmonconfig.xml file using PowerShell. Replace <SYSMON_EXECUTABLE_PATH>
with the path to your Sysmon executable:
> wget -Uri https://wazuh.com/resources/blog/emulation-of-attack-techniques-and-detection-with-wazuh/sysmonconfig.xml -OutFile <SYSMON_EXECUTABLE_PATH>\sysmonconfig.xml
4. Using PowerShell with Administrator privileges, switch to the directory where the Sysmon executable is located. Then run the command below to install and start Sysmon:
> .\Sysmon64.exe -accepteula -i sysmonconfig.xml
5. Add the following configuration within the <ossec_config>
block of the configuration file of the Wazuh agent located at C:\Program Files (x86)\ossec-agent\ossec.conf
to forward Sysmon events to the Wazuh server:
<localfile> <location>Microsoft-Windows-Sysmon/Operational</location> <log_format>eventchannel</log_format> </localfile>
6. Restart the Wazuh agent to apply the configuration changes:
> Restart-Service -Name wazuh
Wazuh server
In this section, we develop rules to detect Lumma Stealer behavior on the victim endpoint.
1. Create a new rule file for detecting Lumma Stealer:
# touch /var/ossec/etc/rules/LummaC2.xml
2. Add the rules below to the /var/ossec/etc/rules/LummaC2.xml
file:
<group name="Lumma, LummaC2, malware,"> <!-- Lumma execution --> <rule id="100501" level="12"> <if_sid>61603</if_sid> <field name="win.eventdata.Image" type="pcre2">\.exe</field> <field name="win.eventdata.OriginalFileName" type="pcre2">GlobalCheats\.exe</field> <description>Suspicious process creation by Lumma Stealer.</description> <mitre> <id>T1204</id> </mitre> </rule> <!-- Credential dumping --> <rule id="100502" level="12"> <if_sid>61614</if_sid> <field name="win.eventdata.TargetObject" type="pcre2">HKLM\\System\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL</field> <field name="win.eventdata.Image" type="pcre2">BitLockerToGo\.exe</field> <description>Suspicious registry modification.</description> <mitre> <id>T1003</id> </mitre> </rule> <rule id="100503" level="12"> <if_sid>61609</if_sid> <field name="win.eventdata.Image" type="pcre2">(?i)[c-z]:\\Windows\\BitLockerDiscoveryVolumeContents\\BitLockerToGo\.exe</field> <field name="win.eventdata.ImageLoaded" type="pcre2">(?i)[c-z]:\\Windows\\SysWOW64\\amsi\.dll</field> <description>Suspicious DLL loading by BitLockerToGo.exe.</description> <mitre> <id>T1059.001</id> </mitre> </rule> <!-- DLL process injection --> <rule id="100504" level="12"> <if_sid>61609</if_sid> <field name="win.eventdata.Image" type="pcre2">.*\.exe</field> <field name="win.eventdata.ImageLoaded" type="pcre2">(?i)[c-z]:\\Windows\\assembly\\NativeImages_v4\.0\.30319_64\\mscorlib\\.*\\mscorlib\.ni\.dll</field> <description>PowerShell process loaded mscorlib.ni.dll, possibly indicating process injection.</description> <mitre> <id>T1055</id> </mitre> </rule> <rule id="100505" level="12"> <if_sid>61609</if_sid> <field name="win.eventdata.Image" type="pcre2">.*\.exe</field> <field name="win.eventdata.ImageLoaded" type="pcre2">(?i)[c-z]:\\Windows\\Microsoft\.NET\\Framework64\\v4\.0\.30319\\clrjit\.dll</field> <description>PowerShell process loaded clrjit.dll, indicating potential process injection.</description> <mitre> <id>T1055.001</id> </mitre> </rule> </group>
Where:
- Rule ID
100501
is triggered when Lumma Stealer creates a suspicious processGlobalCheats.exe
on the Victim endpoint. - Rule ID
100502
is triggered when Lumma Stealer creates a Registry key on the Victim endpoint. - Rule ID
100503
is triggered when Lumma Stealer terminates its original processGlobalCheats.exe
, and starts another process,BitLockerToGo.exe
, to modify the endpoint registry. - Rule ID
100504
is triggered when Lumma Stealer injectsmscorlib.ni.dll
intoC:\Windows\assembly\NativeImages_v4.0.30319_64\mscorlib
. - Rule ID
100505
is triggered when Lumma Stealer injectsclrjit.dll
intoC:\Windows\Microsoft.NET\Framework64\v4.0.30319
.
3. Restart the Wazuh manager for the changes to take effect:
# systemctl restart wazuh-manager
Detection results
The screenshot below shows the alerts generated on the Wazuh dashboard when Lumma Stealer is executed on the Victim endpoint. Perform the following steps to view the alerts on the Wazuh dashboard.
1. Navigate to the Threat Hunting section.
2. Click on Explore agent and select the monitored endpoint.
3. Click + Add filter. Then, filter for rule.id in the Field section.
4. Select filter is one of in the Operator field.
5. Filter for 100501
, 100502
, 100503
, 100504
, and 100505
in the Values field.
6. Click Save.
VirusTotal integration
VirusTotal aggregates antivirus products and online scan engines, providing an API that can be queried with URLs, IP addresses, domains, or file hashes to identify security threats. You can configure Wazuh to automatically send requests to the VirusTotal API with the hashes of files created or modified on the victim endpoint.
For this integration, we configure the Wazuh File Integrity Monitoring module and VirusTotal to detect and scan files that are added or modified on specific directories on the Victim endpoint. Additionally, we configured the Wazuh Active Response module to remove the files identified as malicious by VirusTotal.
Victim endpoint
1. Add the following configuration within the <ossec_config>
block in the C:\Program Files (x86)\ossec-agent\ossec.conf
file to monitor for changes. In this blog post, we configure the FIM module to monitor the Downloads
folder for all users.
<syscheck> <directories check_all="yes" realtime="yes">C:\Users\*\Downloads</directories> </syscheck>
2. Restart the Wazuh agent to apply the changes by running the following PowerShell command as an administrator:
> Restart-Service -Name wazuh
Active response Python script configuration
We create an active response script to remove any known variant of Lumma Stealer immediately after VirusTotal identifies it as a threat.
1. Create an active response script remove-threat.py
on the Victim endpoint with the following content:
#!/usr/bin/python3 # Copyright (C) 2015-2022, Wazuh Inc. # All rights reserved. import os import sys import json import datetime if os.name == 'nt': LOG_FILE = "C:\Program Files (x86)\ossec-agent\active-response\active-responses.log" else: LOG_FILE = "/var/ossec/logs/active-responses.log" ADD_COMMAND = 0 DELETE_COMMAND = 1 CONTINUE_COMMAND = 2 ABORT_COMMAND = 3 OS_SUCCESS = 0 OS_INVALID = -1 class message: def __init__(self): self.alert = "" self.command = 0 def write_debug_file(ar_name, msg): with open(LOG_FILE, mode="a") as log_file: log_file.write(str(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')) + " " + ar_name + ": " + msg +"\n") def setup_and_check_message(argv): # get alert from stdin input_str = "" for line in sys.stdin: input_str = line break try: data = json.loads(input_str) except ValueError: write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format') message.command = OS_INVALID return message message.alert = data command = data.get("command") if command == "add": message.command = ADD_COMMAND elif command == "delete": message.command = DELETE_COMMAND else: message.command = OS_INVALID write_debug_file(argv[0], 'Not valid command: ' + command) return message def send_keys_and_check_message(argv, keys): # build and send message with keys keys_msg = json.dumps({"version": 1,"origin":{"name": argv[0],"module":"active-response"},"command":"check_keys","parameters":{"keys":keys}}) write_debug_file(argv[0], keys_msg) print(keys_msg) sys.stdout.flush() # read the response of previous message input_str = "" while True: line = sys.stdin.readline() if line: input_str = line break # write_debug_file(argv[0], input_str) try: data = json.loads(input_str) except ValueError: write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format') return message action = data.get("command") if "continue" == action: ret = CONTINUE_COMMAND elif "abort" == action: ret = ABORT_COMMAND else: ret = OS_INVALID write_debug_file(argv[0], "Invalid value of 'command'") return ret def main(argv): write_debug_file(argv[0], "Started") # validate json and get command msg = setup_and_check_message(argv) if msg.command < 0: sys.exit(OS_INVALID) if msg.command == ADD_COMMAND: alert = msg.alert["parameters"]["alert"] keys = [alert["rule"]["id"]] action = send_keys_and_check_message(argv, keys) # if necessary, abort execution if action != CONTINUE_COMMAND: if action == ABORT_COMMAND: write_debug_file(argv[0], "Aborted") sys.exit(OS_SUCCESS) else: write_debug_file(argv[0], "Invalid command") sys.exit(OS_INVALID) try: os.remove(msg.alert["parameters"]["alert"]["data"]["virustotal"]["source"]["file"]) write_debug_file(argv[0], json.dumps(msg.alert) + " Successfully removed threat") except OSError as error: write_debug_file(argv[0], json.dumps(msg.alert) + "Error removing threat") else: write_debug_file(argv[0], "Invalid command") write_debug_file(argv[0], "Ended") sys.exit(OS_SUCCESS) if __name__ == "__main__": main(sys.argv)
The os.remove()
function in the active response Python script handles the removal of the malicious file:
os.remove(msg.alert["parameters"]["alert"]["data"]["virustotal"]["source"]["file"])
2. Download Python and run the installer. This works with Python 3.8.7 or later (with pip pre-installed). Then, select the following checkboxes during installation:
- Add Python.exe to PATH.
- Use admin privileges when installing py.exe.
Note: This step is optional if Python is installed on the victim endpoint.
3. Run the following command with administrative privilege to install Pyinstaller
using PowerShell:
> pip install -U pyinstaller
4. Change to the directory where the Python script remove-threat.py
is located and convert the file to an executable file with the following command:
> pyinstaller -F remove-threat.py
5. Move the executable file remove-threat.exe
from the \dist
folder under your current working directory to the C:\Program Files (x86)\ossec-agent\active-response\bin
folder.
6. Restart the agent to apply the changes by running the following PowerShell command as an administrator:
> Restart-Service -Name wazuh
Wazuh server
1. Append the configuration below to the /var/ossec/etc/ossec.conf
file to scan the files with VirusTotal:
<ossec_config> <integration> <name>virustotal</name> <api_key><API_KEY></api_key> <!-- Replace with your VirusTotal API key --> <rule_id>554,550</rule_id> <alert_format>json</alert_format> </integration> </ossec_config>
Replace the <API_KEY>
variable with your VirusTotal API key. The FIM rule IDs 554
and 550
detect file addition and modification events, respectively.
Active response configuration
1. Append the following configuration to the /var/ossec/etc/ossec.conf
file:
<ossec_config> <command> <name>remove-threat</name> <executable>remove-threat.exe</executable> <timeout_allowed>no</timeout_allowed> </command> <active-response> <disabled>no</disabled> <command>remove-threat</command> <location>local</location> <rules_id>87105</rules_id> </active-response> </ossec_config>
2. Add the following rules to the /var/ossec/etc/rules/LummaC2.xml
file to generate alerts when the Wazuh Active Response module successfully removes the malicious files.
<group name="virustotal,"> <rule id="100601" level="12"> <if_sid>657</if_sid> <match>Successfully removed threat</match> <description>$(parameters.program) removed threat located at $(parameters.alert.data.virustotal.source.file)</description> </rule> <rule id="100602" level="12"> <if_sid>657</if_sid> <match>Error removing threat</match> <description>Error removing threat located at $(parameters.alert.data.virustotal.source.file)</description> </rule> </group>
Where:
- Rule ID
100601
generates an alert when the Wazuh Active Response module successfully removes the Lumma Stealer. - Rule ID
100602
generates an alert when the Wazuh Active Response module fails to remove the Lumma Stealer.
3. Restart the Wazuh manager to apply configuration changes:
# sudo systemctl restart wazuh-manager
Visualize results
When a variant of Lumma Stealer is downloaded to the victim’s Downloads
folder, Wazuh generates alerts and promptly initiates an active response to remove the malicious file. The screenshot below shows that the Wazuh FIM module detects the file addition, which VirusTotal confirms as malicious, triggering Wazuh to take an automated response. Follow these steps to view these alerts:
1. Navigate to the Threat Hunting section.
2. Click on Explore agent and select the monitored endpoint.
3. Click + Add filter. Then, filter for rule.id in the Field section.
4. Select filter is one of in the Operator field.
5. Filter for 100601
, 553
, 550
, and 87105
in the Values field.
6. Click Save.
You can further expand the active response alert to inspect the alert’s details.
Conclusion
Lumma Stealer is a malware designed to exfiltrate sensitive data, posing a significant risk to infected systems. Detecting and responding to such threats requires a comprehensive security platform. Wazuh, a free and open source SIEM/XDR platform, provides the visibility and detection capabilities necessary to safeguard your endpoints from such emerging threats.
In this blog post, we demonstrated how integrating Sysmon with Wazuh can effectively detect the behavior of Lumma Stealer. Additionally, we utilized the Wazuh FIM and VirusTotal integration to identify the malware upon its download to an endpoint. We leveraged the Wazuh Active Response module to show how malicious files can be swiftly removed, neutralizing the threat before it causes damage.
To learn more about Wazuh capabilities, check out our documentation, blog posts, and community for support and updates.