Finding Malware: Unveiling NUMOZYLOD with Google Security Operations

codyli
Staff

Welcome to the Finding Malware Series

The "Finding Malware," blog series is authored to empower the Google Security Operations community to detect emerging and persistent malware threats. This post dives deep into the NUMOZYLOD malware family and the detection opportunities available within the Google Security Operations (SecOps) platform. You can read the other installments to the series here. Happy hunting! 

About NUMOZYLOD

Also known as: FakeBat, EugenLoader, PaykLoader

Since mid-2023, Mandiant Managed Defense has responded to a surge in malware infections originating from malvertising campaigns. These attacks are opportunistic in nature, targeting users seeking popular business software. The infection utilizes a trojanized MSIX installer, which executes a PowerShell script to download a secondary payload.

Mandiant tracks this PowerShell script as NUMOZYLOD and attributes its distribution to UNC4536, a threat actor operating under the moniker "eugenfest." The actor is part of a Malware-as-a-Service (MaaS) operation, distributing malware such as ICEDID, REDLINESTEALER, CARBANAK, LUMMASTEALER, or ARECHCLIENT2.

Our research into NUMOZYLOD reveals an interesting glimpse into the growing and thriving underground economy, where threat actors actively seek out partners to fulfill the supply and demand for specialized tools and services for their objectives. It also highlights how threat actors are exploiting MSIX to covertly bundle and distribute malware alongside legitimate software.

Malware Lifecycle

image.png
Figure 1: NUMOZYLOD Attack Lifecycle

Initial Compromise

UNC4536's modus operandi involves leveraging malvertising to distribute trojanized MSIX installers disguised as popular software like Brave, KeePass, Notion, Steam, and Zoom. These trojanized MSIX installers are hosted on websites designed to mimic legitimate software hosting sites, luring users into downloading them.

A key feature of MSIX is its ability to execute scripts with the help of the Package Support Framework (PSF). Installers can instruct the PSF to run a script before the main application starts by adding a configuration item called startScript. Similarly, to run a script after the application finishes, add a configuration item called endScript.

Threat actors have exploited this feature bundling a malicious payload, such as NUMOZYLOD, within the MSIX package, which will be executed during the software installation process.

Trojanized MSIX File Structure Review

Analyzing the structure of the NUMOZYLOD trojanized MSIX files structure provides interesting insights into how threat attackers stage their resources and abuse MSIX features to gain initial access and evade detection.

figure2.pngFigure 2: MSIX File Structure embedded with a malicious PowerShell script, NUMOZYLOD.

Here's a breakdown of its key MSIX components.

1. AppxManifest.xml
This xml file is the heart of the MSIX installer. It specifies how the package is to be installed. Interesting information includes, but is not limited to: 

  • Language: The Resources section lists the languages supported by the application. The languages listed could offer insight into the malware author's origin or the intended target audience for the malware's distribution.

image.pngFigure 3: Package language resource

  • Capabilities: The application's manifest file should list any restricted capabilities. Malicious actors often exploit the 'runFullTrust' setting to bypass the isolation and security controls offered by app containers.

figure4.pngFigure 4: Package capabilities

  • EntryPoint, Executable: The 'Windows.FullTrustApplication' setting under the Application EntryPoint attribute enables an application to run with full trust, granting it elevated privileges and access to system resources. Meanwhile, the Executable attribute specifies the initial executable launched upon installation, which in this case is AiStubX86.exe, and the application ID is used to locate the app's launch setting within the config.json file.

figure5.pngFigure 5: Package EntryPoint, Executable and ID

  • Built: Trojanized MSIX are often found to be built with Advanced Installer as indicated under the build metadata.

figure6.pngFigure 6: Package build

2. Config.json
config.json is a configuration file used by the PSF to handle things that standard MSIX installations cannot directly support, such as launching specific processes alongside the main application. In essence, the config.json file instructs the MSIX installer to trigger the execution of the malicious PowerShell script during the installation of the software.

figure7.pngFigure 7: The config.json shows the trojanized MSIX is designed to execute a PowerShell script named "Refresh2.ps1" (NUMOZYLOD)
and launch "Trello"

