/
Ransomware Containment

Desmistificando técnicas de ransomware usando assemblies.NET: conjuntos EXE versus DLL

Na primeira parte desta série, examinamos algumas técnicas usadas por malware, especificamente ransomware. Como vimos, essas técnicas individuais, como baixadores, droppers e carregadores, bem como codificação e criptografia, são todas capacidades legítimas e programáveis oferecidas pela estrutura de software.Net (dot net) e por muitas outras estruturas de programação e linguagens de código. Abaixo está uma colagem de algumas das técnicas discutidas no artigo anterior.

Neste segundo artigo, examinaremos os fundamentos das montagens por meio da estrutura do Microsoft.Net. Vamos nos aprofundar nas diferenças entre assemblies (EXE versus DLL) e seus relacionamentos, o que permite que esses recursos sejam eventualmente executados a partir de um código inicial de alto nível, como o código de programação C#. Usaremos o código apresentado no artigo anterior para explorar essas diferenças e relacionamentos.

O que é o Microsoft.Net?

O Microsoft.Net é uma estrutura de desenvolvimento de software projetada para suportar várias linguagens de programação e ter como alvo diferentes sistemas operacionais. Linguagens de programação suportadas, como C# (pronunciado C sharp), são compiladas e executadas como o que é conhecido como código gerenciado (em oposição ao código nativo ou não gerenciado). Para conseguir isso, o.Net executa seu código em uma máquina virtual dedicada em vez de diretamente na plataforma de destino. Essa máquina virtual é conhecida como CLR (common language runtime) .Net. Ele pode ser considerado o intermediário comum que eventualmente executa o código compilado ou montado de todas as diferentes linguagens de programação, como C#, VB.Net e F#, que o.Net suporta. O exemplo abaixo mostra o código da linguagem de programação C# do artigo anterior.

Código gerenciado significa que o código de alto nível da linguagem de programação C# acima e outros, como F# e VB.Net, são compilados primeiro em uma linguagem intermediária (IL). O código de alto nível do C# mostrado acima é compilado de acordo com as instruções da linguagem intermediária mostradas na imagem abaixo. Esse código se assemelha à sintaxe de programação de montagem de baixo nível.

Essa linguagem intermediária (IL) é então compilada em código nativo ou de máquina visando a plataforma de máquina relevante. Essa compilação é feita por outro componente do.Net chamado compilador Just-in-Time (JIT).

O código nativo ou de máquina é o conjunto de instruções (zeros e uns) que o processador (CPU) de um determinado computador entende. Essa última etapa é gerenciada pelo Common Language Runtime (CLR), que também contém o JIT. O CLR é o ambiente de execução do.Net ou a máquina virtual. Java é outra estrutura de software que usa o conceito de tempos de execução intermediários. Semelhante à Java Virtual Machine, ela é a parte principal do que torna a plataforma Net independente. O código.NET  é chamado de código gerenciado porque o código de programação é gerenciado pelo CLR intermediário e não executado diretamente pela CPU do computador.

Uma vantagem do código gerenciado no.Net é o gerenciamento automático de memória e a coleta de lixo. Isso significa que o desenvolvedor não precisa se preocupar em alocar e desalocar a memória do computador em seu código para economizar recursos do sistema, como no caso do código C ou C ++. No.Net, existe o coletor de lixo que é executado periodicamente para lidar com a memória desalocada. Ele também pode ser chamado pelo programador quando necessário. O diagrama abaixo mostra a arquitetura de um aplicativo.Net.

