Vectored Overloading PE Injection
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Tip
Vous cherchez des techniques d’évasion Windows 11 LFH heap shaping et VMware Workstation PVSCSI (vmware-vmx) ?
{{#ref}} vmware-workstation-pvscsi-lfh-escape.md {{#endref}}
Aperçu de la technique
Vectored Overloading est une primitive d’injection Windows PE qui fusionne le classique Module Overloading avec les Vectored Exception Handlers (VEHs) et les hardware breakpoints. Au lieu de patcher LoadLibrary ou d’écrire son propre loader, l’adversaire :
- Crée une section
SEC_IMAGEadossée à une DLL légitime (par ex.,wmp.dll). - Écrase la vue mappée avec un PE malveillant entièrement relocalisé mais laisse l’objet section pointant vers l’image bénigne sur disque.
- Enregistre un VEH et programme les registres de debug de sorte que chaque appel à
NtOpenSection,NtMapViewOfSection, et optionnellementNtClosedéclenche un breakpoint en mode utilisateur. - Appelle
LoadLibrary("amsi.dll")(ou toute autre cible bénigne). Lorsque le loader Windows invoque ces syscalls, le VEH évite la transition noyau et retourne les handles et adresses de base de l’image malveillante préparée.
Parce que le loader croit toujours avoir mappé la DLL demandée, les outils qui ne regardent que les fichiers de backing de section voient wmp.dll même si la mémoire contient maintenant la charge utile de l’attaquant. Pendant ce temps, les imports/callbacks TLS sont toujours résolus par le loader authentique, réduisant significativement la quantité de logique personnalisée d’analyse PE que l’adversaire doit maintenir.
Étape 1 – Construire la section déguisée
- Créer et mapper une section pour la DLL leurre
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);
- Copier le PE malveillant dans cette vue section par section, en respectant
SizeOfRawData/VirtualSizeet en mettant à jour les protections ensuite (PAGE_EXECUTE_READ,PAGE_READWRITE, etc.). - Appliquer les relocations et résoudre les imports exactement comme le ferait un reflective loader. Parce que la vue est déjà mappée comme
SEC_IMAGE, les alignements de section et les guard pages correspondent à ce que le loader Windows attend ensuite. - Normaliser l’en-tête PE :
- Si le payload est un EXE, définir
IMAGE_FILE_HEADER.Characteristics |= IMAGE_FILE_DLLet mettre à zéro l’entry point pour empêcherLdrpCallTlsInitializersde sauter dans des stubs spécifiques aux EXE. - Les payloads DLL peuvent laisser leurs en-têtes inchangés.
À ce stade le processus possède une vue RWX dont l’objet backing est toujours wmp.dll, pourtant les octets en mémoire sont contrôlés par l’attaquant.
Étape 2 – Détourner le loader avec des VEHs
- Enregistrer un VEH et armer des hardware breakpoints : programmer
Dr0(ou un autre registre de debug) avec l’adresse dentdll!NtOpenSectionet définirDR7pour que chaque exécution soulèveSTATUS_SINGLE_STEP. Répéter ensuite pourNtMapViewOfSectionet éventuellementNtClose. - Déclencher le chargement de la DLL avec
LoadLibrary("amsi.dll").LdrLoadDllappellera finalementNtOpenSectionpour obtenir le handle de section réel. - Hook VEH pour
NtOpenSection:
- Localiser l’emplacement sur la pile pour l’argument
[out] PHANDLE SectionHandle. - Écrire le handle
DecoySectionprécédemment créé dans cet emplacement. - Avancer
RIP/EIPjusqu’à l’instructionretpour que le kernel ne soit jamais appelé. - Réarmer le hardware breakpoint pour surveiller
NtMapViewOfSectionensuite.
- Hook VEH pour
NtMapViewOfSection:
- Écraser le
[out] PVOID *BaseAddress(et les sorties taille/protection) avec l’adresse de la vue malveillante déjà mappée. - Sauter le corps du syscall comme précédemment.
- (Optionnel) Hook VEH pour
NtClosevérifie que le faux handle de section est nettoyé, évitant les fuites de ressources et fournissant une dernière vérification de cohérence.
Parce que les syscalls ne sont jamais exécutés, les callbacks noyau (ETWti, minifilter, etc.) n’observent pas les événements suspects NtOpenSection/NtMapViewOfSection, réduisant drastiquement la télémétrie. Du point de vue du loader tout a réussi et amsi.dll est en mémoire, il procède donc à la résolution des imports/TLS contre les octets de l’attaquant.
Notes d’implémentation du PoC (2025)
Le PoC public montre quelques détails pratiques faciles à manquer lors de la ré-implémentation de la technique :
- HWBPs are per-thread. Le PoC définit
CONTEXT_DEBUG_REGISTERSsur le thread courant avant d’appelerLoadLibrary, donc le VEH doit s’exécuter sur le même thread qui déclenche le loader. - Syscall emulation: le VEH met
RAX = 0et avanceRIPjusqu’auretà l’intérieur du stubntdll(il scanne pour0xC3) de sorte que la transition noyau n’ait jamais lieu, puis reprend avecNtContinue. - Output parameters: pour
NtMapViewOfSection, le VEH écrase les sorties retournéesBaseAddress,ViewSize, etWin32Protectpour que le loader croie que le mapping a réussi et continue la résolution des imports/TLS en utilisant la vue de l’attaquant.
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);
Variation furtive
Des recherches récentes sur VEH montrent que des handlers peuvent être enregistrés en manipulant manuellement la liste VEH au lieu d’appeler AddVectoredExceptionHandler, ce qui réduit la dépendance aux user-mode APIs qui peuvent être surveillées ou hookées. Cela n’est pas requis pour Vectored Overloading mais peut être combiné avec celui-ci pour réduire l’activité API observable.
Étape 3 – Exécuter le payload
- EXE payload : l’injecteur saute simplement vers le point d’entrée original une fois les relocations terminées. Lorsque le loader pense qu’il va appeler
DllMain, le code personnalisé exécute à la place l’entrée de type EXE. - DLL payload / Node.js addon : résoudre et appeler l’export ciblé (Kidkadi expose une fonction nommée à JavaScript). Parce que le module est déjà enregistré dans
LdrpModuleBaseAddressIndex, les recherches ultérieures le voient comme la DLL bénigne.
Lorsqu’il est combiné avec un Node.js native addon (.node file), toute la partie lourde des Windows-internals reste en dehors de la couche JavaScript, ce qui permet à l’acteur de menace de déployer le même loader avec de nombreux wrappers Node obfusqués différents.
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
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


