Jump to content
  • Por dentro do Ransomware Nephilin

       (1 review)

    Leandro Fróes
    Faz algum tempo que ando botando mais a mão na massa na parte prática da análise de malware e nos conceitos que a envolvem. Este fato somado com minha paixão por tomar notas nos meus estudos acaba resultando na criação de alguns relatórios. Com isto em mente, decidi colocar aqui a análise do último sample no qual trabalhei, de um ransomware chamado Nephilin.
     
    Overview
     
    O Nephilin é uma variante do Nefilim, um Ransomware que acabou ficando bem conhecido no mês de fevereiro/março devido ao fato de ser uma variante do conhecido Nemty, que costumava trabalhar com operações de RaaS (Ransomware as a Service - um modelo de negócio utilizado por criminosos que facilita muito a distribuição de Ransomwares. Basicamente o criador do malware recruta pessoas para usarem o Ransomware e recebe uma parte de seus lucros, facilitando assim a distribuição e a entrada de pessoas não experientes no crime). Por mais que as formas de operação sejam diferentes, há similaridades de código entre essas três famílias de malware.
     
    Análise Estática
     
    O sample analisado foi compilado para x86 e não possui nenhuma técnica que possa dificultar nossa análise como por exemplo packers/protectors e o uso de ASLR. No entanto, este binário é assinado com um certificado válido:
     
    image.png.1dfc5082f0eca6128380b68cb9adaf27.png
     
    Olhando os imports podemos notar que a Import Directory Table possui apenas uma entrada, a da kernel32.dll, levantando a suspeita da utilização de runtime linking, ou seja, o loader não resolve o endereço das funções em tempo de carregamento, pois eles são resolvidos em tempo de execução:
     
    image.png.2959f6443e0c8056048aafc57afc8867.png
     
    Podemos suspeitar ainda mais pelo fato do nome algumas DLLs estarem na lista de strings do binário, assim como o nome de algumas funções que não são exportadas pela kernel32.dll:
     
    image.png.ef382850bc0c9acc9331588d36bc770f.png
     
    Não vou me preocupar muito com esta parte estática da análise, tendo em vista que a ideia deste artigo é cair de cabeça em cada funcionalidade do malware, isto é, executá-lo e ir analisando seu comportamento.
     
    Análise Dinâmica
     
    A primeira função que o malware chama é a que vai criar todo o contexto de criptografia para gerar uma chave que será a chave utilizada para descriptografar a Ransom Note:
     
    image.thumb.png.9a30fee98f6d5d77c4fa8b8cbe9acf7c.png
     
    image.thumb.png.37c57edec6f9ef726597f4225555db33.png
     
    Dentro desta função existem várias funções que permitem trabalhar com criptografia no Windows. A primeira função criptográfica chamada é a CryptAcquireContext, responsável por criar um handle para um key container dentro de um Cryptographic Service Provider (CSP). Após pegar o handle, o tamanho de uma string é calculado para posteriormente se criar e retornar um Hash Object dentro do CSP criado anteriormente. Esta string tem 66 bytes de tamanho (0x42 em hexa) e é uma string lotada de "a".
     
     A função CryptCreateHash cria o Hash Object especificando o tipo como SHA1 e, logo depois, a função CryptHashData tira o hash do que está dentro de um buffer de tamanho 66 bytes sendo passado como parâmetro:
     
    image.png.4de23e89f0c64ae5ab96fb80e576c6b5.png
     
    image.thumb.png.17eb9ca0d01a4c5390ce05417bbb0852.png
     
    image.thumb.png.c954886dc820b08509dafa6f33a3d242.png
     
    Por fim, o SHA1 gerado é derivado, para a geração de uma chave RC4. Como podemos ver quase todas as funções estão sendo importadas dinamicamente. ?
     
    O que acontece após a função que gera esta chave RC4 é a criação de um Mutex com o nome "sofos delaet sosos":
     
    image.thumb.png.7ab2876cc9b599339955a885ee833afb.png
     
    Em seguida, uma string em base64 aparece e é decodada com a função CryptStringToBinary, resultando em uma chave pública RSA:
     
    "BgIAAACkAABSU0ExAAgAAAEAAQDNFw18bUF1x32DZaZt4gnQtAnv5XH60d9B6UgIbVfRdHPeyEljZLKlGBKFPTsh+8xsDHe/9vynuOlnuPt91grReMAwcTDVkxBh/PDkf3Jq0bnFgZAWbgMvGX6lApXTDcTArf4US63VI3z8YPyDNJwEvBEWI13ywob8ECLsrD/C6BPkYG0mBU1ccixzOgkgad0iDvwS/C8iyW1Mi0PCoBa+3TCTVwt0Zpy/HceV5U7SevG7RRN5HrErv54Ihg6kTPPhdxkYdO+CUND19aLqh8MAVLRuP5hR6b6r7cjBNAW2+USaaMyT/llNXdPdySbatLlH6Mau4z1eqzYc7hMB2f+6"
     
    image.thumb.png.ee23ab0d63ab3d7ebaef213232cf195e.png
     
    image.png.977558043b3e1e96557242c9eedfa5e6.png
     
    Há depois uma tentativa de pegar um handle para um CSP onde o key container tem o nome  "rsa session" e, sem sucesso, o binário cria um novo chamado "skr skr skr":
     
    image.thumb.png.18639acce79b90ef01fdef41d32e7ca0.png
     
    Agora a chave pública decodada anteriormente será importada para o contexto "skr skr skr":
     
    image.thumb.png.2d6f05b299fcbac43bdc42aec5dd1652.png
     
    image.png.6d20a48043f438755e64cc293574afa6.png
     
    Ações padrão da maioria dos ransomwares incluem desabilitar a checagem de erros durante o boot, desabilitar o modo de recuperação, deletar backups, etc. O Nephlin faz isso através de uma chamada à função ShellExecuteA() passando uma linha com o cmd.exe como parâmetro:
     
    "C:\\asdfgsdgasd\\..\\Windows\\asdgagsahsfahfhasahfsd\\..\\System32\\cmd.exe" "/c bcdedit /set {default} bootstatuspolicy ignoreallfailures & bcdedit /set {default} recoveryenabled no & wbadmin delete catalog -quiet & wmic shadowcopy delete"
     
    image.thumb.png.a3c4bbe8379a89f5587f4aa7a8a40b45.png
     
    Aqui foi utilizada uma abordagem um tanto curiosa, tendo em vista que o malware considera diretórios que provavelmente não existirão no sistema de arquivos da vítima ("asdgagsahsfahfhasahfsd", por exemplo) e sobe um nível no filesystem utilizando ".." para acessar de fato o que importa, ou seja, o caminho real seria simplesmente "C:\Windows\System32\cmd.exe" ?
     
    Neste momento acontece uma checagem em relação à como o malware foi executado na linha de comando. Se foi passado algum parâmetro, ele checa pra ver se é um arquivo ou diretório. Se for um arquivo, ele chama direto a função que encripta. Caso seja um diretório, ele chama a função que checa uma lista de exclusão dos tipos de arquivos que ele não quer encriptar e esta função chama então a função que encripta.
     
    É interessante notar que com essas checagens o ransomware pode ser usado em diversos cenários e não simplesmente para encriptar o sistema completamente. Ex: para manualmente testar se ele está funcionando (antes da possível invasão), ser executado manualmente após a invasão visando diretórios/arquivos específicos, etc:
     
    image.png.e082bae4138d24b0c93e567593e458fb.png
     
    Se nenhum parâmetro for passado via linha de comando, o binário começa a mapear os drives que estão no sistema e pegar seus tipos, buscando especificamente por drives fixos, removíveis (pen drives, etc) e mapeamentos de rede:
     
    image.thumb.png.c0752111308978a9c7a4f6f8756e4d3c.png
     
    Após pegar o drive o seu nome é concatenado com a string "NEPHILIN-DECRYPT.txt", à fim de criar a Ransom Note na raiz do Drive em questão:
     
    image.thumb.png.65f0cd0ee48dc92eeb9c252db94f9674.png
     
    Após a chamada à CreateFile, podemos ver a Ransom Note sendo criada, mas vazia por enquanto:
     
    image.png.73accce4a8de8c028e2d28d758b80e0f.png
     
    Antes do conteúdo ser de fato escrito no arquivo, ele precisa ser decodado, tendo em vista que é uma string em base64 (sim, outra string em base64):
     
    image.thumb.png.e5dfa670e60df9c57bf2a664fe012491.png
     
    Abaixo está o buffer que contém o conteúdo da Ransom Note em base64:
     
    image.png.73a2694147492320e96b384a50390061.png
     
    Após decodar o base64 o buffer aparenta estar encriptado, e de fato está:
     
    image.png.09048bc372cf0e706ec8f461b4fed076.png
     
    A função CryptDecrypt utiliza a chave RC4 gerada anteriormente para decriptar o conteúdo do buffer em questão. Podemos ver o conteúdo em clear text após a execução da função:
     
    image.png.b521ca6dff4777a5cf8e49ae94df3893.png
     
    Por fim podemos ver a função WriteFile, que irá escrever o conteúdo no arquivo "NEPHILIN-DECRYPT.txt" criado anteriormente:
     
    image.thumb.png.3fc9d6b2f7345e2d91591f866080c815.png
     
    image.png.398256a0c77f96f4475e5edbc550f885.png
     
    Agora que a Ransom Note foi criada, o processo de criptografia começa. O meio utilizado é através da criação de outra thread, isto é, para cada drive encontrado, uma nova thread é criada. A função CreateThread recebe como parâmetro para indicar seu início o endereço de uma função, que por sua vez chama a função que checa a lista de exclusão e depois começa a criptografia. Além disso, o nome do drive escolhido no momento é passado como parâmetro para esta função.

    Esta lista de exclusão é basicamente um lista que contém nomes de arquivos, diretórios e extensões das quais o malware não irá encriptar. Para cada arquivo encontrado o malware irá comparar com as especificações desta lista e, caso não bata, a função de criptografia será chamada:
     
    image.thumb.png.975e0abc618a1c9a1bc7308b9024b564.png
     
    image.thumb.png.0a5ccb5fe0b4d51415b3813771572964.png
     
    image.png.4d2b3101cc199f3fb44ffd30fac8f3fe.png
     
    image.png.ed4d742be06e85efe7e5185ac0f8f9e0.png
     
    Criptografia
     
    A criptografia pode começar de 3 formas diferentes, como mencionado anteriormente: passando um arquivo como parâmetro pela linha de comando, passando um diretório ou mapeando os drives e criando threads.
     
    Um trecho da função que faz as devidas checagens pode ser observada abaixo:
     
    image.png.3d04f00e99471d64cbe79095454df8db.png
     
    Se o arquivo checado não estiver na lista de exclusão, a função de criptografia é chamada:
     
    image.png.f2cc8e798ae645c5f41b3d33a7edc887.png
     
    O processo de criptografia se inicia com a abertura do arquivo em questão e a obtenção do seu tamanho. Depois disso, há duas chamadas para a função SystemFunction036 para gerar números aleatórios. Basicamente esta função é um alias para a função RtlGenRandom, que recebe como parâmetro um buffer e o tamanho do número aleatório que você quer gerar. O tamanho escolhido são 16 bytes (0x10):
     
    image.thumb.png.15af78e8274b04a590bfaa0cc247e4ed.png
     
    image.png.9cef88d8984ff2f05379a7a59efd4bce.png
     
    Tendo 2 buffers de 10 bytes de tamanho cada, com os devidos números aleatórios gerados anteriormente, há duas chamadas à CryptEncrypt, uma para cada buffer. Aqui a chave pública RSA é utilizada para encriptar o buffer em questão, resultando em outros dois buffers de 256 bytes cada.
     
    image.thumb.png.b15d2c4fa22cdf87c2b46b4a2abc5ff1.png
     
    image.png.76a2606a07c76d5285d7c42afd94ac08.png
     
    O conjunto de funções a seguir faz a mesma operação, mas apontando para lugares diferentes. A função SetFilePointerEx é utilizada para apontar para o fim do arquivo (baseando-se no tamanho obtido anteriormente) e depois a função WriteFile é utilizada para escrever os 256 bytes encriptados lá. A próxima chamada à SetFilePointerEx agora aponta para o fim do arquivo + 256 bytes e então escreve o segundo buffer encriptado onde o ponteiro está apontando.
     
    image.thumb.png.a631f976bc5874628fd4333b6730a6ac.png
     
    image.png.d337bbb77f3d88d077bcace73f79249b.png
     
    Neste momento as checagens de tamanho de arquivo começam, assim como as chamadas de função e loops que envolvem a criptografia.
     
    A primeira checagem feita é se o arquivo é maior que 64MB e, caso seja, as funções que criptografam o arquivo começam a ser chamadas de 125KB em 125KB. Caso o arquivo seja menor há uma outra checagem para ver se ele é menor que 1.2MB e caso ele não seja as funções de criptografia rodam em cima de 600KB apenas e finalizam. Caso o arquivo seja menor que 1.2MB ele é encriptado "de uma vez" e depois finaliza.
     
    image.thumb.png.da864155eaba527f35e134377b2ec08b.png
     
    image.thumb.png.5a5e51e4ff53d2a1c9f04bfc39fa2cb0.png
     
    image.thumb.png.bfa091638ab5ded94b70aeb804a43af0.png
     
    Para cada arquivo é gerada uma chave randômica com a função SystemFunction036 e depois esta é encriptada com a chave RSA pública. Esta abordagem dificulta bastante a criação de um decryptor, tendo em vista que a chave será sempre aleatória. Por outro lado, se tivemos a chave RSA privada em mãos a aleatoriedade não teria efeito nenhum pois para cada arquivo teríamos a chave responsável pela sua criptografia.
     
    Por fim a extensão ".NEPHILIN" é adicionada ao arquivo aberto:
     
    image.png.77dc0934cdc5a542295ee9b2f1095b68.png
     
    image.png.c60e66e2ed752dae92cd95f8bc01ad4d.png
     
    image.png.4c526a40d3dfdab2113935f5025bbea9.png
     
    image.png.40b0a5abfb0d9b989bf3bc908edd0797.png
     
    image.png.7ff54b9fb43188ce4f5a70922f4bab00.png
     
    Uma coisa importante a se notar é que se a criptografia foi executada para um arquivo ou diretório específico tanto a Ransom Note quanto o wallpaper do Ransomware não são criados. Podemos observar que as funções de mapeamento de drives (que contém a criação da Ransom Note) e criação do papel de parede são ignoradas devido ao salto incondicional JMP:
     
    image.thumb.png.6c5cf9929f231477b9c900a2199d8942.png
     
    E por fim...
     
    Considerando ainda que não foram especificados arquivos e diretórios, a função responsável por criar a imagem do papel de parede é chamada. Há várias funções aqui e estas utilizam funções gráficas do Windows para editar a imagem em questão:
     
    image.thumb.png.c026ca270a27e242c688822240928356.png
     
    Uma das funções chamadas nesta função responsável por criar a imagem é justamente a função de decoda o base64 da Ransom Note, pois o que é escrito no papel de parede é a mesma coisa da Ransom Note. Após várias funções gráficas para preparar a imagem o arquivo é finalmente criado em %TEMP%, com nome god.jpg e seu conteúdo é escrito no arquivo:
     
    image.thumb.png.e35d57b33b3f77ec79fa12b7a5f77f25.png
     
    image.png.0f7e2d8004295d93422322c36ef46473.png
     
    image.png.c578e41a88878db70d952c6350772f42.png
     
     
    Após configurar a imagem como papel de parede, o malware chama sua última função, que é responsável por fechar todos os handles e contextos de criptografia ainda pendentes:
     
    image.thumb.png.c207d2c5fbdcd7a5337dc11f0feeb71c.png
     
    Depois disso, o processo simplesmente sai retornando 0.
     
    Lista de exclusão:
     
    NEPHILIN-DECRYPT.txt
    $RECYCLE.BIN
    NTDETECT.COM
    MSDOS.SYS
    IO.SYS
    boot.ini
    AUTOEXEC.BAT
    ntuser.dat
    desktop.ini
    CONFIG.SYS
    BOOTSECT.BAK
    program files
    program files (x86)
    windows
    ntldr
    RECYCLER
    bootmgr
    programdata
    appdata
    .dll
    .NEPHILIM
    .exe
    .log
    .cab
    .cmd
    .com
    .cpl
    .ini
    .url
    .ttf
    .mp3
    .pif
    .mp4
    .msi
    .lnk
     
    Espero que o estudo desta análise seja proveitoso assim como foi para mim e qualquer dúvida/feedback estou à disposição!
     
    Abraços!

    Revisão: Fernando Mercês

    User Feedback

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.
    Note: Your post will require moderator approval before it will be visible.

    Guest

    • This will not be shown to other users.
    • Add a review...

      ×   Pasted as rich text.   Paste as plain text instead

        Only 75 emoji are allowed.

      ×   Your link has been automatically embedded.   Display as a link instead

      ×   Your previous content has been restored.   Clear editor

      ×   You cannot paste images directly. Upload or insert images from URL.



  • Similar Content

×
×
  • Create New...