Em contraste, compiladores não.Net, como VB6, C e C++, compilam seu código de alto nível diretamente no código de máquina da plataforma de destino (sistema operacional e CPU). O executável ou conjunto de código resultante está, portanto, vinculado à plataforma da máquina de destino do compilador. Isso também é conhecido como código não gerenciado ou nativo. Embora arquitetonicamente diferente, é possível usar código de assemblies, especialmente DLLs desenvolvidas em código nativo em um aplicativo gerenciado.Net, por meio de um recurso conhecido como Interop Marshalling (Platform Invoke). Exemplos disso serão o uso de DLLs nativas do sistema operacional Windows ou bibliotecas externas, como código escrito em C++, sendo referenciado em um aplicativo.Net gerenciado para habilitar algumas funcionalidades de baixo nível do sistema operacional. Nesse caso, o próprio .Net pode ser considerado um invólucro seguro para as DLLs nativas das quais o sistema operacional Windows depende e muitas das quais são, na verdade, escritas em C++.

O que é uma montagem do.Net?

A Microsoft descreve os assemblies do.Net como uma única unidade de implantação. O que isso significa é que uma montagem é uma coleção de vários tipos de código e arquivos associados que foram compilados (montados) em alguma forma que pode ser executada em qualquer plataforma de destino do.Net compatível. A execução é feita pelo Common Language Runtime do.Net. Exemplos de assemblies no sistema operacional Windows são arquivos executáveis (.exe) e arquivos de biblioteca de classes ou biblioteca de vínculo dinâmico (.dll).  

Um aprofundamento na imagem de código de exemplo abaixo mostra a montagem executável em C# à esquerda e outro código de montagem de DLL em C# (também conhecido como biblioteca de classes) à direita. O código executável faz referência ao arquivo DLL e, em seguida, chama um método (função) específico do código DLL durante a execução. Essas referências e chamadas foram destacadas na imagem abaixo. Explicaremos os detalhes de ambas as partes do código posteriormente neste artigo. Também mostraremos como essa combinação pode ser usada para fins maliciosos nesta série.

No exemplo subsequente, o arquivo DLL é referenciado manualmente no código executável. Isso significa que a DLL e as informações relacionadas sobre seus metadados, bem como o código (composto por módulos, classes e métodos), são referenciadas durante o tempo de compilação do código executável.

Como uma biblioteca compartilhada, o código DLL não pode ser executado sozinho diretamente. Do ponto de vista do código, isso ocorre porque as DLLs não têm uma função de ponto de entrada principal para serem executadas e, portanto, não podem ser executadas como código autônomo da mesma forma que um código executável (.exe) está configurado para fazer. Como exemplo, a mensagem de erro abaixo mostra as consequências de tentar executar uma biblioteca de classes ou arquivo DLL diretamente de um compilador.

O código executável, por outro lado, terá uma função ou método de ponto de entrada principal onde a execução começa, mas uma DLL realmente não precisa de uma função de ponto de entrada principal, pois é basicamente uma biblioteca de blocos de código referenciados por outros assemblies.

Uma vez referenciado, o código específico no arquivo DLL que é de interesse pode ser chamado para execução. Conforme mostrado no artigo anterior, os exemplos de código (EXE e DLL) abaixo reiteram esse ponto.  

O aplicativo executável é executado e chama o código da DLL referenciada para produzir a saída mostrada na imagem a seguir.

Esse programa simples mostra como os assemblies do.Net, como EXEs e DLLs, podem ser usados juntos.

O código DLL mencionado acima tem um método (função) que usa dois parâmetros por entrada — nome e idade — e exibe uma mensagem de saudação usando essas informações. O código executável, por outro lado, executa um código que aceita detalhes de entrada do usuário sobre nome e idade na linha de comando e, em seguida, passa essas informações para o método DLL como argumentos ou entradas. A mensagem do código DLL é então exibida de volta na tela do console usando as informações que o aplicativo EXE coletou do usuário.

Analisando assemblies .Net

Aexecução de uma análise estática no executável mostra as várias referências de DLLs e outros componentes importados para execução. Além de nossa própria DLL personalizada, o conjunto executável também importa DLLs adicionais associadas ao próprio .Net, como mscorlib, que é uma DLL que contém código base (classes, tipos etc.) e é algo que nosso programa precisa para funcionar sem problemas.

