Vectored Overloading PE Injection

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Panoramica della tecnica

Vectored Overloading è un Windows PE injection primitive che fonde il classico Module Overloading con le Vectored Exception Handlers (VEHs) e i breakpoint hardware. Invece di patchare LoadLibrary o scrivere un proprio loader, l’avversario:

  1. Crea una sezione SEC_IMAGE basata su una DLL legittima (per esempio wmp.dll).
  2. Sovrascrive la view mappata con un PE maligno completamente relocato ma mantiene l’oggetto sezione puntato all’immagine benign su disco.
  3. Registra una VEH e programma i debug registers in modo che ogni chiamata a NtOpenSection, NtMapViewOfSection, e opzionalmente NtClose generi un breakpoint in user-mode.
  4. Chiama LoadLibrary("amsi.dll") (o qualsiasi altro target benigno). Quando il loader di Windows invoca quei syscall, la VEH salta la transizione al kernel e restituisce gli handle e gli indirizzi base dell’immagine malevola preparata.

Poiché il loader continua a ritenere di aver mappato la DLL richiesta, gli strumenti che guardano solo ai file di backing delle sezioni vedono wmp.dll anche se la memoria ora contiene il payload dell’attaccante. Nel frattempo, imports/TLS callbacks vengono comunque risolti dal loader genuino, riducendo significativamente la quantità di logica custom di parsing PE che l’avversario deve mantenere.

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.

A questo punto il processo possiede una view con permessi RWX il cui oggetto di backing è ancora wmp.dll, ma i byte in memoria sono controllati dall’attaccante.

Stage 2 – Hijack the loader with VEHs

  1. Register a VEH and arm hardware breakpoints: programma Dr0 (o un altro debug register) con l’indirizzo di ntdll!NtOpenSection e imposta DR7 in modo che ogni esecuzione generi STATUS_SINGLE_STEP. Ripeti poi per NtMapViewOfSection e opzionalmente per NtClose.
  2. Trigger DLL loading con LoadLibrary("amsi.dll"). LdrLoadDll chiamerà infine NtOpenSection per ottenere il reale section handle.
  3. VEH hook for NtOpenSection:
  • Individua lo slot nello stack corrispondente all’argomento [out] PHANDLE SectionHandle.
  • Scrivi in quello slot l’handle DecoySection creato in precedenza.
  • Avanza RIP/EIP fino all’istruzione ret in modo che il kernel non venga chiamato.
  • Re-arm il breakpoint hardware per osservare successivamente NtMapViewOfSection.
  1. VEH hook for NtMapViewOfSection:
  • Sovrascrivi il [out] PVOID *BaseAddress (e gli output di size/protection) con l’indirizzo della view malevola già mappata.
  • Salta il corpo del syscall come fatto prima.
  1. (Optional) VEH hook for NtClose verifica che il fake section handle venga pulito, prevenendo resource leak e fornendo un controllo finale di sanity.

Poiché i syscall non vengono mai eseguiti, le callback del kernel (ETWti, minifilter, ecc.) non osservano gli eventi sospetti NtOpenSection/NtMapViewOfSection, abbassando drasticamente la telemetria. Dal punto di vista del loader tutto è riuscito e amsi.dll è in memoria, quindi procede con la risoluzione di import/TLS contro i byte dell’attaccante.

Stage 3 – Execute the payload

  • EXE payload: L’injector semplicemente salta al entry point originale una volta applicate le relocations. Quando il loader pensa che chiamerà DllMain, il codice custom esegue invece l’entry in stile EXE.
  • DLL payload / Node.js addon: Risolvi e chiama l’export previsto (Kidkadi espone una funzione nominata verso JavaScript). Poiché il modulo è già registrato in LdrpModuleBaseAddressIndex, le ricerche successive lo vedono come la DLL benevola.

Quando combinato con un Node.js native addon (.node file), tutta la complessità degli internals di Windows rimane fuori dallo strato JavaScript, aiutando l’attore di minaccia a distribuire lo stesso loader con molti wrapper Node offuscati differenti.

References

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks