Simple EDR

Bom, neste post vou criar uma ideia para o começo de um EDR/AV básico que provavelmente eu nunca vou terminar. A ideia principal agora é criar uma DLL simples que utilize a MinHook para conseguir realizar um hook em APIs.


Como vai funcionar?

Primeiro vamos fazer o código principal que será responsável por injetar nossa dll no executavel que queremos monitorar. O principal intuito vai ser monitorar as APIs utilizadas por loaders. O intuito é apenas monitorar as chamadas de API da kernel32. Ou seja, se o programa utilizar técnicas como syscalls indiretas ou diretas, nosso EDR/AV não terá como detectar o loader.


Código que obtém o ID do processo com o nome fornecido:

DWORD GetProcessIdByName(const wstring& processName) {
    DWORD processId = 0;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 processEntry = { sizeof(PROCESSENTRY32) };
    if (Process32First(snapshot, &processEntry)) {
        do {
            if (processName == processEntry.szExeFile) {
                processId = processEntry.th32ProcessID;
                break;
            }
        } while (Process32Next(snapshot, &processEntry));
    }
    CloseHandle(snapshot);
    return processId;
}

Código para Injeção da DLL:

  1. Abertura do Processo Alvo: Utiliza a API OpenProcess para obter um identificador para o processo alvo, especificado pelo processId.

  2. Localização da Função LoadLibraryW: Obtém o endereço da função LoadLibraryW na biblioteca kernel32.dll que será utilizada para carregar a DLL no processo alvo.

  3. Alocação de Memória no Processo Alvo: Usa VirtualAllocEx para alocar memória no processo alvo para armazenar o caminho da DLL.

  4. Escrita do Caminho da DLL na Memória do Processo Alvo: Com WriteProcessMemory.

  5. Criação de um Novo Thread: Cria um novo thread no processo alvo com CreateRemoteThread, que executa a função LoadLibraryW para carregar a DLL.

  6. Aguarda a Conclusão da Injeção: Utiliza WaitForSingleObject para aguardar o término do thread.

  7. Limpeza e Fechamento: Após a execução, libera a memória alocada com VirtualFreeEx e fecha o handle do processo e do thread com CloseHandle.


NamedPipeServer para Comunicação:

O NamedPipeServer é basicamente responsável por criar um servidor de Named Pipe que escuta por conexões e processa mensagens recebidas.

Explicação do Código:

  1. Criação do Named Pipe: Utiliza CreateNamedPipe para criar um pipe nomeado (MyPipe) que aceita conexões. Configurado para acesso de entrada (PIPE_ACCESS_INBOUND), com suporte a mensagens e leitura no modo de mensagens.

  2. Conexão com o Pipe: ConnectNamedPipe aguarda a conexão de um cliente ao pipe. Se falhar, o erro é exibido e o pipe é fechado.

  3. Leitura de Dados: Usa ReadFile para ler os dados do pipe. Se ocorrer um erro de leitura ou o pipe for quebrado (ERROR_BROKEN_PIPE), o loop de leitura é interrompido. Se a leitura for bem-sucedida, os dados são exibidos no console.

  4. Fechamento e Repetição: Após a leitura ou se a conexão falhar, o handle do pipe é fechado. O servidor continua a executar e criar novos pipes em um loop infinito.


Inclusão da MinHook:

Este trecho de código inclui a biblioteca MinHook, uma popular biblioteca de hooking para a API do Windows.


Funções:

Aqui definidos tipos de função para algumas das APIs do Windows que serão hooked. Cada tipo de função corresponde a uma função da API do Windows que será substituída por uma função personalizada para monitorar ou modificar seu comportamento.


Ponteiros para as funções originais:

Essa parte define ponteiros para as funções originais da API do Windows que serão substituídas pelos hooks. Esses ponteiros são necessários para que o código possa chamar as funções originais após interceptá-las.


Enviar Mensagem para o Named Pipe:

Essa parte é responsável por enviar mensagens para o nosso Named Pipe.


Código Responsavel por terminar o processo:

Essa parte do código exibe uma caixa de mensagem de alerta e em seguida encerra o processo atual. essa função será usada para bloquear a execução do processo caso ele faça uso de uma API que consideramos maliciosa.


Função para o hook OpenProcess:

Esta parte é uma função de um hook para a função OpenProcess. Ela vai interceptar as chamadas para a API OpenProcess, então vai enviar uma mensagem com o ID do processo alvo para nosso Named Pipe, e depois irá chamar a função original do OpenProcess.


Função para o hook WriteProcessMemory:

Essa é outra função de hook mas para a API WriteProcessMemory. essa parte registra detalhes sobre o endereço de memória que está sendo modificado e envia para o nosso Named Pipe, e depois chama a função original WriteProcessMemory para garantir que a operação de escrita ocorra normalmente.


Função para o hook VirtualAllocEx:


Função para o hook CreateRemoteThread:

Essa é outra função de hook, mas para a API CreateRemoteThread. Diferente das outras, essa irá chamar a função BlockExecution que irá barrar a execução do programa e em seguida, chamará a função original CreateRemoteThread.


Função para Implementar o hook:

Agora nossa função SetupHook vai configurar todos os hooks necessários utilizando a biblioteca MinHook. então ela irá criar os hooks para VirtualAllocEx, CreateRemoteThread, OpenProcess, e WriteProcessMemory, e finalmente habilita todos os hooks criados. Se houver falhas em qualquer uma dessas operações, uma mensagem de erro é enviada para o Named Pipe.


Iniciar thread após a dll ser carregada:

Agora por fim a função DllMain é o ponto de entrada para a DLL. Quando a DLL é carregada DLL_PROCESS_ATTACH, ela desativa as chamadas de thread para a DLL e configura os hooks. Quando a DLL é descarregada DLL_PROCESS_DETACH, ela desativa todos os hooks e desinicializa a biblioteca MinHook.


Entendendo o que fizemos:

O código que fizemos implementa um sistema de hooking para monitorar e controlar chamadas para funções críticas da API do Windows, como OpenProcess, WriteProcessMemory, VirtualAllocEx, e CreateRemoteThread. O uso de hooks nos permite interceptar essas funções para detectar e bloquear ações que possam indicar comportamento malicioso. e enviar mensagens de alerta sobre o uso dessas APIs para o nosso "painel".


Prova de Conceito:

Last updated