Em nosso ambiente de desenvolvimento de código Visual Studio, podemos confirmar o uso de mscorlib  rastreando suas origens em um dos tipos de dados (nesse caso, string de System.String em .Net). Isso revela o conjunto de domínio.Net embutido de onde esse tipo se origina, que é mscorlib, conforme mostrado abaixo.

String é um tipo de dados em termos de programação em que o texto que o usuário insere e depois é exibido novamente é armazenado. Também podemos ver em nossa análise estática a DLL chamada “DLL_DontNet_Assembly”. Essa é nossa DLL personalizada que contém o método “displayMsgMethod”, que mostra uma mensagem ao usuário depois de inserir seus detalhes.

Em nosso exemplo, referenciamos e carregamos nossa DLL personalizada manualmente durante a compilação de todo o nosso código antes de o programa começar a ser executado. Também é possível referenciar uma DLL durante a execução de um executável. Isso pode ser especialmente útil nos casos em que talvez não tenhamos acesso à DLL desejada durante a compilação do nosso código. Esse processo é conhecido como reflexão e permite examinar um assembly.Net (metadados e atributos) e também usar o código (módulos, classes, métodos e propriedades) contido nele durante o tempo de execução do nosso programa. Essa técnica também pode ser ajustada para fins maliciosos no que é conhecido como ataques de injeção reflexiva de DLL.

Os assemblies.NET (executáveis e bibliotecas de classes) também consistem em um arquivo manifesto que contém metadados sobre a montagem e o código da linguagem intermediária (IL) que, juntos, permitem que o Common Language Runtime execute a montagem em qualquer plataforma compatível que possa executar.Net. A imagem abaixo mostra as instruções de montagem IL e a estrutura de manifesto das duas montagens — EXE e DLL. O arquivo de manifesto contém os metadados sobre a montagem do.Net, como número da versão, descrição etc.

Agora devemos ter uma compreensão fundamental da estrutura do software.Net, seus conjuntos associados e como eles podem interagir entre si.

No próximo artigo, colocaremos as técnicas e os recursos que discutimos e aprendemos até agora em um único executável de ransomware malicioso.

Saiba mais sobre como a segmentação Zero Trust da Illumio pode ajudar você a conter violações de ransomware.

Tópicos relacionados

No items found.

Artigos relacionados

Estudo sobre o custo global do ransomware: o que os números nos dizem
Ransomware Containment

Estudo sobre o custo global do ransomware: o que os números nos dizem

Saiba como os atacantes estão migrando para a disrupção operacional, por que a prevenção não é suficiente e como o Zero Trust e a microssegmentação contêm o impacto do ransomware.

Por que os firewalls não são suficientes para a contenção de ransomware
Ransomware Containment

Por que os firewalls não são suficientes para a contenção de ransomware

Descubra os motivos pelos quais os firewalls são muito lentos para acompanhar as ameaças e por que a microssegmentação é fundamental para a contenção do ransomware.

Como interromper os ataques do Clop Ransomware com o Illumio
Ransomware Containment

Como interromper os ataques do Clop Ransomware com o Illumio

Descubra como a variante de ransomware Clop opera e como a Illumio pode ajudar sua organização a conter o ataque com microssegmentação.

Desmistificando técnicas de ransomware usando assemblies.Net: 5 técnicas principais
Ransomware Containment

Desmistificando técnicas de ransomware usando assemblies.Net: 5 técnicas principais

Aprenda sobre 5 técnicas de ransomware usando a estrutura de software.Net.

Como conter ataques de ransomware LockBit com o Illumio
Ransomware Containment

Como conter ataques de ransomware LockBit com o Illumio

Descubra como o ransomware LockBit opera e como a Illumio Zero Trust Segmentation conteve um ataque de ransomware LockBit no verão de 2022.

Suponha que a violação seja feita.
Minimize o impacto.
Aumente a resiliência.

Pronto para saber mais sobre a segmentação Zero Trust?