Receba as últimas notícias, ameaças e recursos do setor.
O ransomware DJVU/STOP, desde que foi detectado pela primeira vez em 2018, foi observado de forma intermitente como parte de ataques de ransomware, mas não ganhou a notoriedade de outros ransomwares como REvil ou Conti. No entanto, houve um ressurgimento, com uma nova variante do DJVU/STOP se tornando um dos malwares de criptografia de arquivos mais difundidos de 2021. Tanto que se tornou um incômodo global, visando entidades nos Estados Unidos, Europa, Ásia, América do Sul e África. Ele foi detectado em pacotes populares de crack de software ou pacotes de adware, que geralmente são encontrados em sites de torrent e outras plataformas.
Nesta série de blogs em duas partes, vamos nos aprofundar no modus operandi do ransomware DJVU/STOP, seus aspectos técnicos e características, como ele identifica as vítimas e mantém a persistência.
Modo de operação do DJVU/STOP Ransomware
O ransomware DJVU/STOP é um malware Trojan de criptografia de arquivos que invade secretamente o computador da vítima e criptografa todos os arquivos para torná-los inacessíveis. Depois disso, ele envia uma nota de resgate notificando a vítima sobre a criptografia. A nota também exige uma quantia específica de dinheiro como resgate pelas chaves de decodificação que descriptografarão os arquivos comprometidos e os tornarão acessíveis à vítima.
O carregador
A amostra analisada (hash) atua como um programa carregador para implantar o criptador de ransomware como o estágio final da cadeia de infecção.
Foi observado que existem várias execuções de código de shell para tornar a entrega do cripter o mais discreta possível, a fim de evitar a segurança.
O carregador também executa algumas verificações de Segurança Operacional (OPSEC) antes da execução do estágio inicial.
Estágio 1
No estágio inicial, o carregador enumera o sistema vítima lendo os atributos do sistema para recuperar informações como nome de usuário, arquitetura do processador, caminho do sistema, diretório raiz do Windows, unidades de rede, entre outros detalhes necessários para infectar ainda mais a máquina.
O carregador aloca uma região de memória com permissões de LEITURA/GRAVAÇÃO/EXECUÇÃO e despeja um código de shell independente de posição para ser executado posteriormente.
Etapa 2
Nesse estágio, o código de shell primário despeja um código de shell secundário em uma memória alocada.
O código de shell secundário executa o “esvaziamento do processo” para entregar a carga útil final do criptografador dentro de um processo carregador recém-gerado com um ID de processo diferente.
O processo recém-criado possui um conjunto de instruções, como resultado do esvaziamento do processo, que podem iniciar a criptografia no sistema da vítima e realizar comunicações de rede.
Estágio de resgate
Na fase final, o ransomware está ativo no sistema da vítima e começa a criptografar seus arquivos, antes de entregar a infame nota de resgate.
Análise técnica
Funcionamento do carregador
O carregador aloca uma memória usando a API VirtualAlloc Win32 com definição de função:
No carregador, os seguintes argumentos são usados para chamar o VirtualAlloc:
A página de memória alocada é capaz de leitura/gravação e execução. Embora na superfície isso possa parecer trivial, é um comportamento comum visto até mesmo nos malwares mais sofisticados executar códigos maliciosos na máquina da vítima de forma discreta.
FLProtect: 0x40
Tipo de alocação FLA: 0x1000
Tamanho DW:
Endereço LP: 0x0
Memória com zero bytes:
O carregador preenche a memória alocada, da etapa anterior, com o shellcode.
O fluxo de execução é então transferido para o código de shell recém-alocado, conforme mostrado abaixo. E a CPU agora aponta para a primeira instrução do código de shell malicioso quando ele começa a ser executado.
Funcionamento do Shellcode do Estágio 1
O shellcode primário de estágio 1 é programado para injetar o shellcode secundário, que é responsável pelo “esvaziamento do processo”, para entregar o código criptografado final do ransomware.
O shellcode primário entrega módulos em seu espaço de endereço, incluindo, mas não se limitando a:
ntdll.dll
Kernel32.dll
A resolução de endereços é feita obtendo o endereço de uma das funções cruciais no módulo kernel32, que é Kernel32.getProcAddress. Os autores de malware usam o Kernel32.getProcAddress para resolver dinamicamente as APIs do Win32 para evitar o escrutínio da análise de código examinando a tabela de importação do programa. Alguns endereços de funções interessantes também foram resolvidos para serem usados posteriormente no programa.
Depois que o malware obtém o endereço da função Kernel32.getProcAddress, ele é usado para resolver os endereços das seguintes funções:
Kernel32. Global Alloc
Kernel3.2. VirtualAlloc
Kernel32.setLastError
Kernel32.sleep
Kernel32.CreateToolHelp32 Snapshot
Kernel32. Primeiro módulo 32
Kernel3.2. Fechar o controle
Depois de resolver os endereços de várias funções, o shellcode começa a executar duas APIs Win32:
Criar um instantâneo do ToolHelp32
Módulo 32 First
Argumentos passados para Criar um instantâneo do ToolHelp32 são:
Bandeiras DW: 0x08 (TH32CS_SNAPMODULE)
The32ProcessiD: 0x0 (processo atual)
ALÇA Criar um instantâneo do ToolHelp32( [em] DWORD DWFlags, [em] DWORD TH32ProcessID );
Os argumentos passados para a função Module32First são:
hSnapshot: 0x108 (identificador de instantâneo para o instantâneo anterior retornado de CreateToolHelp32snapshot)
Lpme: 0x19F768 (Um ponteiro para uma estrutura MODULEENTRY32)
Os códigos mencionados acima são funções comumente usadas para realizar atividades maliciosas. Neste caso:
CreateToolHelp32Snapshot é usado para criar um instantâneo, que contém pilhas, módulos e threads, usados pelos processos de um determinado processo.
O Module32First é usado para percorrer os módulos presentes no instantâneo fornecido pelo CreateToolHelp32Snapshot.
O carregador recupera o código do shell dessa maneira e, em seguida, passa a alocar memória e escrever o shellcode.
Funcionamento do Shellcode do estágio 2
O código de shell do estágio 1 aloca memória com argumentos anteriormente anotados para o código de shell do estágio 2, usando a API VirtualAlloc Win32.
A próxima etapa envolve escrever o shellcode na memória alocada. O controle é então transferido para a lógica de escrita do shellcode por meio de “call 4AE04F2”.
A chamada anterior chega à lógica de código fornecida abaixo, que grava iterativamente o shellcode do estágio 2 no buffer alocado.
Depois que o shellcode é transferido, o controle é atribuído ao shellcode por um comando JMP, conforme mostrado abaixo:
Após o salto, a CPU aponta para o início do shellcode do estágio 2. Esse código de shell é responsável por realizar o “esvaziamento de processos” para fornecer uma carga útil criptografada de ransomware que criptografa os dados do usuário. Em seguida, o shellcode do segundo estágio carrega os módulos user32.dll, ntdll.dll e kernel32.dll no processo atual.
Usando Kernel32.getProcAddress, os endereços das seguintes funções interessantes são resolvidos:
Usuário 32. Caixa de mensagens A
Kernel32.CreateProcess
Kernel32.CreateProcess
User32.getMessageExtraInfo
Kernel32.getThreadContext
Kernel32.getModuleFileName A
Usuário 32. Registre a Classe XA
Kernel3.2. VirtualAlloc
Kernel32.get linha de comando A
Usuário 32. Crie o Windows EXA
Kernel 32. Virtual AlloceX
Kernel32.getFileAtributos A
Usuário 32.postar mensagem A
Kernel 32. Virtual Grátis
Kernel 32. Obtenha informações de inicialização
user32.def WindowProCA
Kernel 3.2. Memória de processo de leitura
Kernel 32. VirtualProtecteX
Kernel32.WinExec
Kernel 3.2. Memória do processo de gravação
Processo Kernel.Exit
Kernel32. Criar arquivo A
Kernel 32. Defina o contexto do tópico
Ntdll.ntunMapVisualização da seção
Kernel32. Escrever arquivo
Kernel32. Retomar o tópico
Memória virtual ntdll.ntwrite
kernel32. Fechar alça
Kernel 32. Espere por um único objeto
O shellcode verifica um arquivo específico chamado “apfHQ”. Nossa melhor suposição é que o arquivo é usado como um marcador para identificar as vítimas. Embora a string seja muito comum em várias famílias de malware, a razão exata desse comportamento ainda é desconhecida.
O shellcode então cria uma janela classe usando duas APIs, a saber, User32.registerClassExa e User32.createWindoExa. O nome dado à classe é “saodkfnosa9uin”.
A classe de janela criada anteriormente é usada para criar uma janela oculta usando User32.createWindowExa, conforme mostrado abaixo:
Processo de esvaziamento
Conforme mencionado acima, o objetivo do shellcode de segundo estágio é realizar o esvaziamento do processo para implantar um criptografador de ransomware para criptografar os dados do usuário.
O esvaziamento de processos é uma forma secreta de injetar código malicioso em um processo benigno e confiável para evitar a detecção e a segurança. Uma explicação intuitiva para o esvaziamento do processo é esculpir a instrução legítima e original do aplicativo benigno para substituí-la por uma maliciosa, sem informar o aplicativo sobre a alteração no código feita pelo agente da ameaça. É por isso que os atacantes criam um processo em estado suspenso e o retomam após a conclusão do esvaziamento.
Etapas básicas envolvidas na execução do esvaziamento
A primeira etapa é selecionar uma imagem PE candidata (aplicativo) para esvaziamento. Nesse caso, o executável do carregador é reaparecido com a carga útil final do ransomware.
A API Win32 Kernel32.getModuleFilenameA é então usada para obter o nome do executável do carregador, que é usado posteriormente na API Kernel32.createProcessA.
O shellcode obtém informações que precisam ser usadas posteriormente na criação do processo. Essas informações consistem nas informações de inicialização do processo e da linha de comando fornecidas ao processo recém-criado.
O ransomware então inicia um novo processo com os seguintes parâmetros: “—Admin IsNotAutoStart IsNotTask.”
Shellcode usando Kernel32.getStartupInfoa para recuperar informações de inicialização
Shellcode usando Kernel32.getStartupInfoa para recuperar parâmetros da linha de comando
Posteriormente, o malware cria um processo em estado suspenso. O Kernel32.createProcessA é usado para criar o processo, usando argumentos como executável de destino, informações de inicialização e parâmetros da linha de comando, etc.
Em seguida, o Bloco de Ambiente de Processo recupera o endereço da imagem base do executável a partir do qual o processo foi criado. O agente da ameaça precisa saber o endereço base para desmapear a imagem real do PE (código) e, em seguida, introduzir a imagem maliciosa.
O Kernel32.ReadProcessMemory é usado para obter o endereço da imagem.
O processo de desmapeamento é feito chamando a função ntdll.zwunmapViewOfSectionA:
Agora, o malware tenta alocar uma memória virtual no espaço de memória do processo remoto criado. Essa memória será usada para hospedar o código do ransomware no processo recém-gerado.
O Kernel32.VirtualAlloceX é usado especificamente para criar as alocações de memória nos espaços de endereço remoto, conforme mostrado abaixo:
A carga útil final é armazenada no carregador. A carga começa com um byte “MZ” indicando que é um executável. Isso precisa ser extraído para uma análise mais aprofundada, pois é o criptador final que o carregador implanta a partir do novo processo.
Na próxima etapa, o malware grava a carga útil na memória do processo remoto do processo recém-gerado por meio de createProcessA.
Agora, o malware pode gravar a carga final no espaço de endereço do processo remoto usando ntdll.zwwriteVirtualMemory/NTWriteProcessMemory, conforme mostrado abaixo:
Escrever um novo código malicioso (esvaziamento) no processo recém-criado é mostrado abaixo. O malware grava bytes iterativamente no processo remoto, que está em estado suspenso. As alterações são feitas segmento por segmento (.text, .data etc).
Em seguida, o ponto de entrada usado pelo carregador do Windows para iniciar a execução do código do programa do aplicativo é alterado.
Essas informações podem ser encontradas no thread primário criado com o processo suspenso. O Kernel32.getThreadContext é usado para recuperar as informações específicas do tópico.
Depois que o ponto de entrada é alterado, as alterações são confirmadas por meio da API Kernel32.setThreadContext e o processo suspenso executa o código malicioso.
Como etapa final, o thread é retomado no processo de destino, que sai do estado suspenso e executa o código do ransomware. A API Kernel32.resumeThread é usada para retomar o thread remoto.
Nesse estágio, podemos observar várias instâncias do programa carregador na listagem de processos. E as alças abertas pelo carregador agora estão fechadas usando Kernel32.closeHandle.
Finalmente, o carregador sai via Kernel32.exitProcess e encerra a execução.
Na lista de processos de memória, haverá um processo com um ID diferente, que é o mesmo executável do carregador, mas com uma lógica de código diferente inserida nele no estágio de esvaziamento do processo.
Esse processo com o novo PID será responsável por criptografar a vítima.
Na segunda parte da postagem do blog, continuaremos analisando o código criptografado do ransomware após obter o processo recém-criado do despejo de memória.
Nenhum item encontrado.
Inscreva-se nos recursos do CloudSEK
Receba as últimas notícias, ameaças e recursos do setor.