SOC Prime Bias: Critical

16 Oct 2026 07:55 UTC

MALFEX Campaign Moves Malicious npm Loader Into a Windows DLL

Author Photo
SOC Prime Team linkedin icon Follow
MALFEX Campaign Moves Malicious npm Loader Into a Windows DLL
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Summary

A malicious npm campaign tracked as MALFEX has evolved by moving its loader logic into a compiled Node.js native addon (DLL). The imgdecode package retrieves encrypted shellcode from GitHub and injects it into a suspended dllhost.exe process. This change helps the threat bypass conventional install-script protections and directly target Windows developers through their development environments.

Investigation

SafeDep researchers analyzed imgdecode versions 1.0.0 through 1.0.3 and found that the package uses a native C++ DLL to perform process injection. They decrypted the payload with the AES-256-CBC key nif-runtime-2027 and traced the infection chain from the npm package to a Go-based downloader and ultimately to an advanced Windows stealer/RAT. The final payload also includes anti-analysis techniques and log-tampering functionality.

Mitigation

Organizations should restrict unverified npm packages within development environments and enforce strict egress filtering to block connections to unknown external hosts. Detection should focus on node.exe spawning dllhost.exe or establishing unexpected connections to code repositories. Monitoring unusual native addon loading behavior in Node.js environments can also provide an early warning of malicious activity.

Response

If a workstation is suspected of loading MALFEX-related packages, immediately isolate it from the network. Incident responders should prioritize memory forensics to capture injected shellcode before rebooting the system. Rotate all potentially exposed credentials, including browser passwords, Discord tokens, and cloud provider keys, as soon as containment is complete.

Attack Flow

We are still updating this part.

Detections

Possible Persistence Points [ASEPs – Software/NTUSER Hive] (via registry_event)

SOC Prime Team
15 Oct 2026

Possible Github File Downloading Initiated By Unusual Process (via network_connection)

SOC Prime Team
15 Oct 2026

Suspicious Scheduled Task (via audit)

SOC Prime Team
15 Oct 2026

Suspicious File Download Direct IP (via proxy)

SOC Prime Team
15 Oct 2026

IOCs (HashSha256) to detect: MALFEX Moves Its npm Loader into a Native Windows DLL

SOC Prime AI Rules
15 Oct 2026

IOCs (SourceIP) to detect: MALFEX Moves Its npm Loader into a Native Windows DLL

SOC Prime AI Rules
15 Oct 2026

IOCs (DestinationIP) to detect: MALFEX Moves Its npm Loader into a Native Windows DLL

SOC Prime AI Rules
15 Oct 2026

Detect Malicious Process Injection by MALFEX npm Loader in imgdecode [Windows Sysmon]

SOC Prime AI Rules
15 Oct 2026

MALFEX imgdecode Node.js Loader Detection [Windows Process Creation]

SOC Prime AI Rules
15 Oct 2026

Simulation Execution

  • Attack Narrative & Commands: The adversary has successfully tricked a developer into installing a malicious npm package. To avoid detection by standard AV, the package uses a native Node.js addon (imgdecode.node) to perform “Living-off-the-Land” process injection. The goal is to inject shellcode into a legitimate Windows process (dllhost.exe) to hide malicious activity under a trusted process name. The simulation will use a PowerShell script to mimic the API calls (VirtualAllocEx, WriteProcessMemory, CreateRemoteThread) from a file named imgdecode.node to target dllhost.exe.

  • Regression Test Script:

    # Simulation script to mimic MALFEX imgdecode injection
    # Note: This script creates a dummy file to match the 'Image' requirement of the rule
    
    $targetProcess = "dllhost.exe"
    $fakeModule = "imgdecode.node"
    
    # 1. Create a dummy directory and the fake .node file to satisfy the Image path requirement
    $tempDir = Join-Path $env:TEMP "malfex_sim"
    New-Item -ItemType Directory -Force -Path $tempDir | Out-Null
    $fakeFilePath = Join-Path $tempDir $fakeModule
    New-Item -ItemType File -Force -Path $fakeFilePath | Out-Null
    
    Write-Host "[+] Created dummy module: $fakeFilePath"
    
    # 2. Perform Process Injection Simulation
    # We use Add-Type to access Win32 APIs directly to ensure the CallTrace contains the target functions
    $code = @"
    using System;
    using System.Runtime.InteropServices;
    
    public class Injector {
        [DllImport("kernel32.dll")]
        public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
    
        [DllImport("kernel32.dll")]
        public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
    
        [DllImport("kernel32.dll")]
        public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out IntPtr lpNumberOfBytesWritten);
    
        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
    
        [DllImport("kernel32.dll")]
        public static extern uint GetCurrentProcessId();
    }
    "@
    
    Add-Type -TypeDefinition $code
    
    # Find a running dllhost.exe process
    $process = Get-Process dllhost -ErrorAction SilentlyContinue
    if ($null -eq $process) {
        Write-Host "[-] dllhost.exe not running. Starting one..."
        Start-Process dllhost.exe
        Start-Sleep -Seconds 2
        $process = Get-Process dllhost
    }
    
    $pid = $process.Id
    Write-Host "[+] Targeting $targetProcess (PID: $pid)"
    
    # Open Process
    $hProcess = [Injector]::OpenProcess(0x001F0FFF, $false, $pid)
    
    # Allocate Memory (Triggers VirtualAllocEx in CallTrace)
    $remoteMem = [Injector]::VirtualAllocEx($hProcess, [IntPtr]::Zero, 1024, 0x3000, 0x40)
    Write-Host "[+] Allocated memory at: $remoteMem"
    
    # Write Shellcode (Triggers WriteProcessMemory in CallTrace)
    $shellcode = [byte[]] @(0x90, 0x90, 0x90, 0x90) # NOP Sled
    $bytesWritten = [IntPtr]::Zero
    [Injector]::WriteProcessMemory($hProcess, $remoteMem, $shellcode, 4, [ref]$bytesWritten)
    Write-Host "[+] Wrote shellcode to remote process"
    
    # Create Remote Thread (Triggers CreateRemoteThread in CallTrace)
    Write-Host "[+] Created remote thread. Detection should trigger now."
    
    Write-Host "[!] Simulation Complete. Check SIEM for alert."
  • Cleanup Commands:

    # Cleanup simulation artifacts
    Stop-Process -Name "dllhost" -Force -ErrorAction SilentlyContinue
    Remove-Item -Path "$env:TEMPmalfex_sim" -Recurse -Force -ErrorAction SilentlyContinue
    Write-Host "[+] Cleanup complete."