Coisas Aleatórias


Posted Sep 13, 2024. 13 min read


Neste post bem aleatório, vou mostrar algumas coisas que devemos saber ou conhecer para realizar uma evasão de antivírus (AV).
Se você é iniciante e quer conhecer algumas coisas este conteúdo é para você.


⚠️ As informações que você encontrar neste post, técnicas, códigos, provas de conceito ou qualquer outra coisa são estritamente para fins educacionais.

Começo de tudo!

Se você é iniciante e decidiu procurar um mapa mental para entender os processos necessários para contornar antivírus, pode se deparar com a seguinte situação:

BypassAV


Então, você olha para isso e fica de boca aberta :O
Mas calma, amigo! Não se preocupe tanto assim. Esses especialistas nerds querem tudo perfeito, eles usam siglas para fazer você questionar sua própria existência.
Obs: Não estou julgando o mapa apresentado pelo matro7sh, até recomendo que de uma olhada nele, eu apenas estou dando um exemplo de uma situação que poderia ocorrer com um iniciante.
Então, você tem que entender tudo que está nesse mapa mental e testar tudo? A resposta curta é não, mas, se você tiver bastante tempo livre, eu recomendaria fazer isso.

Principal Problema com iniciantes

Bom, o principal problema que iniciantes enfrentam é achar que você precisa criar algo totalmente novo para contornar alguns antivírus. É como se eles não conseguissem entender que, muitas vezes, não é necessário criar algo do zero, apenas modificar pequenas partes do código existente já pode ser suficiente para torná-lo indetectável novamente.
Ou seja:

THANKS

Contornar é fácil!

Bom, eu não sou um anjo que vai pegar na sua mão e fazer você sair daqui contornando qualquer antivírus. Pode até parecer que estou ironizando os antivírus ao dizer que é fácil contorná-los, mas isso pode ser porque já faço isso há um tempo. Para um iniciante, pode ser complexo entender o que deve ser modificado no código.

Porque ficou detectável?

Postaram um projeto que conseguia contornar alguns antivírus, e em menos de dois dias já estava sendo detectado. Por que isso aconteceu?
A resposta para isso é o envio de amostras.

Caso você não saiba, o próprio Windows vem com essa opção habilitada por padrão.
Basicamente, ele realiza o envio de amostras de arquivos suspeitos que estão presentes no seu computador para serviços de segurança, como o Windows Defender. Isso permite que os antivírus atualizem suas assinaturas e detectem novos malwares com base nas amostras enviadas:

AMOSTRA


Além disso, existem plataformas como o VirusTotal. que quando você faz o upload de um arquivo para o VirusTotal, ele é analisado por múltiplos antivírus e motores de detecção. Se o arquivo é identificado como malicioso por algum dos motores, essa informação pode ser compartilhada com os fornecedores de antivírus, atualizando suas bases de dados e aumentando a probabilidade de detecção de novas versões do mesmo malware.
Portanto, mesmo que você consiga criar um código que contorne antivírus no início, o envio de amostras e a análise por múltiplas ferramentas de segurança pode rapidamente levar à detecção e à atualização das assinaturas antivírus.

Evitar o envio de amostra!

Bom, para que seu arquivo consiga permanecer indetectável por mais tempo, você vai precisar aprender a contornar máquinas virtuais. Esse processo pode ser bastante desafiador e tedioso, mas é essencial. Após criar um malware indetectável, fazer com que ele consiga contornar máquinas virtuais. caso contrário, você estará basicamente jogando seu trabalho no "lixo".

Técnicas de Detecção de Carregadores

Existem três técnicas principais para detecção de carregadores:

  • Verificação de Arquivos:
    Verificação de assinaturas (por exemplo, usando regras YARA) para arquivos.
  • Varredura de Memória:
    Varredura de assinaturas (por exemplo, usando regras YARA) para a memória de processo.
  • Telemetria/Comportamento:
    Análise das ações executadas pelo processo, principalmente via sistema operacional.