3. StartingScriptWrapper.ps1
The StartingScriptWrapper.ps1 file is an essential component of the PSF that serves as a wrapper for executing PowerShell scripts specified in the config.json file.

figure8.pngFigure 8: The wrapper was observed to execute the malicious PowerShell script "Refresh2.ps1" (NUMOZYLOD) specified in the config.json

4. Virtual File System (VFS) folder
The VFS folder is a virtual storage space within an MSIX package. It holds the application's files and folders, separating them from the main system. This isolation protects both the application and the system. 

Mandiant observed that in some variants, files within the VFS folder (such as gpg.exe and iconv.dll) were written to locations like AppData\Local. These files may be intended for a later stage of a multi-stage malware attack, as we observed the use of gpg.exe to decrypt the downloaded encrypted payload.

Once the trojanized installer package is prepared, the threat actor will distribute it through malvertising, waiting for a victim to download and execute it. 

image.png
Figure 9: Trello users are being targeted by malvertising attacks that redirect them to a fake website at trello.confesapp[.]com.

This installation action will initiate the download of a secondary payload and any additional packages hidden within the MSIX installer. The below illustration demonstrates the triggering of the PowerShell payload during the execution of the malicious installer.

figure10.gif
Figure 10: A PowerShell payload (NUMOZYLOD) was executed discreetly in the background during the installation of the legitimate software.

Established Foothold

UNC4536 operates as a malware distributor, leveraging NUMOZYLOD as one of its vehicles to deliver tailored payloads for their “business partners.” Managed Defense has observed a range of secondary payloads, to be executed through various techniques.

In the following section we will review two NUMOZYLOD variants and their previous delivery of the CARBANAK and LUMMASTEALER payloads.

Variant 1: NUMOZYLOD distributing CARBANAK 

In 2023, Managed Defense observed a campaign utilizing UNC4536's distribution network to spread the CARBANAK backdoor. This campaign exploited SEO poisoning tactics, directing unsuspecting victims to a malicious website that mimicked the legitimate KeePass open-source password manager. The observed trojanized installers contained a NUMOZYLOD downloader that was configured to retrieve CARBANAK backdoor.

The following code snippet is from the NUMOZYLOD malware variant. Upon infecting a system, this variant will transmit host information and then download and execute the CARBANAK malware via DLL Search Order Hijacking.

image.pngFigure 11: A code snippet of this NUMOZYLOD variant that leads to CARBANAK .

Execution of this NUMOZYLOD variant would perform the following:

  • Run WMI to gather host information including a list of installed antivirus software on the system. This information is then sent to its C2 via HTTP GET Request.
  • Download the secondary malicious payload encrypted with GPG from 4Sync, a file-sharing and storage service.
  • In this example, it will decrypt and extract the contents to execute a legitimate WireShark binary (mergecap.exe) to load a malicious DLL payload (in this case, CARBANAK) through DLL search order hijacking.
  • Lastly, it sends an HTTP request to its C2 to notify the host that it is infected. 

Variant 2: NUMOZYLOD distributing LUMMASTEALER 

image.pngFigure 12: An obfuscation NUMOZYLOD variant

In another campaign, Managed Defense observed a heavily obfuscated NUMOZYLOD sample utilized to deliver the LUMMASTEALER payload. Its use of numerous curly brackets makes analysis difficult. However, here are two effective methods to dynamically analyze the content of this obfuscated PowerShell script.

1. Analyzing Obfuscated PowerShell Script - PowerShell Script Block Logging

Turn on PowerShell Script Block Logging - Once Script Block Logging is enabled, PowerShell will log details about PowerShell operations, and the executed PowerShell commands. Using the Windows Event Viewer, a user can filter for eventID 4104 and review the deobfuscated PowerShell script.

The following screenshots illustrate how the NUMOZYLOD variant utilizes several obfuscation techniques to impede analysis and evade security measures.

image.pngFigure 13: Multiple layers of obfuscation to hinder analysis and evade detection

Show More
Community-Tip: If your Google Security Operations setup includes collecting Microsoft Windows Event data, simply search for Event ID 4104. This allows you to easily review all PowerShell commands directly in the console! no muss, no fuss!

2. Analyzing Obfuscated PowerShell Script - Reviewing AMSI events 

