Vectored Overloading PE Injection

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Visão geral da técnica

Vectored Overloading é um Windows PE injection primitive que funde o clássico Module Overloading com Vectored Exception Handlers (VEHs) e hardware breakpoints. Em vez de patchar LoadLibrary ou escrever seu próprio loader, o adversário:

  1. Cria uma seção SEC_IMAGE respaldada por um DLL legítimo (por exemplo, wmp.dll).
  2. Sobrescreve a view mapeada com um PE malicioso totalmente realocado, mas mantém o objeto de seção apontando para a imagem benign no disco.
  3. Registra um VEH e programa os registradores de depuração para que toda chamada a NtOpenSection, NtMapViewOfSection, e opcionalmente NtClose gere um breakpoint em user-mode.
  4. Chama LoadLibrary("amsi.dll") (ou qualquer outro alvo benigno). Quando o loader do Windows invoca esses syscalls, o VEH pula a transição para o kernel e retorna os handles e endereços base da imagem maliciosa preparada.

Como o loader ainda acredita que mapeou o DLL solicitado, ferramentas que olham apenas para os arquivos de backing da seção veem wmp.dll mesmo que a memória agora contenha o payload do atacante. Enquanto isso, imports/callbacks TLS ainda são resolvidos pelo loader genuíno, reduzindo significativamente a quantidade de lógica customizada de parsing de PE que o adversário precisa manter.

Etapa 1 – Construir a seção disfarçada

  1. Create and map a section for the decoy DLL
NtCreateSection(&DecoySection, SECTION_ALL_ACCESS, NULL,
0, PAGE_READWRITE, SEC_IMAGE, L"\??\C:\\Windows\\System32\\wmp.dll");
NtMapViewOfSection(DecoySection, GetCurrentProcess(), &DecoyView, 0, 0,
NULL, &DecoySize, ViewShare, 0, PAGE_READWRITE);
  1. Copy the malicious PE into that view seção por seção, respeitando SizeOfRawData/VirtualSize e atualizando proteções depois (PAGE_EXECUTE_READ, PAGE_READWRITE, etc.).
  2. Apply relocations and resolve imports exatamente como um reflective loader faria. Como a view já está mapeada como SEC_IMAGE, alinhamentos de seção e guard pages coincidem com o que o loader do Windows espera depois.
  3. Normalize the PE header:
  • Se o payload for um EXE, defina IMAGE_FILE_HEADER.Characteristics |= IMAGE_FILE_DLL e zere o entry point para evitar que LdrpCallTlsInitializers salte para stubs específicos de EXE.
  • DLL payloads podem manter seus headers inalterados.

Neste ponto o processo possui uma view com capacidades RWX cujo objeto de backing ainda é wmp.dll, mas os bytes na memória estão sob controle do atacante.

Etapa 2 – Sequestrar o loader com VEHs

  1. Register a VEH and arm hardware breakpoints: programe Dr0 (ou outro registrador de depuração) com o endereço de ntdll!NtOpenSection e ajuste DR7 para que cada execução gere STATUS_SINGLE_STEP. Repita depois para NtMapViewOfSection e, opcionalmente, NtClose.
  2. Trigger DLL loading com LoadLibrary("amsi.dll"). LdrLoadDll eventualmente chamará NtOpenSection para obter o handle da seção real.
  3. VEH hook for NtOpenSection:
  • Localize a posição na stack para o argumento [out] PHANDLE SectionHandle.
  • Escreva o handle DecoySection previamente criado naquele slot.
  • Avance RIP/EIP até a instrução ret para que o kernel nunca seja chamado.
  • Reative o hardware breakpoint para observar NtMapViewOfSection a seguir.
  1. VEH hook for NtMapViewOfSection:
  • Sobrescreva o [out] PVOID *BaseAddress (e as saídas de tamanho/proteção) com o endereço da view maliciosa já mapeada.
  • Pule o corpo do syscall do mesmo modo que antes.
  1. (Optional) VEH hook for NtClose verifica que o fake section handle é limpo, prevenindo resource leaks e fornecendo uma checagem final de sanidade.

Como os syscalls nunca são executados, callbacks do kernel (ETWti, minifilter, etc.) não observam os eventos suspeitos de NtOpenSection/NtMapViewOfSection, reduzindo drasticamente a telemetria. Do ponto de vista do loader, tudo ocorreu com sucesso e amsi.dll está em memória, então ele prossegue com a resolução de imports/TLS contra os bytes do atacante.

Etapa 3 – Executar o payload

  • EXE payload: O injector simplesmente salta para o entry point original uma vez que as realocações estão aplicadas. Quando o loader pensa que chamaria DllMain, o código customizado executa o entry no estilo EXE.
  • DLL payload / Node.js addon: Resolva e chame o export pretendido (Kidkadi expõe uma função nomeada para JavaScript). Como o módulo já está registrado em LdrpModuleBaseAddressIndex, buscas subsequentes o veem como o DLL benigno.

Quando combinado com um Node.js native addon (.node file), toda a complexidade de Windows-internals fica fora da camada JavaScript, ajudando o ator de ameaça a distribuir o mesmo loader com múltiplos wrappers Node ofuscados.

Referências

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks