Patch AMSI

Bom, neste post estarei mostrando como realizar uma técnica para fazer um patch na amsi.dll do Windows10.


O que é a AMSI.DLL

Antimalware Scan Interface é uma biblioteca do Windows que fornece uma interface padrão para permitir que aplicativos e serviços solicitem verificações antimalware em conteúdo carregado. Um exemplo comum de uso da amsi.dll é na utilização do PowerShell para executar scripts. Quando um script é executado, a AMSI pode escanear o conteúdo do script para detectar e bloquear comandos potencialmente perigosos antes que eles sejam executados. Abaixo, uma imagem para melhor entendimento:


Para que uma aplicação envie amostras ao AMSI, ela precisa carregar amsi.dll em seu espaço de endereços e chamar um conjunto de APIs do AMSI exportadas por essa DLL.

Se usarmos o ApiMonitor para fazer Hook no PowerShell e observar quais APIs ele chama.

Veremos que as principais são:

Encerra a sessão que foi aberta por AmsiOpenSession

Inicializa a API do AMSI.

Envia ao provedor antimalware uma notificação sobre alguma operação arbitrária.

Abre uma sessão na qual vários pedidos de verificação podem ser associados.

Determina se o resultado de uma verificação indica que o conteúdo deve ser bloqueado.

Analisa um buffer de memória cheio de conteúdo, procurando por malware.

Analisa uma string à procura de malware.

Remove a instância da API AMSI que foi aberta originalmente por AmsiInitialize.

Esta é a arquitetura do AMSI fornecida pela Microsoft.

https://learn.microsoft.com/en-us/windows/win32/amsi/images/amsi7archi.jpg

A interface AMSI do Windows é aberta. Isso significa que qualquer aplicativo pode chamá-la, qualquer mecanismo antivírus registrado pode processar o conteúdo enviado a ela.

O antivírus escaneia todos os assemblies. Nas versões anteriores do .NET Framework, o runtime usava o Windows Defender ou antivírus de terceiros para escanear todos os assemblies carregados a partir do disco. Porém, assemblies carregados a partir de outras fontes (por exemplo, usando o método Assembly.Load()), que podem conter malware não detectado, não eram escaneados.

A partir do .NET 4.8, o AMSI se tornou parte do framework, por isso, quando um assembly é carregado, a AMSI.DLL também é carregada.

O AMSI é chamado direta ou indiretamente no sistema Windows, distribuído principalmente nos seguintes programas:

1. Controle de Conta de Usuário (UAC)%windir%\System32\consent.exe 2. PowerShell (scripts, uso interativo e execução dinâmica)System.Management.Automation.dll 3. Windows Script Hostwscript.exe ou cscript.exe 4. JavaScript / VBScript%windir%\System32\jscript.dll , %windir%\System32\vbscript.dll 5. Office VBA MacrosVBE7.dll 6. .NET Assemblyclr.dll 7. WMI%windir%\System32\wbem\fastprox.dll


Ou seja se abrirmos um PowerShell localmente e observarmos os módulos carregados, veremos que ele carrega automaticamente o amsi.dll.

Para contornarmos isso, podemos fazer com que o AMSI execute muitas verificações de validação antes de atingir o código crítico de "verificação" do AMSI. Podemos debugar a AMSI.dll no ida64.exe. Temos apenas que encontrar o ponto crítico. Abaixo, uma imagem para melhor entendimento:

Para isso podemos simplesmente alternar um dos JZ/JE para JNZ/JNE. Para entender melhor: 0x74 = JZ/JE e 0x75 = JNZ/JNE. O código para realizar o patch está abaixo:

Abaixo está uma explicação mais detalhada para entender o código:

Obter o Endereço da Função "AmsiScanBuffer"

Começamos pegando o endereço da função AmsiScanBuffer carregada na DLL amsi.dll:

Calcular o Endereço Final

Somamos ? ao endereço de AmsiScanBuffer para obter o endereço final, que contém a instrução JZ/JE:

Alterar a Permissão de Memória

Alteramos a permissão de memória do endereço final para permitir escrita. Note que 0x40 é PAGE_EXECUTE_READWRITE. Em seguida exibimos a permissão de memória anterior:

Aplicar o Patch

Mudamos os primeiros bytes do endereço final para 0x75, que altera a instrução para JNZ/JNE:

1

Primeiro passo

2

Segundo passo

Aqui apenas definimos um BreakPoint para acharmos o endereço do AmsiScanBuffer. Depois pressionamos Ctrl + B, colamos o hex que copiamos para então encontrar o endereço do JZ/JE que precisamos copiar:

3

Terçeiro passo

Aqui fazemos um cálculo simples: Endereço do "AmsiScanBuffer" + Endereço do "JZ/JE" que queremos modificar para JNZ/JNE:

4

Quarto passo

Agora que sabemos quanto temos que adicionar (0x95) ao endereço do AmsiScanBuffer para chegar no endereço final JZ/JE, apenas o adicionamos no código:


Entendendo o processo

Agora que terminamos de achar tudo que precisávamos, vamos executar o código no próprio PowerShell. Ao executar nosso código, ele fará o seguinte: obterá o endereço de AmsiScanBuffer, adicionará 0x95 ao endereço para chegar ao endereço final JZ/JE, alterará as permissões para 0x40 (que corresponde a PAGE_EXECUTE_READWRITE), mudará o byte de 0x74 para 0x75 (alterando JZ/JE para JNZ/JNE), e restaurará as permissões de memória originais para garantir que nosso patch seja realizado com sucesso.


Realizando o patch:

Last updated