Generating and analyzing Antimalware Scan Interface (AMSI) events - Alternatively, you can conduct dynamic analysis with the help from AMSI events. This method not only enables users to review the deobfuscated PowerShell script, but also reveals whether AMSI successfully blocked the malicious content.

The following screenshots show the same NUMOZYLOD variant after deobfuscation using the AMSI event generation and analysis method.

image.pngFigure 14: Analyzing AMSI events

Essentially, this obfuscated NUMOZYLOD variant downloads and executes a secondary PowerShell payload from a C2 server. The following screenshot illustrates this second-stage payload.

figure15.pngFigure 15: Multiple layers of obfuscation to hinder analysis and evade detection

Execution of this NUMOZYLOD variant would perform the following:

  • First, the malware downloads and executes a script from GitHub. This script uses hardware breakpoints to disable AMSI (the Antimalware Scan Interface), a core Windows security feature. Disabling AMSI allows the malware to run undetected by security software.
  • Second, it sets its target to the website telegra[.]ph and downloads the contents of the web page.
  • Next, it searches the downloaded web page for any links ending in .dat (a common file extension for data files).
  • Finally, it downloads the contents of each .dat file and executes the malicious code directly in memory.

In this NUMOZYLOD variant, the downloaded payload is identified as LUMMASTEALER, a known infostealer malware.

Host Reconnaissance

NUMOZYLOD gathers system information, including operating system details, domain joined, and antivirus products installed. In some variants, it gathers the public IPv4 and IPv6 address of the host and sends this information to its C2.

Maintain Presence

In some variants, NUMOZYLOD creates a shortcut(.lnk) in the StartUp folder as its persistence.

Complete Mission

As a part of a Malware-as-a-Service (MaaS) operation, NUMOZYLOD completes its mission upon the successful deployment of the second-stage malware from its C2 server and hands it over to its buyer for the subsequent mission.

Hunting Opportunities

Mandiant Hunt surfaces otherwise undetected malicious activity by employing a detection strategy that uses both strong signals - high enough fidelity to be reviewed 1:1, and weak signals - low fidelity on their own, but provide broad coverage of threat actor tactics. These signals or combinations thereof are used to sequentially funnel the gargantuan amount of customer telemetry data to a number of cases worthy of analyst review. Mandiant uses security frameworks like MITRE ATT&CK® to help label data, (discussed further below) find interesting sequences of activity, and share actionable results with customers

The NUMOZYLOD attack chain presents several opportunities for engineering strong detections. Examples of detections used by Mandiant Hunt within Google Security Operations include:

  • Initial Compromise: MSIX file distribution - Mandiant threat hunters review events surrounding MSIX files written to disk by unexpected or uncommon processes, or sourced from suspicious or untrusted sites. Such events map to MITRE ATT&CK® Technique T1204.002 - User Execution: Malicious File. 

    Use the UDM query below in Google Security Operations to identify MSIX filewrites, which can be explored using the Pivot functionality on fields like principal.process.file.full_path.
    metadata.event_type = "FILE_CREATION" OR metadata.event_type = "FILE_MODIFICATION" AND target.file.full_path = /\.msix$/ nocase

     

  • Initial Compromise: "StartingScriptWrapper.ps1" - While the file itself is legitimate, Mandiant has observed its use in malicious activity. Mandiant threat hunters review events related to its writing on a host to determine if the overall activity was benign or malicious. These events map to MITRE ATT&CK® Technique T1204.002 - User Execution: Malicious File. 

    Google Security Operations users can find instances of this file written to disk with the following UDM query:
    metadata.event_type = "FILE_CREATION" OR metadata.event_type = "FILE_MODIFICATION" AND target.file.full_path = /startingscriptwrapper\.ps1$/ nocase​

     

  • Initial Compromise: Virtual File System (VFS) folder - Uncommon events like writing of the GnuPG binary gpg.exe or uncommon processes launching copy.exe or xcopy.exe were observed in compromises by malware such as NUMOZYLOD. These events map to MITRE ATT&CK® Technique T1105 - Ingress Tool Transfer. 

    For this example, the following UDM query can provide a starting point:
    (target.file.full_path = /gpg\.exe$/ nocase AND (principal.process.file.full_path = /copy\.exe$/ nocase OR principal.process.file.full_path = /xcopy\.exe$/ nocase)) AND target.file.full_path != /cygwin/ nocase AND target.file.full_path != /git\\usr\\bin/ nocase​

     

  • Establish Foothold: PowerShell - Throughout the evolution of NUMOZYLOD variants, Mandiant maintained visibility with a multitude of detection logic mapped to MITRE ATT&CK® Technique T1059.001 - Command and Scripting Interpreter: PowerShell. Suspicious arguments, execution of scripts in unexpected locations, and PowerShell activity with unexpected execution policies all present opportunities for detection logic to help amplify malicious signals.