A maioria dos implantes de arquivo .exe gerados prontos para uso por frameworks C2 são assinados e, portanto, não são úteis. Portanto, o primeiro passo é ofuscar o código, o que é difícil. Ou usar um carregador, que carrega o implante como carga útil, Na maioria das vezes, essa técnica usa uma shellcode gerado pelo C2 (alternativa, a DLL gerada pode ser usada com um carregador de DLL ou o EXE convertendo-o em Shellcode ou DLL). A vantagem é que a carga útil pode ser criptografada, então a única coisa que precisa ser ofuscada da varredura de assinatura de arquivo AV é o próprio carregador real.
Em vez de escanear um arquivo, o AV também pode escanear a memória dos processos. Isso derrota os carregadores, pois o código de carga útil precisa ser descriptografado na memória para ser executado. Para evitar a detecção na memória, o processo precisa criptografar suas regiões de memória quando estiver dormindo. Então, no momento em que o AV escaneia o processo, nada suspeito deve estar na memória. O escaneamento de memória é uma operação intensiva em desempenho e só é feito se o AV achar que vale a pena. Isso se baseia na telemetria coletada ou em intervalos regulares.
A maioria dos casos de uso de detecção depende de telemetria: Chamadas de função importantes no Windows geram eventos que são processados, correlacionados e analisados ​​pelo AV. Como alteração de permissões de regiões de memória, criação de processos e threads, cópia de memória e similares.
Por exemplo, se usarmos um carregador para ignorar o AV e simplesmente alocar uma região de memória para nosso shellcode, não geraremos muita telemetria para o AV. Mas o payload será detectável por um scanner de memória. Se introduzirmos criptografia de memória para ignorar o scanner de memória, então geraremos mais telemetria, que por sua vez pode ser usada para detectar a criptografia de memória.

Técnicas de detecção

Quando um arquivo está sendo gravado no disco, ele será escaneado pelo antivírus (AV). O AV possui um banco de dados de assinaturas com malwares conhecidos (como regras do Yara). Eventos de gravação de arquivos são gerados pelo Sistema Operacional (SO) e entregues ao AV através de AMSI ou callbacks do kernel / ETW. O AV então escaneará os arquivos recém-criados.
ETW (Event Tracing for Windows): Um mecanismo de rastreamento de eventos do Windows que permite ao sistema e aos aplicativos gerar eventos para análise e depuração. Por exemplo, quando um arquivo é criado ou modificado, o ETW pode gerar um evento que informa ao antivírus que uma nova operação de arquivo ocorreu, permitindo que ele faça a varredura.
AMSI (Antimalware Scan Interface): Uma interface fornecida pelo Windows para permitir que aplicativos e scripts se integrem com software antivírus para realizar varreduras de malware. Por exemplo, se um script PowerShell tentar baixar e executar um arquivo, o AMSI pode interceptar essa ação e solicitar ao antivírus que faça uma varredura no arquivo antes da execução.
A varredura de assinatura é baseada no conteúdo estático do arquivo. Isso significa que o antivírus analisa os dados do arquivo, incluindo seus cabeçalhos e seções, antes de ser executado.
Cabeçalhos PE (Portable Executable): São estruturas de dados no arquivo que fornecem informações sobre a organização do arquivo executável. Por exemplo, um antivírus pode analisar os cabeçalhos PE para verificar se há algo suspeito, como strings de código malicioso ou seções incomuns.


PE


Conteúdo das Seções PE: As seções de um arquivo PE podem conter código executável, dados e recursos. O antivírus examina essas seções para procurar padrões conhecidos de malware. Por exemplo, pode verificar se há seções com tamanho anormalmente grande ou com padrões de bytes que correspondem a assinaturas de malware conhecidas.

Isso acontece antes que o EXE seja executado. Após uma detecção positiva, o arquivo será removido antes da execução para evitar que o malware seja ativado.

Um exemplo de detecção:

Vou utilizar o projeto yara para detectar um binario gerado pelo donut, utilizando as regras do elastic, lembrando que o Yara pode escanear executáveis, binários e processos em execução etc:


