
Freeze é um kit de ferramentas de payload para contornar EDRs usando processos suspensos, chamadas de sistema diretas e métodos alternativos de execução.
Para ver a versão mais recente do Freeze ou para enviar um problema, consulte https://github.com/Tylous/Freeze.
Se quiser saber mais sobre as técnicas utilizadas neste framework, dê uma olhada no SourceZero Blog
Freeze é uma ferramenta de criação de payloads usada para contornar controles de segurança EDR e executar shellcode de forma furtiva. O Freeze utiliza múltiplas técnicas não apenas para remover hooks de EDR em Userland, mas também para executar shellcode de modo a contornar outros controles de monitoramento de endpoints.
Quando um processo é criado, Ntdll.dll é a primeira DLL a ser carregada. Isso acontece antes de qualquer DLL de EDR ser carregada. Isso significa que há um certo atraso antes que um EDR possa ser carregado e começar a fazer hooking e modificar a montagem das DLLs do sistema. Ao observar as syscalls do Windows em Ntdll.dll, podemos ver que nada está sendo hookado ainda. Se criarmos um processo em estado suspenso (um que está congelado no tempo), podemos ver que nenhuma outra DLL é carregada, exceto Ntdll.dll. Você também pode ver que nenhuma DLL de EDR é carregada, o que significa que as syscalls localizadas em Ntdll.dll não estão modificadas.
Para usar este processo suspenso limpo para remover hooks do loader Freeze, precisamos de uma maneira de encontrar e ler programaticamente a memória do processo suspenso limpo. É aqui que entra a aleatorização do layout do espaço de endereço (ASLR). ASLR é um mecanismo de segurança para prevenir vulnerabilidades baseadas em corrupção de memória da pilha. O ASLR randomiza o espaço de endereço dentro de um processo, para garantir que todos os objetos mapeados em memória, a pilha, o heap e o próprio programa executável sejam únicos. Agora, é aqui que fica interessante, porque embora o ASLR funcione, ele não funciona para código independente de posição, como DLLs. O que acontece com DLLs (especificamente DLLs de sistema conhecidas) é que o espaço de endereço é randomizado uma vez na inicialização. Isso significa que não precisamos enumerar informações de um processo remoto para encontrar o endereço base de sua ntdll.dll, porque ele é o mesmo em todos os processos, incluindo o que controlamos. Como o endereço de cada DLL está no mesmo lugar por inicialização, podemos obter essas informações do nosso próprio processo e nunca precisamos enumerar o processo suspenso para encontrar o endereço.
Com essas informações, podemos usar a API ReadProcessMemory para ler a memória de um processo. Esta chamada de API é comumente associada à leitura do LSASS como parte de qualquer ataque baseado em credenciais; no entanto, por si só, não é inerentemente maliciosa, especialmente se estivermos apenas lendo uma seção arbitrária de memória. A única vez que ReadProcessMemory será sinalizada como parte de algo suspeito é se você estiver lendo algo que não deveria (como o conteúdo do LSASS). Os produtos EDR nunca devem sinalizar o fato de que ReadProcessMemory foi chamado, pois há usos operacionais legítimos para essa função e resultaria em muitos falsos positivos.
Podemos dar um passo adiante lendo apenas uma seção do Ntdll.dll onde todas as syscalls estão armazenadas - sua seção .text, em vez de ler toda a DLL.
Combinando esses elementos, podemos obter programaticamente uma cópia da seção .text do Ntdll.dll para sobrescrever nossa seção .text hookada existente antes de executar o shellcode.
O ETW utiliza syscalls internas para gerar essa telemetria. Como o ETW também é um recurso nativo do Windows, os produtos de segurança não precisam "hookar" as syscalls do ETW para acessar as informações. Como resultado, para prevenir o ETW, o Freeze aplica patch em várias syscalls do ETW, zerando os registradores e retornando o fluxo de execução para a próxima instrução. O patching de ETW agora é padrão em todos os loaders.
Como apenas Ntdll.dll é restaurada, todas as chamadas subsequentes para executar shellcode precisam residir em Ntdll.dll. Usando Go (note que você pode fazer isso em outras linguagens, mas em Go é bastante fácil de implementar), podemos definir e chamar as syscalls NT necessárias para alocar, escrever e proteger o shellcode, efetivamente pulando as chamadas padrão localizadas em kernel32d.dll e Kernelbase.dll, pois estas podem ainda estar hookadas.
O Freeze foi desenvolvido em Golang.
Para instalar o Freeze, execute os seguintes comandos, ou use o binário compilado:
go build Freeze.go
___________
\_ _____/______ ____ ____ ________ ____
| __) \_ __ \_/ __ \_/ __ \\___ // __ \
| \ | | \/\ ___/\ ___/ / /\ ___/
\___ / |__| \___ >\___ >_____ \\___ >
\/ \/ \/ \/ \/
(@Tyl0us)
Soon they will learn that revenge is a dish... best served COLD...
Usage of ./Freeze:
-I string
Path to the raw 64-bit shellcode.
-O string
Name of output file (e.g. loader.exe or loader.dll). Depending on what file extension defined will determine if Freeze makes a dll or exe.
-console
Only for Binary Payloads - Generates verbose console information when the payload is executed. This will disable the hidden window feature.
-encrypt
Encrypts the shellcode using AES 256 encryption
-export string
For DLL Loaders Only - Specify a specific Export function for a loader to have.
-process string
The name of process to spawn. This process has to exist in C:\Windows\System32\. Example 'notepad.exe' (default "notepad.exe")
-sandbox
Enables sandbox evasion by checking:
Is Endpoint joined to a domain?
Does the Endpoint have more than 2 CPUs?
Does the Endpoint have more than 4 gigs of RAM?
-sha256
Provides the SHA256 value of the loaders (This is useful for tracking)
O Freeze pode gerar tanto um arquivo .exe quanto um .dll. Para especificar isso, certifique-se de que a opção de linha de comando -O termine com .exe para binários ou .dll para DLLs. Nenhum outro tipo de arquivo é atualmente suportado. No caso de arquivos DLL, o Freeze também pode adicionar funcionalidade de exportação adicional. Para isso, use -export com o nome específico da função de exportação.
O Freeze utiliza uma técnica de primeiro criar o processo e depois movê-lo para segundo plano. Isso faz duas coisas: primeiro, ajuda a manter o processo oculto e, segundo, evita ser detectado por qualquer produto EDR. Iniciar um processo imediatamente em segundo plano pode ser muito suspeito e um indicador de maliciosidade. O Freeze faz isso chamando as funções do Windows ‘GetConsoleWindow’ e ‘ShowWindow’ após o processo ser criado e os hooks do EDR serem carregados, e então altera os atributos da janela para oculto. O Freeze utiliza essas APIs em vez de usar o tradicional -ldflags -H=windowsgui, pois isso é altamente assinado e classificado na maioria dos produtos de segurança como um Indicador de Comprometimento.
Se a opção de linha de comando -console for selecionada, o Freeze não ocultará o processo em segundo plano. Em vez disso, o Freeze adicionará várias mensagens de depuração exibindo o que o loader está fazendo.
Agradecimentos especiais a aahmad097 por desenvolver AlternativeShellcodeExec
Agradecimentos especiais a mvdan por desenvolver Garble