Pesquisadores de segurança descobriram um pacote malicioso no npm (gerenciador de pacotes do Node.js) que faz parte de uma campanha de ataque à cadeia de suprimentos de software, divulgada recentemente e batizada de MALFEX.
O pacote, chamado "imgdecode", foi publicado no registro de pacotes em 30 de setembro de 2026 por um usuário chamado "malfexteste8". Até a redação desta matéria, ele havia sido baixado 979 vezes e continuava disponível no npm. A versão mais recente é a 1.0.3.
"O pacote npm imgdecode esconde um carregador malicioso em um addon nativo do Node.js compilado", afirmou a SafeDep. "Seu arquivo JavaScript de nove linhas carrega uma biblioteca de vínculo dinâmico (DLL) do Windows. Quando um programa Node.js chama require('imgdecode') a partir de um console do Windows, a DLL tenta baixar do GitHub um shellcode criptografado. Ela descriptografa a resposta e injeta o resultado em um novo processo dllhost.exe."
Identificado inicialmente pela Checkmarx e pela CloudSEK, o MALFEX é o nome atribuído a uma campanha de longa duração, na qual um agente de ameaça desconhecido vem publicando pacotes maliciosos no npm desde 6 de agosto de 2023, com o objetivo de comprometer sistemas Windows. Esses pacotes foram publicados em cinco contas de publicação: malfexkkj, malfex_user, malfexteste2, malfexteste3 e malfexteste4.
Dos oito pacotes identificados, três atuavam como carregadores do Overlord RAT (ferramenta de acesso remoto). Outros três ("cdn-img-fetch", "img-to-native" e "native-runner") trabalhavam juntos para baixar e executar um programa de roubo de dados (stealer) do Node.js. Um terceiro caminho de infecção envolvia o uso de um hook de pós-instalação (postinstall) para executar JavaScript capaz de contatar um servidor externo e obter um binário de próxima etapa, não especificado.
Curiosamente, o operador por trás da campanha parece reagir a divulgações públicas e remoções feitas pelo npm, publicando substitutos para "native-runner" e "img-to-native" em até dois dias, na forma de "runhelper" e "imgbundle". No mesmo dia, a primeira versão de "imgdecode" foi publicada. A linha do tempo dos eventos é a seguinte:
Linha do tempo
- 26 de setembro de 2026: cdn-img-fetch, img-to-native e native-runner 1.0.0 publicados
- 28 de setembro de 2026, às 16h06 UTC (Tempo Universal Coordenado): npm remove native-runner e img-to-native
- 30 de setembro de 2026, às 03h29 UTC: imgbundle 1.0.0 publicado, substituindo img-to-native
- 30 de setembro de 2026, às 03h37 UTC: runhelper 1.0.0 publicado, substituindo native-runner
- 30 de setembro de 2026, às 16h13 UTC: runhelper despublicado
- 30 de setembro de 2026, às 22h32 UTC: imgdecode 1.0.0 publicado
- 30 de setembro de 2026, às 23h07 UTC: imgdecode 1.0.1 publicado
- 1º de outubro de 2026, às 17h48 UTC: imgdecode 1.0.2 publicado
- 7 de outubro de 2026, às 23h06 UTC: npm remove imgbundle
- 8 de outubro de 2026, às 13h03 UTC: npm remove cdn-img-fetch
- 11 de outubro de 2026, às 22h09 UTC: imgdecode 1.0.3 publicado
A cadeia de roubo de dados do Node.js chama a atenção pelo fato de nenhum dos pacotes ter um hook de instalação. Em vez disso, o código malicioso é executado quando "native-runner" é carregado. O pacote declara "img-to-native" como sua dependência, que, por sua vez, tem "img-to-native" como dependência.
Funcionamento dos pacotes
As funções exatas de cada um desses pacotes são as seguintes:
- cdn-img-fetch baixa "banner.png" de um repositório do GitHub ("cavecrew/proj") e extrai um bloco criptografado.
- img-to-native descriptografa o bloco usando a chave "malfexteam2027" e grava o conteúdo no disco como um executável em Go ("%APPDATA%\Microsoft\Windows\node_runtime_helper.exe").
- native-runner executa o executável em Go, que então baixa o binário do stealer ("setup.exe", também conhecido como movinlike) a partir de "104.234.65[.]75:700".
"Runhelper", apresentado como um utilitário auxiliar para "lançar binários nativos a partir de projetos Node.js", funciona de forma semelhante ao "native-runner", pois foi projetado para executar código malicioso. Sua principal função é localizar um arquivo JPG ("cdn-img-fetch/.runtime/rt.jpg"), extrair dele um shellcode, copiá-lo para a memória executável e executá-lo com o Koffi, um módulo de interface de função estrangeira (FFI) para Node.js.
"Seis horas depois que o runhelper foi despublicado, o operador publicou o imgdecode com uma DLL compilada para executar o shellcode", disse a SafeDep. "A partir da versão 1.0.1, a DLL também baixa e descriptografa a carga. As versões 1.0.1 e 1.0.2 ainda chamam require('imgbundle') antes de carregar a DLL. A versão 1.0.3 remove essa dependência e não precisa de nenhum outro pacote do MALFEX."
Assim como no caso do "runhelper", a versão 1.0.0 do "imgdecode" aguarda que o "imgbundle" grave um arquivo no local "cdn-img-fetch/.runtime/". Quando o arquivo estiver disponível, o pacote lê seu conteúdo na memória e o repassa a um addon nativo do Node.js para decodificar os dados.
O addon é uma DLL de 64 bits do Microsoft Visual C++ (MSVC) que primeiro verifica se está sendo executada no terminal de um desenvolvedor. Em seguida, baixa um arquivo JPG ("banner.jpg") do mesmo repositório ("cavecrew/proj"), descriptografa a carga incorporada usando a chave "nif-runtime-2027" e, por fim, injeta o resultado em "dllhost.exe".
"Após a descriptografia, a DLL verifica os primeiros bytes do texto simples", explicou a SafeDep. "Se eles corresponderem à assinatura de um JPEG ou de um PNG, a DLL para. Inferência: o operador poderia desligar o carregador servindo um conteúdo criptografado que descriptografa para uma imagem. Servir uma imagem comum faria a descriptografia falhar antes dessa verificação, em geral."
Embora a conta "cavecrew" no GitHub não esteja mais acessível, uma captura de tela do Internet Archive do arquivo de imagem, datada de 6 de outubro de 2026, mostra que se trata do mesmo downloader baseado em Go usado para obter o stealer do Node.js e a ferramenta de acesso remoto (movinlike) a partir de "104.234.65[.]75:700".
O aplicativo Node.js inclui um arquivo .env que contém um endereço de comando e controle (C2, na sigla em inglês) ("104.234.65[.]75:7007") e uma chave de licença do MALFEX. Isso indica o uso de um construtor de malware ou de um sistema de licenciamento para criar essas cargas maliciosas.
O malware executa verificações anti-análise que procuram a presença de máquinas virtuais, sandboxes e ferramentas de análise, como Process Monitor e Wireshark. Só depois disso ele coleta frases de recuperação de carteiras (seed phrases) e arquivos com extensões específicas (.kdbx, .pem, .ppk e .env), além de dados de navegadores baseados em Chromium, Discord, Telegram, carteiras de criptomoedas e aplicativos de jogos (Steam, Epic Games, Riot, Battle.net, Minecraft e Ubisoft).
Ele também pode estabelecer uma conexão WebSocket com o servidor C2, o que permite receber comandos para execução de shell, transferência de arquivos, controle de processos, acesso à área de transferência, capturas de tela e entrada de mouse e teclado. Para garantir persistência, adiciona uma chave Run ao Registro do Windows e cria uma tarefa agendada chamada "MicrosoftEdgeUpdateService".
Desenvolvedores que instalaram qualquer um dos pacotes mencionados devem considerar seus sistemas Windows potencialmente comprometidos. Recomenda-se isolá-los, verificar entradas de persistência, trocar credenciais e transferir fundos para novas carteiras caso frases de recuperação tenham sido armazenadas neles.