rule Windows_Trojan_Donutloader_f40e3759 {
    meta:
        author = "Elastic Security"
        id = "f40e3759-2531-4e21-946a-fb55104814c0"
        fingerprint = "a6b9ccd69d871de081759feca580b034e3c5cec788dd5b3d3db033a5499735b5"
        creation_date = "2021-09-15"
        last_modified = "2022-01-13"
        threat_name = "Windows.Trojan.Donutloader"
        severity = 100
        arch_context = "x86"
        scan_context = "file, memory"
        license = "Elastic License v2"
        os = "windows"
    strings:
        $x64 = { 06 B8 03 40 00 80 C3 4C 8B 49 10 49 8B 81 30 08 00 00 }
        $x86 = { 04 75 EE 89 31 F0 FF 46 04 33 C0 EB 08 83 21 00 B8 02 }
    condition:
        any of them
}

Para realizar essa análise, vamos executar o Yara com o primeiro argumento sendo o local onde está nossa regra Yara, que, neste caso, deixei no mesmo diretório, e o segundo argumento sendo o arquivo no qual queremos aplicar a regra.


Usage: yara [OPTION]... [NAMESPACE:]RULES_FILE... FILE | DIR | PID
PS C:\yara: .\yara64.exe donut.yar loader.bin
Windows_Trojan_Donutloader_f40e3759 loader.bin (Detectou!)

Scanners de memória

Scanners de memória típicos são:
PE-sieve e o Moneta que eu já mostrei o uso no post: Malware-Analysis-2.
Os scanners de memória servem basicamente para ajudar a detectar algum tipo de malware. Obviamente, não são ferramentas utilizadas por leigos, mas têm como objetivo realizar uma análise do processo escaneado e identificar shellcodes, hooks e patches realizados na memória do processo. Caso ainda não tenha testado esses projetos, recomendo fortemente que experimente.


Para conseguir contornar esses scanners de memória pode ser utilizado:
SWAPPALA / Gargoyle / Ekko / Cronos / Foliage

Caso já for experiente recomendo fortemente que teste esses projetos e leia o artigo escrito pelo Bakki:
Naively bypassing new memory scanning POCs e o artigo escrito pelo oldboy21 Timer Callbacks Spoofing to Improve your SLEAP and SWAPPALA Untold, Caso contrário, deixe isso para depois, pois pode ser bastante complexo para um iniciante.
Mas você pode abordar o uso de algumas técnicas de sono utilizando o Havoc Framework, já que ele tem técnicas de ofuscação do sono.

Análise de pilha de chamadas

Quando um processo chama uma função do Windows, é possível descobrir as funções pai que levam a essa chamada. Isso é chamado de callstack.


STACK


Um exemplo de como funciona uma análise de pilha de chamadas:


STACK


Falsificação de pilha de chamadas:
ThreadStackSpoofer / VulcanRaven / Máscara de pilha de chamadas / An Introduction into Stack Spoofing

O que poderia desencadear uma varredura de memória?

Lembrando que isso não é uma regra, sempre é bom considerar que diferentes antivírus e EDRs podem ter comportamentos variados para essas operações.


			      ┌──────────────────────────────────────────────────────────────────────────────────────┐ 
			      |   O que             | Aciona a varredura?  |                 Notas                   |
			      |---------------------|----------------------|-----------------------------------------|
			      | VirtualAlloc()      | Não?                 | Muito comum, exceto quando RWX          |
			      | WriteProcessMemory()| Talvez               | Muito comum                             |
			      | VirtualProtect()    | Não?                 | RWX ou RW->RX podem ser gatilhos        |
			      | CreateRemoteThread()| Sim                  | Deve acionar a varredura de memória     |
			      └──────────────────────────────────────────────────────────────────────────────────────┘ 

VirtualAlloc() e WriteProcessMemory() são comumente chamadas. CreateRemoteThread() Não só é menos chamada, como também é um indicador mais claro de comportamento potencialmente malicioso.

Hooking

Um hook pode ser usado por um AV/EDR para monitorar e modificar chamadas de funções em APIs do sistema, como as fornecidas pela kernel32.dll. por exemplo um antivírus pode usar hooks para interceptar chamadas a funções como CreateFile ou ReadFile para detectar atividades suspeitas de malware, caso queira saber mais sobre recomendo que leia meu post: Creating-EDR-AV.


hooking


Caso queria entender melhor sobre como realizar unhooking leia meu post Unhooking-Windows-API.

Criação do seu próprio shellcode!

Criar seu próprio shellcode pode ser uma tarefa bastante difícil e complexa. No entanto, é algo a se considerar, especialmente quando falamos sobre acesso inicial, onde não precisamos de algo tão sofisticado. Abordei brevemente a criação de shellcode no post Writing and Compiling Shellcode in C.
Se você deseja explorar mais sobre o assunto:

From a C project through assembly to shellcode
Leveraging from PE parsing technique to write x86 shellcode
introduction-to-windows-shellcode-development-part1/
Introduction to Windows shellcode development – Part 2
Introdução ao desenvolvimento de shellcode do Windows – Parte 3
Windows x64 Shellcode Development
Basics of Windows shellcode writing
Windows shellcoding - part 1. Simple example
Windows shellcoding - part 2. Find kernel32 address
Windows shellcoding - part 3. PE file format

Indirect syscalls

A técnica de syscall indireta é mais ou menos uma evolução da técnica de syscall direta. Comparadas as syscalls diretas, as syscalls indiretas podem resolver os seguintes problemas de evasão de AV/EDR.

Primeiro, a execução do comando syscall ocorre na memória do ntdll.dll e, portanto, é legítima para o AV/EDR.
Por outro lado, a execução da instrução return ocorre na memória do ntdll.dll e aponta da memória do ntdll.dll para a memória do assembly de syscall indireta.


DETECT


Chamada de sistema direta: basta fazer a chamada de sistema você mesmo (com o número de chamada de sistema correto).
Chamada de sistema indireta: Reutilize partes do hooked ntdll.dll, invoque a chamada de sistema, mas não o hook:


INDIRECT


Syscalls indiretas oferecem uma aparência mais legítima no contexto da pilha de chamadas de thread. Com syscalls indiretas, tanto a execução da syscall quanto a instrução de retorno ocorrem dentro da memória de ntdll.dll, que é o comportamento esperado em processos normais de aplicativos.
Ao substituir syscalls diretas por indiretas, a pilha de chamadas resultante imita um padrão de execução mais convencional. Isso pode ser útil para contornar sistemas AV/EDR que examinam a área de memória onde syscalls e seus retornos são executados.

Vários experimentos com diferentes EDRs mostraram que syscalls diretos ainda podem funcionar, mas também são cada vez mais detectados dependendo do EDR. Com base em IOCs no contexto de syscalls diretos, syscalls indiretos podem ser uma solução útil, pois resolvem os seguintes problemas em comparação

Resumo:

Primeiro, a execução do comando syscall ocorre na memória do ntdll.dll e, portanto, é legítima para o AV/EDR.
Por outro lado, a execução da declaração return ocorre dentro da memória de ntdll.dll e aponta da memória de ntdll.dll para a memória do assembly syscall indireto. Esse comportamento é pelo menos mais legítimo do que o comportamento com syscalls diretos, mas ainda pode levar a IOCs dependendo do AV/EDR, por exemplo, se o AV/EDR também verificar a pilha de chamadas.
Syscalls indiretas são uma melhoria em relação a syscalls diretas, mas têm suas limitações e também têm certos IOCs que agora são usados ​​por fornecedores de AV/EDR para gerar regras de detecção. Por exemplo, com syscalls indiretas é possível falsificar o endereço de retorno, o que coloca o endereço de memória do retorno subsequente no topo da pilha de chamadas e ignora a verificação de retorno do AV/EDR. No entanto, se um AV/EDR estiver usando ETW, ele pode verificar adicionalmente a própria pilha de chamadas para comportamento impróprio. Syscalls indiretas sozinhas não são mais suficientes para evasão de EDR no caso de um EDR também usar ETW, e você precisa dar uma olhada mais de perto na falsificação de pilha de chamadas. Um bom artigo sobre isso:
Hiding In PlainSight - Indirect Syscall is Dead! Long Live Custom Call Stacks. Part1
Hiding In PlainSight - Indirect Syscall is Dead! Long Live Custom Call Stacks. Part2