Vectored Overloading PE Injection
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Tip
Ψάχνετε για τεχνικές shaping heap LFH των Windows 11 και escape για VMware Workstation PVSCSI (vmware-vmx);
{{#ref}} vmware-workstation-pvscsi-lfh-escape.md {{#endref}}
Technique overview
Το Vectored Overloading είναι μια βασική τεχνική εισαγωγής PE στα Windows που συνδυάζει το κλασικό Module Overloading με Vectored Exception Handlers (VEHs) και hardware breakpoints. Αντί να τροποποιήσει το LoadLibrary ή να γράψει τον δικό του loader, ο επιτιθέμενος:
- Δημιουργεί ένα
SEC_IMAGEsection που έχει σαν backing ένα νόμιμο DLL (π.χ.wmp.dll). - Επαναγράφει την mapped view με ένα πλήρως relocated κακόβουλο PE αλλά διατηρεί το section object να δείχνει στο benign αρχείο στο δίσκο.
- Εγγράφει έναν VEH και προγραμματίζει τα debug registers έτσι ώστε κάθε κλήση σε
NtOpenSection,NtMapViewOfSection, και προαιρετικάNtCloseνα προκαλεί ένα user-mode breakpoint. - Καλεί
LoadLibrary("amsi.dll")(ή οποιοδήποτε άλλο benign target). Όταν ο Windows loader καλεί αυτές τις syscalls, ο VEH παρακάμπτει τη μετάβαση στον kernel και επιστρέφει τα handles και τις base addresses της προετοιμασμένης κακόβουλης εικόνας.
Επειδή ο loader εξακολουθεί να πιστεύει ότι έκανε map το ζητούμενο DLL, εργαλεία που κοιτάνε μόνο τα section backing files βλέπουν wmp.dll παρότι η μνήμη περιέχει πλέον το payload του επιτιθέμενου. Παράλληλα, τα imports/TLS callbacks εξακολουθούν να επιλύονται από τον πραγματικό loader, μειώνοντας σημαντικά την ποσότητα custom PE-parsing λογικής που πρέπει να υλοποιήσει ο επιτιθέμενος.
Stage 1 – Build the disguised section
- 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);
- Copy the malicious PE into that view section by section, honouring
SizeOfRawData/VirtualSizeand updating protections afterwards (PAGE_EXECUTE_READ,PAGE_READWRITE, etc.). - Apply relocations and resolve imports ακριβώς όπως θα έκανε ένας reflective loader. Επειδή η view είναι ήδη mapped ως
SEC_IMAGE, οι ευθυγραμμίσεις section και οι guard pages ταιριάζουν με αυτά που ο Windows loader αναμένει αργότερα. - Normalize the PE header:
- Αν το payload είναι EXE, ορίστε
IMAGE_FILE_HEADER.Characteristics |= IMAGE_FILE_DLLκαι μηδενίστε το entry point ώστε τοLdrpCallTlsInitializersνα μην επιχειρήσει άλμα σε EXE-specific stubs. - Τα DLL payloads μπορούν να κρατήσουν τα headers αμετάβλητα.
Σε αυτό το σημείο η διεργασία έχει μια RWX-capable view της οποίας το backing object παραμένει wmp.dll, αλλά τα bytes στη μνήμη είναι υπό έλεγχο του επιτιθέμενου.
Stage 2 – Hijack the loader with VEHs
- Register a VEH and arm hardware breakpoints: προγραμματίστε
Dr0(ή κάποιο άλλο debug register) με τη διεύθυνση τουntdll!NtOpenSectionκαι ορίστεDR7έτσι ώστε κάθε εκτέλεση να προκαλείSTATUS_SINGLE_STEP. Επαναλάβετε αργότερα γιαNtMapViewOfSectionκαι προαιρετικάNtClose. - Trigger DLL loading με
LoadLibrary("amsi.dll"). ΤοLdrLoadDllτελικά θα καλέσειNtOpenSectionγια να πάρει το πραγματικό section handle. - VEH hook for
NtOpenSection:
- Βρείτε τη θέση στο stack για το
[out] PHANDLE SectionHandleόρισμα. - Γράψτε το προηγουμένως δημιουργημένο
DecoySectionhandle σε αυτή τη θέση. - Προωθήστε το
RIP/EIPστην εντολήretώστε να μην κληθεί ποτέ ο kernel. - Επαν-οπλίστε το hardware breakpoint για να παρακολουθήσει το
NtMapViewOfSectionστη συνέχεια.
- VEH hook for
NtMapViewOfSection:
- Επαναγράψτε το
[out] PVOID *BaseAddress(και τα outputs για μέγεθος/προστασία) με τη διεύθυνση της ήδη mapped κακόβουλης view. - Παραλείψτε το σώμα της syscall όπως και πριν.
- (Optional) VEH hook for
NtCloseεπαληθεύει ότι το fake section handle καθαρίζεται, αποτρέποντας resource leaks και παρέχοντας έναν τελικό έλεγχο ορθότητας.
Επειδή οι syscalls δεν εκτελούνται ποτέ, kernel callbacks (ETWti, minifilter, κ.λπ.) δεν παρατηρούν τα ύποπτα NtOpenSection/NtMapViewOfSection γεγονότα, μειώνοντας δραστικά την τηλεμετρία. Από την πλευρά του loader όλα φαίνονται επιτυχημένα και το amsi.dll είναι στη μνήμη, οπότε ο loader συνεχίζει με την επίλυση imports/TLS χρησιμοποιώντας την view του επιτιθέμενου.
PoC implementation notes (2025)
Το δημόσιο PoC δείχνει μερικές πρακτικές λεπτομέρειες που είναι εύκολο να παραβλεφτούν όταν επανυλοποιείτε την τεχνική:
- HWBPs are per-thread. Το PoC ορίζει
CONTEXT_DEBUG_REGISTERSστο τρέχον thread πριν καλέσειLoadLibrary, οπότε ο VEH πρέπει να τρέξει στο ίδιο thread που πυροδοτεί τον loader. - Syscall emulation: ο VEH θέτει
RAX = 0και προωθεί τοRIPστοretμέσα στοntdllstub (σκανάρει για0xC3) ώστε η μετάβαση στον kernel να μην συμβεί ποτέ, και μετά συνεχίζει μεNtContinue. - Output parameters: για το
NtMapViewOfSection, ο VEH επαναγράφει τα επιστρεφόμεναBaseAddress,ViewSizeκαιWin32Protectoutputs ώστε ο loader να πιστεύει ότι το mapping πέτυχε και να συνεχίσει με imports/TLS χρησιμοποιώντας την view του επιτιθέμενου.
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);
Stealth variation
Πρόσφατη έρευνα για το VEH επισημαίνει ότι handlers μπορούν να καταχωρηθούν με manually manipulating the VEH list αντί να καλείται AddVectoredExceptionHandler, μειώνοντας έτσι την εξάρτηση από user-mode APIs που ενδέχεται να παρακολουθούνται ή να είναι hooked. Αυτό δεν είναι απαραίτητο για το Vectored Overloading, αλλά μπορεί να συνδυαστεί με αυτό για να μειώσει την παρατηρήσιμη API δραστηριότητα.
Stage 3 – Εκτέλεση του payload
- EXE payload: Ο injector απλώς πηδάει στο αρχικό entry point μόλις ολοκληρωθούν οι relocations. Όταν ο loader νομίζει ότι θα καλέσει τη
DllMain, ο custom κώδικας εκτελεί αντ’ αυτού το EXE-style entry. - DLL payload / Node.js addon: Επιλύει και καλεί το προοριζόμενο export (Kidkadi exposes a named function to JavaScript). Εφόσον το module έχει ήδη καταχωρηθεί με
LdrpModuleBaseAddressIndex, οι επόμενες αναζητήσεις το βλέπουν ως το benign DLL.
Όταν συνδυάζεται με ένα Node.js native addon (.node file), όλο το Windows-internals heavy lifting παραμένει έξω από το JavaScript layer, βοηθώντας τον threat actor να διανείμει τον ίδιο loader με πολλούς διαφορετικούς obfuscated Node wrappers.
References
- Check Point Research – GachiLoader: Defeating Node.js Malware with API Tracing
- VectoredOverloading – PoC implementation
- IBM X-Force – You just got vectored: Using VEH for defense evasion and process injection
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.


