Vectored Overloading PE Injection

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Tip

Windows 11 LFH heap shaping ve VMware Workstation PVSCSI (vmware-vmx) escape tekniklerini mi arıyorsunuz?

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

Technique overview

Vectored Overloading, klasik Module Overloading ile Vectored Exception Handlers (VEHs) ve hardware breakpoints’i birleştiren bir Windows PE injection primitive’sidir. LoadLibrary’yi patchlemek veya kendi loader’ını yazmak yerine, saldırgan:

  1. Meşru bir DLL (ör. wmp.dll) tarafından desteklenen bir SEC_IMAGE section oluşturur.
  2. Maplenmiş görünümü tamamen relocate edilmiş kötü amaçlı bir PE ile üzerine yazar, fakat section objesinin diskteki zararsız imaja işaret etmesini sağlar.
  3. Bir VEH kaydeder ve debug register’ları programlayarak her NtOpenSection, NtMapViewOfSection ve isteğe bağlı olarak NtClose çağrısının user-mode breakpoint tetiklemesini sağlar.
  4. LoadLibrary("amsi.dll") (veya başka herhangi bir zararsız hedef) çağırır. Windows loader bu syscall’ları çağırdığında, VEH kernel geçişini atlar ve hazırlanmış kötü amaçlı görüntünün handle ve base adreslerini döndürür.

Loader hâlâ isteği yapılan DLL’i maplediğini düşündüğü için, yalnızca section backing file’ına bakan tooling wmp.dll görür; oysa hafızada artık saldırganın payload’u bulunur. Bu arada import/TLS callback’leri genuine loader tarafından hâlâ çözülür, bu da saldırganın bakımını yapması gereken özel PE-parsinge ait kod miktarını önemli ölçüde azaltır.

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.

Bu noktada işlem, backing object’ı hâlâ wmp.dll olan fakat hafızadaki baytları saldırgan tarafından kontrol edilen RWX kapasiteli bir view’a sahiptir.

Stage 2 – Hijack the loader with VEHs

  1. Register a VEH and arm hardware breakpoints: ntdll!NtOpenSection adresi ile Dr0 (veya başka bir debug register) programlanır ve her yürütmede STATUS_SINGLE_STEP tetiklenmesi için DR7 ayarlanır. Daha sonra NtMapViewOfSection ve isteğe bağlı olarak NtClose için de tekrarlanır.
  2. Trigger DLL loading with LoadLibrary("amsi.dll"). LdrLoadDll eninde sonunda gerçek section handle’ını almak için NtOpenSection’ı çağıracaktır.
  3. VEH hook for NtOpenSection:
  • [out] PHANDLE SectionHandle argümanının stack slot’unu bulun.
  • Önceden oluşturulmuş DecoySection handle’ını o slota yazın.
  • Kernel hiçbir zaman çağrılmasın diye RIP/EIP’i ret komutuna ilerletin.
  • Donanım breakpoint’ini bir sonraki olarak NtMapViewOfSection’ı izleyecek şekilde yeniden kurun.
  1. VEH hook for NtMapViewOfSection:
  • [out] PVOID *BaseAddress (ve size/protection çıktılarını) zaten maplenmiş kötü amaçlı view adresi ile üzerine yazın.
  • Daha önce olduğu gibi syscall gövdesini atlayın.
  1. (Optional) VEH hook for NtClose sahte section handle’ının temizlendiğini doğrular, resource leak’leri engeller ve son bir tutarlılık kontrolü sağlar.

Syscall’lar hiçbir zaman çalıştırılmadığı için kernel callback’leri (ETWti, minifilter, vb.) şüpheli NtOpenSection/NtMapViewOfSection olaylarını gözlemlemez; bu da telemetriyi önemli ölçüde düşürür. Loader açısından her şey başarılı olmuş gibi görünür ve amsi.dll hafızadadır; dolayısıyla import/TLS çözümlemesine saldırganın view’ı üzerinden devam eder.

PoC implementation notes (2025)

Public PoC, yeniden uygulama sırasında gözden kaçması kolay birkaç pratik detayı gösterir:

  • HWBPs are per-thread. PoC, CONTEXT_DEBUG_REGISTERS’ı LoadLibrary çağırılmadan önce geçerli thread üzerinde ayarlar; bu yüzden VEH’nin loader’ı tetikleyen aynı thread üzerinde çalışması gerekir.
  • Syscall emulation: VEH, RAX = 0 ayarlar ve kernel geçişinin hiç olmaması için ntdll stub içindeki ret’e (0xC3) ilerletir, sonra NtContinue ile devam eder.
  • Output parameters: NtMapViewOfSection için VEH, döndürülen BaseAddress, ViewSize ve Win32Protect çıktılarının üzerine yazar, böylece loader map işleminin başarılı olduğunu sanır ve import/TLS’e saldırganın view’ı üzerinden devam eder.

Minimal HWBP setup used by the PoC (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);

Gizli varyasyon

Son VEH araştırmaları, handler’ların AddVectoredExceptionHandler çağırmak yerine VEH listesi üzerinde elle manipüle edilerek kaydedilebileceğini gösteriyor; bu da izlenebilecek veya hooklanabilecek user-mode API’larına olan bağımlılığı azaltır. Bu, Vectored Overloading için gerekli değildir ancak gözlemlenebilir API etkinliğini azaltmak için onunla birleştirilebilir.

Aşama 3 – Execute the payload

  • EXE payload: Enjektör, relocations tamamlandığında basitçe orijinal entry point’e atlar. Loader DllMain çağıracağını düşündüğünde, özel kod bunun yerine EXE tarzı entry’yi çalıştırır.
  • DLL payload / Node.js addon: Hedeflenen export’ı çözümleyip çağırır (Kidkadi JavaScript’e isimlendirilmiş bir fonksiyon sunar). Modül zaten LdrpModuleBaseAddressIndex ile kayıtlı olduğu için sonraki aramalar onu zararsız DLL olarak görür.

Node.js native addon (.node file) ile birleştirildiğinde, Windows-internals ile ilgili tüm ağır işler JavaScript katmanının dışında kalır; bu da tehdit aktörünün aynı loader’ı birçok farklı obfuscated Node wrapper ile dağıtmasına yardımcı olur.

Referanslar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin