Vectored Overloading PE Injection

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Tip

Op soek na Windows 11 LFH heap shaping en VMware Workstation PVSCSI (vmware-vmx) ontsnappingsmetodes?

{{#ref}} vmware-workstation-pvscsi-lfh-escape.md {{#endref}}

Oorsig van die tegniek

Vectored Overloading is ’n Windows PE injection primitive wat klassieke Module Overloading met Vectored Exception Handlers (VEHs) en hardware breakpoints kombineer. In plaas daarvan om LoadLibrary te patch of ’n eie loader te skryf, doen die teenstander:

  1. Skep ’n SEC_IMAGE section wat gesteun word deur ’n regte DLL (bv. wmp.dll).
  2. Oorskryf die gemapte view met ’n volledig herlokaliseerde kwaadwillige PE, maar laat die section-object steeds na die onskuldige beeld op skyf wys.
  3. Registreer ’n VEH en programmeer debug-registers sodat elke oproep na NtOpenSection, NtMapViewOfSection, en opsioneel NtClose ’n user-mode breakpoint opwek.
  4. Roep LoadLibrary("amsi.dll") (of enige ander onskuldige teiken). Wanneer die Windows loader daardie syscalls aanroep, slaan die VEH die kernel-oorgang oor en gee die handles en basisadresse terug van die voorbereide kwaadwillige image.

Omdat die loader steeds glo dit het die versoekte DLL gemap, sien tooling wat slegs na section backing files kyk wmp.dll alhoewel die geheue nou die aanvaller se payload bevat. Intussen word imports/TLS callbacks steeds deur die ware loader opgelos, wat die hoeveelheid aangepaste PE-parsing logika wat die teenstander moet onderhou aansienlik verminder.

Fase 1 – Bou die vermomde seksie

  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. Kopieer die kwaadwillige PE in daardie view afdeling vir afdeling, en hou rekening met SizeOfRawData/VirtualSize en werk beskermings daarna by (PAGE_EXECUTE_READ, PAGE_READWRITE, etc.).
  2. Pas relocations toe en los imports op presies soos ’n reflective loader sou doen. Omdat die view reeds as SEC_IMAGE gemap is, stem section-uitlyning en guard pages ooreen met wat die Windows loader later verwag.
  3. Normaliseer die PE-header:
  • As die payload ’n EXE is, stel IMAGE_FILE_HEADER.Characteristics |= IMAGE_FILE_DLL en zero die entry point om te verhoed dat LdrpCallTlsInitializers in EXE-spesifieke stubs spring.
  • DLL payloads kan hul headers ongewysig hou.

Op hierdie punt besit die proses ’n RWX-vaardige view waarvan die backing object steeds wmp.dll is, maar die bytes in geheue is deur die aanvaller beheer.

Fase 2 – Kap die loader met VEHs

  1. Registreer ’n VEH en aktiveer hardware breakpoints: programmeer Dr0 (of ’n ander debug register) met die adres van ntdll!NtOpenSection en stel DR7 sodat elke uitvoering STATUS_SINGLE_STEP opwek. Herhaal later vir NtMapViewOfSection en opsioneel NtClose.
  2. Trigger DLL loading met LoadLibrary("amsi.dll"). LdrLoadDll sal uiteindelik NtOpenSection aanroep om die werklike section handle te verkry.
  3. VEH hook vir NtOpenSection:
  • Lokaliseer die stackslot vir die [out] PHANDLE SectionHandle argument.
  • Skryf die vooraf geskepte DecoySection handle in daardie slot.
  • Verskuif RIP/EIP na die ret instruksie sodat die kernel nooit aangeroep word nie.
  • Heraktiveer die hardware breakpoint om volgende na NtMapViewOfSection te kyk.
  1. VEH hook vir NtMapViewOfSection:
  • Oorskryf die [out] PVOID *BaseAddress (en grootte/beskerming outputs) met die adres van die reeds gemapte kwaadwillige view.
  • Slaan die syscall-lichaam oor net soos voorheen.
  1. (Opsioneel) VEH hook vir NtClose verifieer dat die fake section handle skoongemaak word, wat resource leaks voorkom en ’n finale sanity check verskaf.

Omdat die syscalls nooit uitgevoer word nie, sien kernel callbacks (ETWti, minifilter, etc.) nie die verdagte NtOpenSection/NtMapViewOfSection gebeure nie, wat telemetry dramaties verlaag. Vanuit die laaier se oogpunt het alles geslaag en is amsi.dll in geheue, so dit gaan voort met import/TLS resolusie teenoor die aanvaller se bytes.

PoC implementasie notas (2025)

Die publieke PoC wys ’n paar praktiese besonderhede wat maklik misgekyk word wanneer die tegniek herimplementer word:

  • HWBPs is per-thread. Die PoC stel CONTEXT_DEBUG_REGISTERS op die huidige thread voordat LoadLibrary geroep word, dus die VEH moet op dieselfde thread loop wat die loader trigger.
  • Syscall emulasie: die VEH stel RAX = 0 en verskuif RIP na die ret binne die ntdll stub (dit scan vir 0xC3) sodat die kernel-oorgang nooit plaasvind nie, en hervat dan met NtContinue.
  • Output parameters: vir NtMapViewOfSection oorskryf die VEH die teruggegewe BaseAddress, ViewSize, en Win32Protect outputs sodat die loader glo die mapping het suksesvol plaasgevind en voortgaan met imports/TLS wat die aanvaller se view gebruik.

Minimum HWBP-opstelling wat deur die PoC gebruik word (x64):

CONTEXT ctx = {0};
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
GetThreadContext(GetCurrentThread(), &ctx);
ctx.Dr0 = (DWORD64)NtOpenSection;
ctx.Dr7 = 1;
SetThreadContext(GetCurrentThread(), &ctx);
AddVectoredExceptionHandler(1, VehHandler);

Stealth-variasie

Onlangse VEH-navorsing beklemtoon dat handlers geregistreer kan word deur manueel die VEH-lys te manipuleer in plaas daarvan om AddVectoredExceptionHandler aan te roep, wat die afhanklikheid van user-mode APIs verminder wat moontlik gemonitor of gehook kan wees. Dit is nie nodig vir Vectored Overloading nie maar kan daarmee gekombineer word om sigbare API-aktiwiteit te verminder.

Stage 3 – Voer die payload uit

  • EXE payload: Die injector spring eenvoudig na die oorspronklike entry point sodra relocations klaar is. Wanneer die loader dink dit sal DllMain aanroep, voer die pasgemaakte kode in plaas daarvan die EXE-styl entry uit.
  • DLL payload / Node.js addon: Los op en roep die beoogde export aan (Kidkadi exposes a named function to JavaScript). Omdat die module reeds geregistreer is by LdrpModuleBaseAddressIndex, sien opvolgende lookups dit as die goedaardige DLL.

Wanneer dit gekombineer word met ’n Node.js native addon (.node file), bly al die Windows-internals swaar werk buite die JavaScript-laag, wat die threat actor help om dieselfde loader met baie verskillende obfuscated Node wrappers te versprei.

Verwysings

Tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks