SOC Prime Bias: Médio

08 Mai 2026 18:33

NWHStealer Disseminado Através do Tempo de Execução Bun JavaScript

Author Photo
SOC Prime Team linkedin icon Seguir
NWHStealer Disseminado Através do Tempo de Execução Bun JavaScript
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Resumo

O artigo explica como atores de ameaça estão usando o runtime JavaScript Bun para entregar o infostealer NWHStealer baseado em Rust. Arquivos ZIP maliciosos contêm um instalador primário que lança um carregador JavaScript empacotado com Bun junto com um carregador secundário chamado dw.exe. O componente JavaScript executa verificações anti-máquina virtual, entra em contato com a infraestrutura de comando e controle, descriptografa uma carga adicional e abusa das APIs nativas do Windows para injetar o stealer na memória. Para reduzir a suspeita, a campanha esconde arquivos maliciosos atrás de plataformas de hospedagem legítimas como o GitHub, MediaFire e SourceForge.

Investigação

Pesquisadores descobriram que o Bun foi usado para empacotar JavaScript malicioso dentro da seção .bun do carregador. Dois scripts, sysreq.js and memload.js, cuidavam das verificações de ambiente e da comunicação com a infraestrutura do atacante. O carregador recuperou dados de configuração e cargas criptografadas de domínios como silent-harvester.cc, os descriptografou com AES-256-CBC e os injetou através de chamadas de API Win32. A carga final era o NWHStealer, que rouba credenciais, dados de navegador e informações de carteiras de criptomoeda, podendo também iniciar atividades adicionais de mineração.

Mitigação

Usuários devem evitar baixar executáveis de sites não confiáveis e verificar assinaturas de instaladores antes da execução. Equipes de segurança devem monitorar atividades incomuns do runtime Bun, consultas PowerShell CIM usadas para verificações de virtualização e chamadas de API suspeitas como VirtualAlloc and LoadLibraryA. As organizações também devem bloquear os domínios maliciosos conhecidos e aplicar políticas de execução com o menor privilégio para limitar abusos.

Resposta

Se esta atividade for detectada, isole o endpoint afetado, colete imagens de memória e disco, e procure por Installer.exe, dw.exe, e seções suspeitas .bun . Bloqueie os domínios e URLs de comando e controle identificados no perímetro da rede. Desdobre detecções de endpoint para os comandos PowerShell observados e padrões de API Win32. Gire credenciais expostas e monitore sistemas afetados para sinais de mineração de criptomoeda não autorizada.

graph TB %% Definições de classes classDef technique fill:#ffcc99 classDef action fill:#99ccff %% Nós node_initial_access[“<b>Acesso inicial</b><br/><b>T1036.008 Mascaramento: Tipo de ficheiro</b>: ZIP malicioso disfarçado como tipo de ficheiro benigno.<br/><b>T1204.002 Execução pelo utilizador: Ficheiro malicioso</b>: A vítima executa o ficheiro descarregado.”] class node_initial_access technique node_obfuscated_loader[“<b>Loader ofuscado</b><br/><b>T1027.016 Inserção de código lixo</b>: Insere JavaScript irrelevante para ocultar a lógica maliciosa.<br/><b>T1027.008 Remoção de partes do payload</b>: Remove código não essencial para reduzir tamanho e evitar análise.”] class node_obfuscated_loader technique node_discovery[“<b>Descoberta</b><br/><b>T1082 Descoberta de informações do sistema</b>: Recolhe sistema operativo, hardware e software.<br/><b>T1016 Descoberta de configuração de rede</b>: Enumera adaptadores, endereços IP e informação de routing.”] class node_discovery technique node_credential_access[“<b>Acesso a credenciais</b><br/><b>T1555.003 Credenciais de navegadores</b>: Extrai passwords guardadas e dados de autopreenchimento.<br/><b>T1550.004 Uso de material de autenticação alternativo</b>: Recolhe cookies de sessão web para acesso autenticado.”] class node_credential_access technique node_c2[“<b>Comando e controlo</b>: Obtém seed de desencriptação AES e payload encriptado de servidor remoto.”] class node_c2 action node_execution[“<b>Execução</b><br/><b>T1620 Carregamento de código refletivo</b>: Carrega payload encriptado diretamente em memória sem escrita em disco.<br/><b>T1055.009 Injeção de processo: memória</b>: Injeta código refletido num processo em execução.”] class node_execution technique node_persistence[“<b>Persistência</b><br/><b>T1053 Tarefa agendada</b>: Cria tarefa agendada para executar o payload malicioso de forma recorrente.”] class node_persistence technique %% Ligações node_initial_access –>|leva a| node_obfuscated_loader node_obfuscated_loader –>|leva a| node_discovery node_discovery –>|leva a| node_credential_access node_credential_access –>|leva a| node_c2 node_c2 –>|leva a| node_execution node_execution –>|leva a| node_persistence

Fluxo de Ataque

Execução de Simulação