Mandiant threat hunters use various signals captured in Google Security Operations to identify later stages of compromise all the way through threat actor mission completion, if attackers progress to that point. 

Detection Through Google Security Operations

Enterprise and Enterprise Plus customers will benefit from these detections being applied automatically through curated detections. Standard customers can use the YARA-L rules below to create single or multi-event rules to detect the malware. You can even ask Gemini in Google Security Operations to do it for you. 

  • This rule detects when StartingScriptWrapper.ps1 is executed with Advanced Installer.  
    rule POWERSHELL_EXECUTE_SCRIPTWRAPPER_FROM_WINDOWSAPPS_VIA_REMOTESIGNED_EXECUTION_POLICY {
        meta:
            author = "Mandiant"
            description = "This rule detects when startingscriptwrapper.ps1 is executed with Advanced Installer. The process is executed with MSIX files as package support framework and may point to an additional malicious powershell script within the ps1." 
            mitre_attack_tactic = "Execution"
            mitre_attack_technique = "Command and Scripting Interpreter"
            mitre_attack_url = "https://attack.mitre.org/techniques/T1059/001/"
            mitre_attack_version = "v14.1"
            severity = "High"
            priority = "High"
            platform = "Windows"
            type = "hunt"
    
        events:
            (
                $e.metadata.event_type = "PROCESS_LAUNCH"
            ) and
            (
                re.regex($e.target.process.command_line, `StartingScriptWrapper.ps1`) nocase and
                re.regex($e.target.process.file.full_path, `powershell`) nocase and
                re.regex($e.target.process.command_line, `RemoteSigned\s\-file.*\\WindowsApps\\.*Powershell(.exe).*RemoteSigned\s\-file.*\.ps1`) nocase 
            ) and
            (
                re.regex($e.principal.process.file.full_path, `\\ai_stubs\\`) nocase or
                re.regex($e.principal.process.command_line, `\\ai_stubs\\`) nocase
            )
    
        condition:
            $e
    }

     

  • This rule detects file creation of gpg.exe at the path %localappdata%.
    rule XCOPY_WRITING_GNUPG_PROCESS_METHODOLOGY {
       meta:
           author = "Mandiant"
           description = "This rule is designed to detect on gpg.exe (GnuPG) being copied to the path %localappdata%. This technique has been previously observed in NUMOZYLOD compromises."
           mitre_attack_tactic = "Command And Control"
           mitre_attack_technique = "Ingress Tool Transfer"
           mitre_attack_url = "https://attack.mitre.org/techniques/T1105/"
           severity = "Low"
           platform = "Windows"
           type = "hunt"
           
       events:
           (
               $e.metadata.event_type = "FILE_CREATION" or
               $e.metadata.event_type = "FILE_MODIFICATION"
           ) and
           (
               re.regex($e.target.file.full_path, `gpg\.exe$`) nocase and
               re.regex($e.target.file.full_path, `\\appdata\\local`) nocase and
               not re.regex($e.target.file.full_path, `\\localsum\\cygwin\\bin`) nocase and
               not re.regex($e.target.file.full_path, `temp\\rest\\bin`) nocase and
               not re.regex($e.target.file.full_path, `Git\\usr\\bin`) nocase and
               (
                   re.regex($e.principal.process.file.full_path, `xcopy\.exe$`) nocase or
                   re.regex($e.principal.process.file.full_path, `copy\.exe$`) nocase
               )
           )
    
       condition:
           $e
    }

     

Have questions or feedback for the Managed Defense team? Comment on the blog or ask a question in the Managed Defense Forum

OSZAR »