Injection de processus¶
L'injection de processus est le principal mécanisme de livraison pour les opérations post-exploitation à Stentor. Chaque commande fork-and-run (execute-assembly, powerpick, shspawn, etc.) et chaque commande d'injection explicite (inject, shinject, dllinject) utilise l'une de ces techniques pour exécuter du code dans un processus cible.
Stentor prend en charge 23 techniques d'injection, chacune produisant des artefacts médico-légaux distincts et offrant différents compromis OPSEC. La technique par défaut est CRT (CreateRemoteThread), mais les opérateurs peuvent configurer des alternatives via le profil malléable ou les remplacements par beacon pour les environnements à forte densité EDR.
ATTAQUE À ONGLET&CK
L'injection de processus correspond à T1055 - Injection de processus et à ses sous-techniques. Chaque section technique ci-dessous comprend l'ID de sous-technique spécifique.
Tableau de comparaison OPSEC¶
Ce tableau fournit une référence rapide pour sélectionner la bonne technique d'injection en fonction de vos exigences OPSEC.
| Technique | ID | Méthode | Allocation mémoire | Création de thread | Niveau OPSEC | Idéal pour |
|---|---|---|---|---|---|---|
crt | T1055.003 | VirtualAllocEx + WriteProcessMemory + CreateRemoteThread | VirtualAllocEx (RW-> RX) | Créer un thread distant | ⅕ | Laboratoire/tests, compatibilité |
ntmap | T1055.012 | NtCreateSection + NtMapViewOfSection + RtlCreateUserThread | Cartographie des sections partagées | RtlCreateUserThread | ⅗ | Missions standards |
setthreadctx | T1055.003 | Détournement de thread Get/SetThreadContext sur un thread suspendu | VirtualAllocEx (RW-> RX) | Discussion sur le détournement de RIP | ⅗ | Fork-and-run uniquement |
queueapc | T1055.004 | QueueUserAPC early-bird sur le fil suspendu | VirtualAllocEx (RW-> RX) | APC avant le point d'entrée | ⅗ | Fork-and-run uniquement |
rtlthread | T1055 | VirtualAllocEx + WriteProcessMemory + RtlCreateUserThread | VirtualAllocEx (RW-> RX) | RtlCreateUserThread | ⅖ | Contourner les hooks kernel32 |
selfinject | T1055 | VirtualAlloc + CreateThread dans le processus en cours | VirtualAlloc local (RW->RX) | Créer un thread local | ⅖ | Auto-injection BOF/beacon |
udrl | T1620 | Chargeur réfléchissant personnalisé ajouté à le payload | Contrôlé par l'opérateur | Contrôlé par l'opérateur | ⅘ | Engagements personnalisés |
obfsetthreadctx | T1055.003 | Créer un thread sur une fonction légitime, puis détourner RIP | VirtualAllocEx (RW-> RX) | CreateRemoteThread (démarrage falsifié) | ⅘ | Évasion EDR |
cloneprocess | T1055.012 | RtlCloneUserProcess + APC sur clone | VirtualAllocEx (RW-> RX) | APC sur thread cloné | ⅘ | Éviter les threads distants |
tpdirect | T1055 | Faux détournement de rappel TP_DIRECT + pool de threads | Structure VirtualAllocEx + TP_DIRECT | Rappel du pool de threads | ⅘ | Environnements à forte densité EDR |
earlycascade | T1055.012 | Processus suspendu + détournement RIP avant chargement de DLL | VirtualAllocEx (RW-> RX) | Sujet de détournement de RIP avant l'initialisation | 5/5 | Évasion maximale |
tpstartroutinestub | T1055 | Fausse répartition des travailleurs TP_WORK + pool de threads | Structure VirtualAllocEx + TP_WORK | Travailleur du pool de threads | 5/5 | Environnements à forte densité EDR |
modulestomp | T1055.001 | Charger la DLL + écraser la section .text avec le shellcode | MEM_IMAGE sauvegardé (DLL signée) | Créer un thread distant | ⅘ | Évasion du scanner de mémoire |
dllinject | T1055.001 | Conversion sRDI + injection de shellcode | VirtualAllocEx (RW-> RX) | Injecteur par défaut | ⅗ | Chargement de DLL réfléchissant |
threadless | T1055 | Crochet trampoline sur fonction exportée | VirtualAllocEx (RW-> RX) | Pas de création de fil | 5/5 | Furtivité maximale |
hollowing | T1055.012 | CreateProcess (SUSPENDED) + remplacer l'image | VirtualAllocEx (RW-> RX) | Reprendre le fil principal suspendu | ⅘ | Remplacement du processus |
poolparty_workitem | T1055 | Insertion de TP_WORK dans le pool de threads cible | Structure VirtualAllocEx + TP_WORK | Travailleur du pool de threads | 5/5 | Environnements à forte densité EDR |
poolparty_timer | T1055 | Insertion TP_TIMER dans le pool de threads cible | Structure VirtualAllocEx + TP_TIMER | Rappel du minuteur du pool de threads | 5/5 | Environnements à forte densité EDR |
poolparty_io | T1055 | Achèvement de TP_IO dans le pool de threads cible | Structure VirtualAllocEx + TP_IO | Rappel d’E/S du pool de threads | 5/5 | Environnements à forte densité EDR |
poolparty_alpc | T1055 | Port TP_ALPC dans le pool de threads cible | Structure VirtualAllocEx + TP_ALPC | Rappel ALPC du pool de threads | 5/5 | Environnements à forte densité EDR |
cb_fontenum | T1055 | Déclencheur de shellcode de rappel EnumFontFamiliesEx | VirtualAllocEx (RW-> RX) | Rappel depuis l'API GDI | ⅘ | Évasion basée sur le rappel |
cb_timer | T1055 | Déclencheur de shellcode de rappel CreateTimerQueueTimer | VirtualAllocEx (RW-> RX) | Rappel de la file d'attente du minuteur | ⅘ | Évasion basée sur le rappel |
cb_winenum | T1055 | Déclencheur de shellcode de rappel EnumWindows | VirtualAllocEx (RW-> RX) | Rappel depuis l'API user32 | ⅘ | Évasion basée sur le rappel |
Lire le niveau OPSEC
OPSEC Niveau ⅕ = le plus détectable (empreinte d'artefact la plus élevée). OPSEC niveau 5/5 = le moins détectable (empreinte API minimale, chemins d'exécution d'apparence légitime). Plus haut est plus furtif.
Guide de sélection des techniques¶
Le choix de la bonne technique d'injection dépend des capacités de détection de l'environnement cible. Utilisez ce guide comme point de départ.
Quelle technique dois-je utiliser ?
Labo ou environnement de test : Utilisez crt (par défaut). Compatibilité la plus fiable et la plus large, plus facile à déboguer.
Engagement standard (pas d'EDR) : Utilisez ntmap ou queueapc. Bon équilibre entre furtivité et fiabilité. ntmap évite entièrement VirtualAllocEx/WriteProcessMemory ; queueapc évite CreateRemoteThread.
Environnement à forte intensité EDR : Utilisez tpdirect, tpstartroutinestub ou earlycascade. Ces techniques ont la plus petite empreinte API et s’exécutent via un pool de threads Windows légitime ou des chemins d’initialisation de processus.
Évasion du scanner de mémoire : Utilisez modulestomp. Le shellcode réside dans la mémoire MEM_IMAGE soutenue par une DLL signée, battant ainsi les scanners qui signalent la mémoire exécutable non sauvegardée.
Auto-injection (BOF/beacon en cours) : Utilisez selfinject. Aucune opération inter-processus : le shellcode s'exécute à l'intérieur du processus de beacon lui-même.
Chargeur personnalisé pour environnements uniques : Utilisez udrl. L'opérateur fournit son propre shellcode de chargeur réfléchissant, permettant une personnalisation par engagement sans signature fixe.
Injection sans fil (pas de nouveaux fils) : Utilisez threadless. Accroche une fonction exportée dans le processus cible avec un trampoline - le shellcode s'exécute lorsque la fonction est appelée naturellement. Aucun artefact de création de thread.
Abus de pool de threads (PoolParty) : Utilisez poolparty_workitem, poolparty_timer, poolparty_io ou poolparty_alpc. Ceux-ci détournent les composants internes du pool de threads Windows pour exécuter du shellcode via des chemins de répartition de travailleurs légitimes. Basé sur la recherche PoolParty de SafeBreach Labs.
Injection basée sur un rappel : Utilisez cb_fontenum, cb_timer ou cb_winenum. Déclenchez l'exécution du shellcode via des API de rappel Win32 légitimes (EnumFontFamiliesEx, CreateTimerQueueTimer, EnumWindows). L'exécution du rappel apparaît comme une activité API normale.
Remplacement du processus : Utilisez hollowing. Crée un processus suspendu et remplace son image par un shellcode avant son initialisation. Le shellcode fonctionne comme le fil conducteur d'un processus d'apparence épurée.
Commandes d'injection autonomes¶
Ces commandes permettent à l'opérateur d'injecter du code dans un processus spécifique par PID. Elles se distinguent des opérations fork-and-run (qui génèrent et s’injectent automatiquement dans un processus sacrificiel).
injecter¶
Injectez un payload de beacon dans un processus existant par PID. Le backend génère un shellcode pour le listener et l'architecture spécifiés, puis le beacon l'injecte à l'aide de la technique d'injection configurée.
Type de tâche : inject (méthode : inject)
OPSEC
inject crée un thread distant dans le processus cible. L'événement Sysmon 8 (CreateRemoteThread) et l'événement 10 (ProcessAccess) se déclencheront. Les produits EDR surveillent généralement l’injection inter-processus. Choisissez soigneusement le processus cible : l'injection dans un navigateur ou un processus Office est moins suspecte que l'injection dans notepad.exe.
shinject¶
Injectez du shellcode brut (à partir d'un fichier) dans un processus existant par PID. Contrairement à inject, qui génère un shellcode de beacon à partir d'un listener, shinject prend un shellcode arbitraire fourni par l'opérateur.
Type de tâche : inject (méthode : shinject)
Exemple :
OPSEC
Même profil OPSEC que inject. Le backend lit le fichier sur la machine de l'opérateur, l'encode en base64 et l'envoie au beacon pour injection. Le fichier shellcode ne touche jamais le disque cible.
dllinjecter¶
Injection de DLL réfléchissante via sRDI (injection de DLL réfléchissante Shellcode). La DLL est convertie en shellcode indépendant de la position qui se mappe en mémoire sans utiliser LoadLibrary, puis injectée dans le PID cible.
Type de tâche : inject (méthode : dllinject)
OPSEC
L'injection de DLL réfléchissante (T1055.001) charge une DLL en mémoire sans toucher au disque et sans appeler LoadLibrary. Cependant, la DLL injectée réside dans une mémoire exécutable non sauvegardée, que les analyseurs de mémoire peuvent signaler. Pour une exécution basée sur MEM_IMAGE, utilisez plutôt modulestomp comme technique d'injection.
Configuration¶
La technique d'injection par défaut et l'allocateur de mémoire sont configurés via le profil malléable au moment de la génération de le payload. Ces valeurs par défaut s'appliquent à toutes les opérations fork-and-run et peuvent être remplacées par beacon.
Paramètres de profil malléable¶
Le bloc process-inject dans le profil malléable contrôle le comportement d'injection :
| Paramètre | Valeurs | Par défaut | Description |
|---|---|---|---|
set-executemethod | CreateRemoteThread, SetThreadContext, RtlCreateUserThread, NtQueueApcThread-s | CreateRemoteThread | Méthode d'exécution de l'injection primaire |
set-allocator | VirtualAllocEx, NtMapViewOfSection | VirtualAllocEx | Stratégie d'allocation de mémoire |
set-min_alloc | Entier (octets) | 4096 | Taille d'allocation minimale (remplissage pour éviter les petites allocations qui se démarquent des scanners de mémoire) |
set-startrwx | true, false | false | Obsolète. Commencez avec les autorisations RWX. Stentor applique W^X (écriture XOR, exécution) quel que soit ce paramètre. |
set-bof_allocator | VirtualAlloc, MapViewOfFile, HeapAlloc | VirtualAlloc | Allocateur de mémoire pour l'exécution de BOF |
set-bof_reuse_memory | true, false | false | Réutiliser les allocations de mémoire BOF |
Exécuter le mappage de méthode¶
Les valeurs du profil malléable set-executemethod correspondent aux techniques d'injection Stentor :
| Valeur du profil | Technique du stentor | Remarques |
|---|---|---|
CreateRemoteThread | crt | Par défaut. Le plus compatible. |
SetThreadContext | setthreadctx | Détournement de threads (fork-and-run uniquement). |
RtlCreateUserThread | rtlthread | Alternative API NT au CRT. |
NtQueueApcThread-s | queueapc | APC anticipé (fork-and-run uniquement). |
Techniques avancées
Des techniques telles que tpdirect, tpstartroutinestub, earlycascade, obfsetthreadctx, cloneprocess et modulestomp sont sélectionnées par beacon via le remplacement de la technique d'injection dans les données de la tâche ou la configuration de génération, et non via la méthode d'exécution du profil malléable.
Paramètre MinAlloc¶
Le paramètre min_alloc assigne des allocations d'injection à une taille minimale. Les petites allocations de mémoire (par exemple, 4 Ko pour une petite payload de shellcode) sont inhabituelles et peuvent être signalées par les analyseurs de mémoire. En définissant min_alloc sur une valeur plus grande (par exemple, 16384 ou 65536), la taille de l'allocation se fond dans les allocations légitimes.
Remplacement par beacon¶
La technique d'injection peut être remplacée par beacon dans la tâche JSON :
Le champ technique accepte tout nom de technique enregistré du tableau de comparaison OPSEC ci-dessus.
Référence technique détaillée¶
Chaque technique ci-dessous inclut sa chaîne d'appels API, ses artefacts médico-légaux, ses limitations et le mappage MITRE ATT&CK.
CRT (Créer un thread distant)¶
Détails techniques : CRT
ID : crt MITRE ATT&CK : T1055.003 - Détournement de l'exécution des threads
Comment ça marche : Alloue de la mémoire dans le processus distant avec VirtualAllocEx(PAGE_READWRITE), copie le shellcode via WriteProcessMemory, modifie la protection en PAGE_EXECUTE_READ via VirtualProtectEx, puis crée un thread distant à l'adresse du shellcode avec CreateRemoteThread. Tous les appels API sont acheminés via BeaconGate lorsqu'ils sont activés.
Chaîne d'appels API :
VirtualAllocEx(processHandle, PAGE_READWRITE)WriteProcessMemory(processHandle, shellcode)VirtualProtectEx(processHandle, PAGE_EXECUTE_READ)CreateRemoteThread(processHandle, shellcodeAddr)
Artefacts médico-légaux :
- Événement Sysmon 8 : CreateRemoteThread détecté
- Événement Sysmon 10 : ProcessAccess avec PROCESS_VM_WRITE
- Mémoire : transition de protection RW -> RX dans le processus cible
- ETW : création de thread à partir d'un processus parent inattendu
Limites : Technique la plus surveillée. Chaque produit EDR majeur détecte CreateRemoteThread des appelants non standard. À utiliser uniquement dans des environnements de laboratoire ou lorsque la détection n'est pas un problème.
Prend en charge InjectByPID : Oui - ouvre le processus par PID, injecte, ferme le handle.
Prend en charge InjectByHandle : Oui - injection directe avec le handle de processus existant.
NtMapViewOfSection¶
Détails techniques : NtMapViewOfSection
ID : ntmap MITRE ATT&CK: T1055.012 - Procédé Creux (variante)
Comment ça marche : Crée une section de mémoire partagée sauvegardée par le fichier d'échange à l'aide de NtCreateSection, mappe une vue inscriptible dans le processus de beacon (NtMapViewOfSection avec PAGE_READWRITE), copie le shellcode dans la vue locale, mappe une vue exécutable dans le processus cible (PAGE_EXECUTE_READ), démappe la vue locale, puis s'exécute via RtlCreateUserThread.
Chaîne d'appels API :
NtCreateSection(PAGE_EXECUTE_READWRITE)-- protection maximale de la section, pas protection de la pageNtMapViewOfSection(local, PAGE_READWRITE)-- vue inscriptible dans le beaconmemcpyvers la vue localeNtMapViewOfSection(remote, PAGE_EXECUTE_READ)-- vue exécutable dans la cibleNtUnmapViewOfSection(local)-- nettoyageRtlCreateUserThread(remote, shellcodeAddr)
Artefacts médico-légaux :
- Création d'objet de section (visible dans le gestionnaire d'objets du noyau)
- Vue mappée dans le processus cible (pas d'artefact VirtualAllocEx)
- Création de thread via RtlCreateUserThread (différent de CRT dans ETW)
Limitations : Les objets de section peuvent être visibles par les analyseurs de mémoire avancés. La protection maximale de la section est PAGE_EXECUTE_READWRITE (requis pour la technique), bien que les protections réelles des pages ne soient jamais RWX.
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
DéfinirThreadContext¶
Détails techniques : SetThreadContext
ID : setthreadctx MITRE ATT&CK : T1055.003 - Détournement de l'exécution des threads
Comment ça marche : Alloue et écrit le shellcode au processus distant, puis trouve le thread principal du processus enfant suspendu (fork-and-run). Ouvre le thread, appelle GetThreadContext pour capturer l'état actuel du registre, modifie RIP pour pointer vers l'adresse du shellcode et l'applique avec SetThreadContext. Lorsque l'appelant reprend le thread, il exécute le shellcode au lieu du point d'entrée d'origine.
**Chaîne d'appels API :**
1. `VirtualAllocEx` + `WriteProcessMemory` + `VirtualProtectEx`
2. `GetThreadContext(threadHandle, CONTEXT_CONTROL)`
3. Définir `ctx.Rip = shellcodeAddr`
4. `SetThreadContext(threadHandle, ctx)`
5. L'appelant appelle `ResumeThread`
**Artefacts médico-légaux :**
- Mémoire : transition RW -> RX dans le processus cible
- Modification du contexte du thread (détectable via ETW)
- Aucun artefact CreateRemoteThread
**Limitations :** Fonctionne uniquement avec fork-and-run (nécessite un thread principal suspendu). InjectByPID revient à CRT car le piratage de threads dans les processus en cours d'exécution n'est pas fiable : le thread peut détenir des verrous ou être en mode noyau.
**Prend en charge InjectByPID :** Revient au CRT.
**Prend en charge InjectByHandle :** Oui (fork-and-run uniquement).
QueueUserAPC¶
Détails techniques : QueueUserAPC
ID : queueapc MITRE ATT&CK : T1055.004 - Appel de procédure asynchrone
Comment ça marche : Alloue et écrit le shellcode, trouve le thread principal du processus enfant suspendu, ouvre le thread et met en file d'attente un APC pointant vers l'adresse du shellcode via QueueUserAPC. Lorsque l'appelant reprend le thread, l'APC se déclenche avant le point d'entrée normal du thread - c'est le modèle « early-bird ».
Chaîne d'appels API :
VirtualAllocEx+WriteProcessMemory+VirtualProtectExOpenThread(THREAD_SET_CONTEXT)QueueUserAPC(shellcodeAddr, threadHandle)- L'appelant appelle
ResumeThread-- APC se déclenche en premier
Artefacts médico-légaux :
- Mémoire : transition RW -> RX dans le processus cible
- Modification de la file d'attente APC (visible dans les structures du noyau)
- Aucun artefact CreateRemoteThread
- Early-bird : le shellcode s'exécute avant le point d'entrée du processus
Limitations : Fonctionne de manière fiable uniquement avec fork-and-run (modèle de lève-tôt). Pour InjectByPID, la technique revient à CRT car APC sur les threads existants nécessite un état d'attente pouvant être alerté (SleepEx, WaitForMultipleObjectsEx), qui n'est pas fiable pour les processus arbitraires.
Prend en charge InjectByPID : Revient au CRT. Prend en charge InjectByHandle : Oui (fork-and-run uniquement).
RtlCreateUserThread¶
Détails techniques : RtlCreateUserThread
ID : rtlthread MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Allocation de mémoire et écriture standard, puis crée un thread distant en utilisant RtlCreateUserThread de ntdll au lieu de CreateRemoteThread de kernel32. Cela contourne les hooks du mode utilisateur que les produits EDR placent sur les exportations kernel32.dll.
Chaîne d'appels API :
VirtualAllocEx+WriteProcessMemory+VirtualProtectExRtlCreateUserThread(processHandle, shellcodeAddr)
Artefacts médico-légaux :
- Mémoire : transition RW -> RX dans le processus cible
- Création de thread via l'API NT (événement ETW différent du kernel32 CRT)
- Adresse de début du thread dans la mémoire du processus distant
Limitations : Bien qu'elle contourne les hooks kernel32, l'instrumentation ETW au niveau du noyau enregistre toujours la création du thread. Moins évasive que les techniques qui évitent complètement la création de threads.
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
Auto-injection¶
Détails techniques : SelfInject
ID : selfinject MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Alloue de la mémoire dans le processus (beacon) en cours avec VirtualAlloc(PAGE_READWRITE), copie le shellcode, modifie la protection en PAGE_EXECUTE_READ, puis crée un thread local avec CreateThread. Lorsque le transfert par chargement goutte à goutte est activé, utilise DripAlloc pour l'allocation fragmentée de réserve puis de validation afin de réduire les artefacts d'allocation.
**Chaîne d'appels API :**
1. `VirtualAlloc(MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)` -- ou `DripAlloc` si activé
2. `memcpy(shellcode)`
3. `VirtualProtect(PAGE_EXECUTE_READ)` -- ou `DripProtect`
4. `CreateThread(shellcodeAddr)`
**Artefacts médico-légaux :**
- Mémoire : transition RW -> RX dans le processus en cours
- Création d'un nouveau thread (visible dans ETW)
- Aucune implication de processus à distance (pas d'événement Sysmon 8/10)
**Limitations :** Le shellcode s'exécute dans le processus de beacon. Si le shellcode plante, le beacon plante. Impossible d'injecter dans des processus distants -- `InjectByHandle` renvoie une erreur, `InjectByPID` n'accepte que le PID du processus actuel.
**Prend en charge InjectByPID :** Uniquement si le PID correspond au processus en cours.
**Prend en charge InjectByHandle :** Non (renvoie une erreur).
UDRL (chargeur réfléchissant défini par l'utilisateur)¶
Détails techniques : UDRL
ID : udrl MITRE ATT&CK : T1620 - Chargement de code réfléchissant
Comment ça marche : L'opérateur fournit un shellcode de chargeur réfléchissant personnalisé via un script d'agresseur (SetUDRL()). Le chargeur est ajouté au début de le payload du beacon. Lors de l'injection, le payload combinée (chargeur + beacon) est écrite dans le processus cible. Le thread distant démarre au point d'entrée du chargeur, qui gère son propre mappage PE, sa résolution d'importation et sa relocalisation - en contournant complètement la détection LoadLibrary standard.
Chaîne d'appels API :
- Ajouter le shellcode du chargeur à le payload du beacon
VirtualAllocEx(PAGE_READWRITE)via BeaconGateWriteProcessMemory(loader + beacon)via BeaconGate- Suivre les régions dans BUD (Beacon User Data) pour le masque de sommeil
VirtualProtectEx(PAGE_EXECUTE_READ)via BeaconGateCreateRemoteThread(loaderAddr)via BeaconGate
Artefacts médico-légaux :
- Mémoire exécutable non sauvegardée (pas de fichier correspondant sur le disque)
- Anomalies d'en-tête PE (le chargeur personnalisé peut omettre/modifier les en-têtes)
- La disposition de la mémoire diffère du chargeur PE standard
- Contrôlé par l'opérateur : les artefacts varient selon l'implémentation du chargeur
Limitations : Non enregistré par défaut - disponible uniquement lorsque l'opérateur fournit le shellcode du chargeur au moment de l'exécution via SetUDRL(). La qualité et la furtivité du chargeur dépendent entièrement de la mise en œuvre de l'opérateur. Si le chargeur nécessite RWX pour l'auto-modification, la configuration UseRWX peut être définie, mais cela dégrade OPSEC.
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
SetThreadContext obscurci¶
Détails techniques : SetThreadContext obscurci
ID : obfsetthreadctx MITRE ATT&CK : T1055.003 - Détournement de l'exécution des threads
Comment ça marche : Contrairement au SetThreadContext standard qui détourne un thread existant, cette technique crée un NOUVEAU thread à une adresse de fonction légitime (par exemple, ntdll!RtlUserThreadStart+0x21) en utilisant CreateRemoteThread avec CREATE_SUSPENDED. L'adresse de début du thread semble légitime pour les outils EDR qui analysent les origines des threads. Après la création, GetThreadContext capture l'état complet du registre, RIP est modifié pour pointer vers le shellcode, SetThreadContext applique la modification et ResumeThread exécute le shellcode.
Chaîne d'appels API :
VirtualAllocEx+WriteProcessMemory+VirtualProtectEx- Résoudre
ntdll!RtlUserThreadStart+0x21dans le processus distant CreateRemoteThread(processHandle, legitimateAddr, CREATE_SUSPENDED)GetThreadContext(threadHandle, CONTEXT_FULL)- Définir
ctx.Rip = shellcodeAddr SetThreadContext(threadHandle, ctx)ResumeThread(threadHandle)
Artefacts médico-légaux :
- Sujet créé à une adresse légitime basée sur une image (plus difficile à détecter)
- Mémoire : transition RW -> RX dans le processus cible
- Modification du contexte du thread (détectable via ETW)
- Appel CreateRemoteThread présent, mais l'adresse de départ semble légitime
Limitations : Nécessite ntdll ou kernel32 pour une résolution d'adresses inter-processus fiable (ASLR est par démarrage pour les DLL système, donc les adresses correspondent entre les processus). Les autres modules ne sont pas pris en charge pour l'adresse de départ.
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
Processus de clonage¶
Détails techniques : CloneProcess
ID : cloneprocess MITRE ATT&CK: T1055.012 - Procédé Creux (variante)
Comment ça marche : Utilise RtlCloneUserProcess pour créer une copie d'un processus cible avec un thread principal suspendu. Le shellcode est écrit dans le clone à l'aide d'une allocation standard, puis un appel QueueUserAPC cible le thread principal du clone. Lorsque ResumeThread est appelé, l'APC se déclenche et le shellcode s'exécute dans le processus cloné. Cela évite de créer des threads distants dans les processus existants.
Chaîne d'appels API :
RtlCloneUserProcess(CREATE_SUSPENDED | NO_SYNCHRONIZE)- Extraire les poignées de processus/thread de clonage
VirtualAllocEx+WriteProcessMemory+VirtualProtectExdans le cloneQueueUserAPC(shellcodeAddr, cloneThread)ResumeThread(cloneThread)
Artefacts médico-légaux :
- Création de clone de processus (appel
RtlCloneUserProcessinhabituel) - Mémoire : transition RW -> RX dans un processus cloné
- Modification de la file d'attente APC sur le thread principal du clone
- Aucun artefact CreateRemoteThread dans les processus existants
Limitations : Nécessite Windows 10+ (disponibilité RtlCloneUserProcess). Revient au CRT sur les anciennes versions. Le processus cloné est une copie du processus en cours, ce qui peut être suspect si le beacon s'exécute comme un exécutable inhabituel.
Prend en charge InjectByPID : Oui (ouvre le processus, puis clone). Prend en charge InjectByHandle : Oui.
TP_DIRECT (pool de threads direct)¶
Détails techniques : TP_DIRECT
ID : tpdirect MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Basé sur la recherche PoolParty de SafeBreach Labs. Alloue le shellcode dans le processus distant, puis crée une fausse structure TP_DIRECT avec son pointeur de rappel au décalage 0x08 pointant vers l'adresse du shellcode. Le shellcode (RX) et la structure TP_DIRECT (RW) sont écrits dans le processus cible. Un thread distant est créé pour s'exécuter via le chemin de rappel du pool de threads, faisant apparaître l'exécution comme un élément de travail légitime du pool de threads.
Chaîne d'appels API :
VirtualAllocEx+WriteProcessMemory+VirtualProtectEx(shellcode, RX)- Construire une fausse structure
TP_DIRECT(rappel = adresse du shellcode) VirtualAllocEx(PAGE_READWRITE)pour la structure TP_DIRECTWriteProcessMemory(TP_DIRECT vers la cible)CreateRemoteThread(shellcodeAddr, tpDirectAddr)-- répartition du pool de threads
Artefacts médico-légaux :
- Mémoire : transition RW -> RX pour le shellcode
- Allocation RW supplémentaire pour la fausse structure TP_DIRECT
- Création de threads à distance ciblant l'infrastructure du pool de threads
- L'exécution du rappel du pool de threads apparaît comme une activité de travail légitime
Limitations : La disposition de la structure TP_DIRECT est spécifique à la version (rappel au décalage 0x08 sous Windows 10/11 x64). Peut tomber en panne sur les futures versions de Windows si la disposition de la structure interne change.
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
DébutCascade¶
Détails techniques : EarlyCascade
ID : earlycascade MITRE ATT&CK: T1055.012 - Procédé Creux (variante)
Comment ça marche : Crée un processus dans un état suspendu (CREATE_SUSPENDED | CREATE_NO_WINDOW) et détourne son chemin d'initialisation avant le chargement de toute DLL. À ce stade, RIP pointe vers RtlUserThreadStart ou ntdll!LdrInitializeThunk -- la toute première instruction du mode utilisateur. La technique écrit le shellcode, modifie RIP via SetThreadContext et l'appelant reprend le thread. Le shellcode s'exécute dans la fenêtre « première cascade » avant l'initialisation de ntdll, le chargement de DLL, les rappels TLS ou tout hook du mode utilisateur sont actifs.
**Chaîne d'appels API :**
1. `VirtualAllocEx` + `WriteProcessMemory` + `VirtualProtectEx`
2. `GetThreadContext(CONTEXT_CONTROL)` -- capture RIP avant l'exécution de tout code
3. Définir `ctx.Rip = shellcodeAddr`
4. `SetThreadContext(threadHandle, ctx)`
5. `ResumeThread` -- le shellcode s'exécute avant l'initialisation de ntdll
Pour `InjectByPID`, la technique en plus :
1. `CreateProcessW(rundll32.exe, CREATE_SUSPENDED | CREATE_NO_WINDOW)`
2. Injecter via `InjectByHandle`
3. `ResumeThread`
**Artefacts médico-légaux :**
- Création de processus suspendue (indicateur `CREATE_SUSPENDED`)
- Mémoire : transition RW -> RX dans le processus cible
- Modification du contexte du thread avant la première instruction
- Le point d'entrée ne s'exécute jamais (se distingue de l'exécution normale)
**Limitations :** Pour `InjectByPID`, utilise `rundll32.exe` comme processus sacrificiel par défaut. Cela peut être personnalisé via la configuration de spawn-to. Si l’injection échoue, le processus suspendu est terminé pour éviter les processus orphelins.
**Prend en charge InjectByPID :** Oui (crée un nouveau processus suspendu).
**Prend en charge InjectByHandle :** Oui (fork-and-run).
TpStartRoutineStub¶
Détails techniques : TpStartRoutineStub
ID : tpstartroutinestub MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Basé sur la variante 7 de PoolParty (SafeBreach Labs). Crée une fausse structure TP_WORK dont le pointeur CleanupGroupMember.Callback (au décalage 0x40) pointe vers le shellcode. Le champ Task LIST_ENTRY (au décalage 0x20) est initialisé en tant que liste à double lien auto-référencée pour éviter les plantages. La structure est écrite dans le processus cible et un thread distant est créé avec le shellcode comme point d'entrée et le pointeur TP_WORK comme paramètre, simulant la façon dont TppWorkerThread distribue les éléments de travail via TpStartRoutineStub.
Chaîne d'appels API :
VirtualAllocEx+WriteProcessMemory+VirtualProtectEx(shellcode, RX)- Construisez une fausse structure
TP_WORK(0x68 octets) :- Décalage 0x20 : tâche LIST_ENTRY (Flink/Blink auto-référencé)
- Décalage 0x40 : CleanupGroupMember.Callback = adresse du shellcode
VirtualAllocEx(PAGE_READWRITE)pour la structure TP_WORKWriteProcessMemory(TP_WORK vers la cible)CreateRemoteThread(shellcodeAddr, tpWorkAddr)-- répartition des travailleurs
Artefacts médico-légaux :
- Mémoire : transition RW -> RX pour le shellcode
- Allocation RW supplémentaire pour la fausse structure TP_WORK
- Création de threads à distance ciblant l'infrastructure du pool de threads
- L’exécution de l’élément de travail du pool de threads apparaît comme une activité de travail légitime
Limitations : La disposition de la structure TP_WORK est spécifique à la version (rappel au décalage 0x40, tâche au décalage 0x20 sous Windows 10/11 x64). Contrairement à tpdirect qui manipule les structures de pool existantes, cette technique crée de nouveaux éléments de travail, qui peuvent être détectables par une surveillance avancée en mode noyau.
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
Module piétinant¶
Détails techniques : Module Stomping
ID : modulestomp MITRE ATT&CK : T1055.001 - Injection de bibliothèque de liens dynamiques (variante)
Comment ça marche : Charge une DLL signée légitime dans le processus distant via CreateRemoteThread(LoadLibraryW), puis écrase sa section .text avec le shellcode. Le résultat est un shellcode soutenu par la mémoire MEM_IMAGE qui semble résider dans un module chargé légitime. Cela élimine les scanners de mémoire qui signalent la mémoire exécutable non sauvegardée.
**Chaîne d'appels API :**
1. Charger la DLL localement pour analyser l'en-tête PE (trouver le décalage et la taille .text)
2. Écrire le chemin de la DLL (UTF-16) vers le processus distant
3. `CreateRemoteThread(LoadLibraryW, pathAddr)` -- charger la DLL dans la cible
4. `WaitForSingleObject` (attendre le chargement de la DLL)
5. Énumérer les modules distants pour trouver l'adresse de base de la DLL
6. `VirtualProtectEx(.text, PAGE_READWRITE)`
7. `WriteProcessMemory(.text, shellcode)`
8. `VirtualProtectEx(.text, PAGE_EXECUTE_READ)`
9. Nettoyer la mémoire du chemin distant
**Artefacts médico-légaux :**
- Chargement de DLL dans un processus distant (DLL légitime et signée)
- Modification de la protection de la mémoire sur la section .text
- Le shellcode apparaît sous la forme MEM_IMAGE soutenu par le module signé
- Thread distant pour LoadLibraryW (modèle d'API commun)
**Limitations :** La section .text de la DLL doit être suffisamment grande pour contenir le shellcode. La DLL est configurée via l'option d'évasion `module_stomp_dll` (par défaut : `xpsservices.dll`). La technique utilise CreateRemoteThread pour l'appel LoadLibraryW initial, qui est détectable.
**Configuration :** Définissez la DLL piétinée via la configuration d'évasion :
```json
{
"module_stomp_dll": "xpsservices.dll"
}
```
**Prend en charge InjectByPID :** Géré via `allocAndWriteModuleStomp` + injecteur par défaut.
**Prend en charge InjectByHandle :** Géré via `allocAndWriteModuleStomp` + exécution de thread.
Injection de DLL (sRDI)¶
Détails techniques : injection de DLL via sRDI
ID : dllinject MITRE ATT&CK : T1055.001 - Injection de bibliothèque de liens dynamiques
Comment ça marche : Convertit une DLL en shellcode indépendant de la position à l'aide de la technique sRDI (Shellcode Reflective DLL Injection). Le stub de shellcode gère le mappage PE, la résolution d’importation et la relocalisation entièrement en mémoire – aucun appel LoadLibrary n’est effectué. Le shellcode converti est ensuite injecté à l'aide de la technique d'injection par défaut (CRT).
Chaîne d'appels API :
- Valider l'en-tête PE (vérification MZ)
- Convertir la DLL en shellcode via sRDI
- Injecter le shellcode à l'aide de l'injecteur par défaut (
InjectByPID)
Artefacts médico-légaux :
- Mémoire exécutable non sauvegardée (DLL mappée sans LoadLibrary)
- L'en-tête PE peut être présent en mémoire (détectable par les scanners de mémoire)
- Les artefacts d'injection dépendent de la technique sous-jacente (par défaut : CRT)
Limitations : La DLL est spécifiée par l'opérateur via la commande dllinject. La conversion sRDI ajoute un stub de shellcode qui gère le chargement réfléchissant. La technique d'injection sous-jacente est toujours celle par défaut (CRT) et ne peut pas être remplacée pour l'injection de DLL.
Prend en charge InjectByPID : Oui (via l'injecteur par défaut après la conversion sRDI). Prend en charge InjectByHandle : Non (commande autonome uniquement).
Injection sans fil¶
Détails techniques : injection sans filetage
ID : threadless MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Accroche une fonction exportée dans le processus cible en écrivant un trampoline (enregistrer les registres + appeler le shellcode + jmp à la fonction d'origine) sur le point d'entrée de la fonction. Lorsque le processus cible appelle naturellement la fonction hookée, le trampoline redirige l'exécution vers le shellcode. Aucun thread n'est jamais créé dans le processus cible - l'exécution s'appuie sur les threads existants. Cible de hook par défaut : ntdll!RtlExitUserProcess.
Chaîne d'appels API :
- Résoudre l'adresse de fonction exportée dans un processus distant
- Lire les octets de fonction d'origine (pour le retour du trampoline)
VirtualAllocEx(RW) pour shellcode + trampoline- Construire un trampoline : pousser les registres, appeler le shellcode, restaurer les registres, jmp original
WriteProcessMemory(shellcode + trampoline)VirtualProtectEx(RW -> RX)WriteProcessMemorypour écraser l'entrée de fonction avec jmp sur le trampoline
Artefacts médico-légaux :
- Prologue de fonction modifié dans le processus cible (détectable par des contrôles d'intégrité du code)
- Mémoire : transition RW -> RX pour l'allocation du shellcode
- Aucun artefact CreateRemoteThread ou APC
- Aucun nouvel événement de création de thread (Sysmon Event 8 absent)
Limitations : La fonction hookée doit être appelée par le processus cible pour que le shellcode puisse s'exécuter. Le timing n’est pas déterministe. La cible par défaut RtlExitUserProcess se déclenche à la sortie du processus, ce qui peut ne pas être immédiat. Choisissez une exportation fréquemment appelée pour un déclenchement plus rapide.
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
Processus de creusement¶
Détails techniques : Processus de creusement
ID : hollowing MITRE ATT&CK : T1055.012 - Processus de creusement
Comment ça marche : Crée un nouveau processus en état suspendu (CREATE_SUSPENDED | CREATE_NO_WINDOW), puis remplace sa mémoire image par un shellcode. Le RIP du thread principal est redirigé vers le shellcode via SetThreadContext et le thread reprend. Le shellcode s'exécute comme le fil principal d'un processus apparemment légitime. Processus sacrificiel par défaut : svchost.exe.
Chaîne d'appels API :
CreateProcessW(sacrificialProcess, CREATE_SUSPENDED | CREATE_NO_WINDOW)VirtualAllocEx+WriteProcessMemory+VirtualProtectEx(shellcode, RX)GetThreadContext(CONTEXT_FULL)sur le fil principal- Définir
ctx.Rip = shellcodeAddr SetThreadContext(mainThread, ctx)ResumeThread(mainThread)
Artefacts médico-légaux :
- Création de processus suspendu (indicateur CREATE_SUSPENDED)
- Modification du contexte du thread sur le thread principal
- Mémoire : transition RW -> RX en processus creux
- Incompatibilité d'image de processus (le contenu de la mémoire ne correspond pas au binaire du disque)
Limitations : Les produits EDR qui comparent la mémoire de processus à l'image sur disque détecteront la non-concordance. Le processus sacrificiel peut être configuré via les paramètres d'apparition. Si l’injection échoue, le processus suspendu est terminé pour éviter les orphelins.
Prend en charge InjectByPID : Oui (crée un nouveau processus suspendu). Prend en charge InjectByHandle : Oui.
PoolParty : Insertion d'éléments de travail¶
Détails techniques : élément de travail PoolParty (poolparty_workitem)
ID : poolparty_workitem MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Basé sur la recherche PoolParty de SafeBreach Labs. Localise le handle d'usine de travail du pool de threads du processus cible via NtQuerySystemInformation, puis insère un faux élément TP_WORK pointant vers le shellcode. Lorsque le pool de threads distribue l'élément de travail suivant, le shellcode s'exécute en tant que rappel légitime du travailleur du pool de threads.
Chaîne d'appels API :
NtQuerySystemInformation(SystemHandleInformation)pour trouver le handle de l'usine du travailleurVirtualAllocEx+WriteProcessMemory+VirtualProtectEx(shellcode, RX)- Construire une fausse structure
TP_WORKavec rappel → adresse shellcode VirtualAllocEx(PAGE_READWRITE)pour la structure TP_WORKWriteProcessMemory(TP_WORK vers la cible)- Insérer un élément de travail dans la file d'attente du pool de threads via
NtSetInformationWorkerFactory
Artefacts médico-légaux :
- Non CreateRemoteThread - exécution via la répartition du pool de threads
- Mémoire : transition RW -> RX pour le shellcode
- Allocation RW supplémentaire pour la structure TP_WORK
- L'activité du pool de threads apparaît comme une exécution légitime du travailleur
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
PoolParty : minuterie¶
Détails techniques : PoolParty Timer (poolparty_timer)
ID : poolparty_timer MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Semblable à l'insertion d'éléments de travail, mais utilise le mécanisme de minuterie du pool de threads. Crée une fausse structure TP_TIMER avec le rappel pointant vers le shellcode et l'insère dans la file d'attente du minuteur de la cible. Lorsque le minuteur se déclenche, le pool de threads distribue le rappel, exécutant le shellcode.
**Chaîne d'appels API :**
1. `NtQuerySystemInformation(SystemHandleInformation)` pour trouver le handle de l'usine du travailleur
2. `VirtualAllocEx` + `WriteProcessMemory` + `VirtualProtectEx` (shellcode, RX)
3. Construire une fausse structure `TP_TIMER` avec rappel → adresse shellcode
4. Écrire la structure dans le processus cible
5. Insérer un minuteur dans la file d'attente du minuteur du pool de threads
**Artefacts médico-légaux :**
- Aucun artefact CreateRemoteThread
- L'exécution du rappel du minuteur apparaît comme une activité légitime du minuteur du pool de threads
- Mémoire : transition RW -> RX pour le shellcode
**Prend en charge InjectByPID :** Oui.
**Prend en charge InjectByHandle :** Oui.
PoolParty : achèvement des E/S¶
Détails techniques : E/S PoolParty (poolparty_io)
ID : poolparty_io MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Utilise le mécanisme d'achèvement des E/S du pool de threads. Crée une fausse structure TP_IO avec le rappel pointant vers le shellcode et l'associe à un port d'achèvement d'E/S dans le processus cible. Lorsqu'un paquet de fin d'E/S arrive, le pool de threads distribue le rappel.
Chaîne d'appels API :
NtQuerySystemInformation(SystemHandleInformation)pour trouver le handle du port de fin d'E/SVirtualAllocEx+WriteProcessMemory+VirtualProtectEx(shellcode, RX)- Construire une fausse structure
TP_IOavec rappel → adresse shellcode - Écrire la structure dans le processus cible
- Mettre en file d'attente le paquet d'achèvement d'E/S pour déclencher le rappel
Artefacts médico-légaux :
- Aucun artefact CreateRemoteThread
- Le rappel d'achèvement des E/S apparaît comme une gestion légitime des E/S asynchrones
- Mémoire : transition RW -> RX pour le shellcode
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
PoolParty : port ALPC¶
Détails techniques : PoolParty ALPC (poolparty_alpc)
ID : poolparty_alpc MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Utilise le mécanisme ALPC (Advanced Local Procedure Call) du pool de threads. Crée une fausse structure TP_ALPC avec le rappel pointant vers le shellcode et l'associe à un port ALPC dans le processus cible. Lorsqu'un message ALPC arrive sur le port, le pool de threads distribue le rappel.
Chaîne d'appels API :
NtQuerySystemInformation(SystemHandleInformation)pour trouver le handle du port ALPCVirtualAllocEx+WriteProcessMemory+VirtualProtectEx(shellcode, RX)- Construire une fausse structure
TP_ALPCavec rappel → adresse shellcode - Écrire la structure dans le processus cible
- Envoyer un message ALPC pour déclencher l'envoi de rappel
Artefacts médico-légaux :
- Aucun artefact CreateRemoteThread
- Le rappel ALPC apparaît comme une gestion légitime des communications inter-processus
- Mémoire : transition RW -> RX pour le shellcode
Prend en charge InjectByPID : Oui. Prend en charge InjectByHandle : Oui.
Rappel : EnumFontFamiliesEx¶
Détails techniques : rappel de l'énumération des polices (cb_fontenum)
ID : cb_fontenum MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Utilise l'API Windows GDI EnumFontFamiliesExW comme déclencheur de shellcode. Crée un processus suspendu, y écrit du shellcode, puis crée un thread distant qui appelle EnumFontFamiliesExW avec l'adresse du shellcode comme paramètre de rappel. Lorsque GDI énumère les polices, il appelle le rappel (shellcode) pour chaque famille de polices.
Chaîne d'appels API :
CreateProcessW(sacrificialProcess, CREATE_SUSPENDED | CREATE_NO_WINDOW)VirtualAllocEx+WriteProcessMemory+VirtualProtectEx(shellcode, RX)GetThreadContext→ modifierRIPpour pointer vers le stubEnumFontFamiliesExW- Appels
EnumFontFamiliesExW(NULL, NULL, shellcodeAddr, 0) ResumeThread-- L'énumération des polices GDI déclenche le rappel du shellcode
Artefacts médico-légaux :
- Création de processus suspendue
- L'appel API GDI semble légitime (l'énumération des polices est courante)
- Mémoire : transition RW -> RX pour le shellcode
- Modification du contexte du thread
Prend en charge InjectByPID : Oui (crée un nouveau processus suspendu). Prend en charge InjectByHandle : Oui.
Rappel : file d'attente du minuteur¶
Détails techniques : rappel de la file d'attente du minuteur (cb_timer)
ID : cb_timer MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Utilise CreateTimerQueueTimer comme déclencheur de shellcode. Crée un processus suspendu, écrit le shellcode, puis redirige l'exécution vers un stub qui appelle CreateTimerQueueTimer avec l'adresse du shellcode comme rappel du minuteur. Le minuteur se déclenche immédiatement (période d'échéance = 0), exécutant le shellcode.
Chaîne d'appels API :
CreateProcessW(sacrificialProcess, CREATE_SUSPENDED | CREATE_NO_WINDOW)VirtualAllocEx+WriteProcessMemory+VirtualProtectEx(shellcode, RX)GetThreadContext→ modifierRIPpour pointer vers le stubCreateTimerQueueTimer- Appels
CreateTimerQueueTimer(NULL, NULL, shellcodeAddr, NULL, 0, 0, WT_EXECUTEDEFAULT) ResumeThread-- le minuteur se déclenche immédiatement, déclenchant le rappel du shellcode
Artefacts médico-légaux :
- Création de processus suspendue
- Création de file d'attente de minuterie (modèle d'API Windows légitime)
- Mémoire : transition RW -> RX pour le shellcode
- Modification du contexte du thread
Prend en charge InjectByPID : Oui (crée un nouveau processus suspendu). Prend en charge InjectByHandle : Oui.
Rappel : EnumWindows¶
Détails techniques : rappel d'énumération de fenêtre (cb_winenum)
ID : cb_winenum MITRE ATT&CK : T1055 - Injection de procédé
Comment ça marche : Utilise l'API EnumWindows comme déclencheur de shellcode. Crée un processus suspendu, écrit le shellcode, puis redirige l'exécution vers un stub qui appelle EnumWindows avec l'adresse du shellcode comme rappel d'énumération. Lorsque user32 énumère les fenêtres de niveau supérieur, il appelle le rappel (shellcode) pour chaque fenêtre.
Chaîne d'appels API :
CreateProcessW(sacrificialProcess, CREATE_SUSPENDED | CREATE_NO_WINDOW)VirtualAllocEx+WriteProcessMemory+VirtualProtectEx(shellcode, RX)GetThreadContext→ modifierRIPpour pointer vers le stubEnumWindows- Appels
EnumWindows(shellcodeAddr, 0) ResumeThread-- l'énumération de la fenêtre déclenche le rappel du shellcode
Artefacts médico-légaux :
- Création de processus suspendue
- Appel d'API d'énumération de fenêtre (activité user32 courante)
- Mémoire : transition RW -> RX pour le shellcode
- Modification du contexte du thread
Prend en charge InjectByPID : Oui (crée un nouveau processus suspendu). Prend en charge InjectByHandle : Oui.