Pré-requisito: A Verificação Pré‑Voo 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. Exemplos abstratos ou não relacionados levarão a um diagnóstico incorreto.

  • Narrativa & Comandos do Ataque:

    1. Acesso Inicial: O atacante entrega um arquivo JavaScript malicioso (loader.js) no sistema da vítima e o executa usando o bun runtime (bun loader.js).
    2. Rotina de Autoinjeção: O código JavaScript chama APIs Win32 nativas via um auxiliar PowerShell que usa Add‑Type para definir assinaturas P/Invoke para VirtualAlloc, VirtualProtect, e LoadLibraryA.
    3. Alocação de Memória: VirtualAlloc reserva uma região RWX dimensionada para o shellcode embutido.
    4. Injeção de Shellcode: O script PowerShell copia o shellcode decodificado em base64 para a memória alocada usando Marshal.Copy.
    5. Mudança de Permissão: VirtualProtect altera a proteção da página para PAGE_EXECUTE_READ.
    6. Execução de Carga: LoadLibraryA é invocada em uma DLL maliciosa que reside apenas em memória (o cabeçalho da DLL é escrito na região alocada, então o endereço é passado para LoadLibraryA).
    7. Sem Nova Thread: O atacante evita deliberadamente chamar CreateThread; o DllMain da DLL é executado no contexto do processo atual, satisfazendo a cláusula de exclusão da regra.
  • Script de Teste de Regressão:

    # -------------------------------------------------
    # NWHStealer JavaScript Loader – Demo de Autoinjeção
    # -------------------------------------------------
    # Este script imita o comportamento do carregador real NWHStealer.
    # Ele chama deliberadamente VirtualAlloc, VirtualProtect, e LoadLibraryA
    # sem invocar CreateThread.
    
    # 1. Defina assinaturas de API Win32
    $sig = @"
    using System;
    using System.Runtime.InteropServices;
    public class Win32 {
        [DllImport("kernel32.dll", SetLastError=true)]
        public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
        [DllImport("kernel32.dll", SetLastError=true)]
        public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);
        [DllImport("kernel32.dll", CharSet=CharSet.Ansi, SetLastError=true)]
        public static extern IntPtr LoadLibraryA(string lpFileName);
    }
    "@
    Add-Type $sig
    
    # 2. Alocar memória executável (RWX)
    $size = 0x1000
    $MEM_COMMIT = 0x1000
    $PAGE_EXECUTE_READWRITE = 0x40
    $mem = [Win32]::VirtualAlloc([IntPtr]::Zero, $size, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
    if ($mem -eq [IntPtr]::Zero) { throw "VirtualAlloc failed" }
    
    # 3. Shellcode de exemplo (MessageBox) – codificado em base64 para legibilidade
    $b64 = "AQAAANAAAABAAEAAAABAAAAAgAAAAEAAABWAAAAAQAAAAIAAAD/////AQAAAAAAAAA="
    $shellcode = [Convert]::FromBase64String($b64)
    
    # 4. Copiar shellcode na região alocada
    [System.Runtime.InteropServices.Marshal]::Copy($shellcode, 0, $mem, $shellcode.Length)
    
    # 5. Alterar proteção para EXECUTE_READ
    $oldProtect = 0
    $PAGE_EXECUTE_READ = 0x20
    $ok = [Win32]::VirtualProtect($mem, $size, $PAGE_EXECUTE_READ, [ref]$oldProtect)
    if (-not $ok) { throw "VirtualProtect failed" }
    
    # 6. Carregar a "DLL" na memória (aqui simplesmente chamamos LoadLibraryA em kernel32 como um espaço reservado)
    # No carregador real, esta seria uma DLL personalizada escrita em $mem.
    $hLib = [Win32]::LoadLibraryA("kernel32.dll")
    if ($hLib -eq [IntPtr]::Zero) { throw "LoadLibraryA failed" }
    
    Write-Host "Passos de autoinjeção concluídos – o processo agora deve ser sinalizado pela regra de detecção."
    # -------------------------------------------------
  • Comandos de Limpeza:

    # Terminar a instância do PowerShell que realizou a injeção
    Stop-Process -Id $PID -Force
    
    # (Opcional) Se uma DLL personalizada foi escrita no disco para teste, remova-a
    Remove-Item -Path "$env:TEMPmalicious.dll" -ErrorAction SilentlyContinue

Validação Pós‑Execução

  1. Confirme a Geração de Alerta: Execute a seguinte consulta KQL para verificar se a regra foi acionada:

     // Regra de Detecção: VirtualAlloc/VirtualProtect/LoadLibraryA sem CreateThread
     Sysmon
     | onde EventID == 1
     | onde CallTrace contém "VirtualAlloc" ou CallTrace contém "VirtualProtect" ou CallTrace contém "LoadLibraryA"
     | onde não(CallTrace contém "CreateThread")
     | projeto TimeGenerated, Process, CallTrace, EventID
  2. Verifique se Não há Falso Positivo: Re‑execute o comando benigno do Notepad e assegure-se que a consulta retorne zero resultados para essa execução.


Fim do Relatório