Vectored Overloading PE Injection

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Descripción de la técnica

Vectored Overloading es una primitiva de inyección PE en Windows que fusiona el clásico Module Overloading con Vectored Exception Handlers (VEHs) y hardware breakpoints. En lugar de parchear LoadLibrary o escribir su propio loader, el adversario:

  1. Crea una sección SEC_IMAGE respaldada por un DLL legítimo (por ejemplo, wmp.dll).
  2. Sobrescribe la vista mapeada con un PE malicioso totalmente relocado pero mantiene el objeto de sección apuntando a la imagen benign en disco.
  3. Registra un VEH y programa los registros de depuración para que cada llamada a NtOpenSection, NtMapViewOfSection, y opcionalmente NtClose genere un breakpoint en modo usuario.
  4. Llama a LoadLibrary("amsi.dll") (o cualquier otro objetivo benigno). Cuando el loader de Windows invoque esos syscalls, el VEH salta la transición al kernel y devuelve los handles y las direcciones base de la imagen maliciosa preparada.

Porque el loader aún cree que mapeó el DLL solicitado, las herramientas que solo inspeccionan los archivos de backing del section ven wmp.dll aunque la memoria ahora contenga el payload del atacante. Mientras tanto, imports/TLS callbacks siguen siendo resueltos por el loader genuino, reduciendo significativamente la cantidad de lógica de parsing PE personalizada que el adversario debe mantener.

Stage 1 – Build the disguised section

  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 section by section, honouring SizeOfRawData/VirtualSize and updating protections afterwards (PAGE_EXECUTE_READ, PAGE_READWRITE, etc.).
  2. Apply relocations and resolve imports exactly as a reflective loader would. Because the view is already mapped as SEC_IMAGE, section alignments and guard pages match what the Windows loader expects later.
  3. Normalize the PE header:
  • If the payload is an EXE, set IMAGE_FILE_HEADER.Characteristics |= IMAGE_FILE_DLL and zero the entry point to keep LdrpCallTlsInitializers from jumping into EXE-specific stubs.
  • DLL payloads can keep their headers unchanged.

En este punto el proceso posee una vista con permisos RWX cuyo objeto de backing sigue siendo wmp.dll, sin embargo los bytes en memoria están controlados por el atacante.

Stage 2 – Hijack the loader with VEHs

  1. Register a VEH and arm hardware breakpoints: program Dr0 (o otro registro de depuración) con la dirección de ntdll!NtOpenSection y configura DR7 para que cada ejecución genere STATUS_SINGLE_STEP. Repetir luego para NtMapViewOfSection y opcionalmente NtClose.
  2. Trigger DLL loading con LoadLibrary("amsi.dll"). LdrLoadDll eventualmente llamará a NtOpenSection para obtener el handle de sección real.
  3. VEH hook for NtOpenSection:
  • Localizar la posición en pila del argumento [out] PHANDLE SectionHandle.
  • Escribir el handle previamente creado DecoySection en esa posición.
  • Avanzar RIP/EIP hasta la instrucción ret para que nunca se invoque el kernel.
  • Re-armar el hardware breakpoint para vigilar NtMapViewOfSection a continuación.
  1. VEH hook for NtMapViewOfSection:
  • Sobrescribir el [out] PVOID *BaseAddress (y las salidas de tamaño/protección) con la dirección de la vista maliciosa ya mapeada.
  • Omitir el cuerpo del syscall igual que antes.
  1. (Optional) VEH hook for NtClose verifica que el fake section handle se limpie, previniendo resource leaks y proporcionando una comprobación final de sanity.

Como los syscalls nunca se ejecutan, callbacks del kernel (ETWti, minifilter, etc.) no observan los eventos sospechosos de NtOpenSection/NtMapViewOfSection, reduciendo drásticamente la telemetría. Desde el punto de vista del loader todo tuvo éxito y amsi.dll está en memoria, por lo que procede con la resolución de imports/TLS contra los bytes del atacante.

Stage 3 – Execute the payload

  • EXE payload: El injector simplemente salta al entry point original una vez que se aplican las relocations. Cuando el loader crea que va a llamar a DllMain, el código personalizado ejecuta en su lugar el entry de estilo EXE.
  • DLL payload / Node.js addon: Resolver y llamar al export deseado (Kidkadi expone una función nombrada a JavaScript). Como el módulo ya está registrado en LdrpModuleBaseAddressIndex, búsquedas posteriores lo verán como el DLL benigno.

Cuando se combina con un Node.js native addon (.node file), todo el trabajo pesado relacionado con Windows internals permanece fuera de la capa JavaScript, ayudando al actor de amenaza a distribuir el mismo loader con muchos wrappers de Node ofuscados.

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks