Chasser la persistance Windows : registre, tâches, WMI
Détecter la persistance d'un attaquant sous Windows : clés Run, services, tâches planifiées, WMI, Winlogon, IFEO, COM et BITS, avec MITRE ATT&CK et outils.
Une fois entrés, les attaquants s'assurent de pouvoir revenir après un redémarrage, un changement de mot de passe ou le correctif d'une vulnérabilité. Ce guide passe en revue les emplacements de démarrage automatique les plus utilisés dans les intrusions Windows, rattache chacun à sa technique MITRE ATT&CK et indique où regarder sur un hôte vivant ou sur une image disque. Vous repartirez avec une méthode de triage reproductible et un moyen de distinguer une vraie persistance des centaines d'autostarts légitimes d'une machine ordinaire.
Cartographie de la persistance
| Mécanisme | ATT&CK | Emplacement principal | Journaux clés |
|---|---|---|---|
| Clés Run / RunOnce | T1547.001 | SOFTWARE et NTUSER.DAT : ...\CurrentVersion\Run, RunOnce | Sysmon 13 |
| Dossiers Startup | T1547.001 | ...\Start Menu\Programs\Startup (par utilisateur et tous utilisateurs) | Sysmon 11 |
| Services Windows | T1543.003 | SYSTEM\ControlSet00x\Services\<nom> | 7045, 4697 |
| Tâches planifiées | T1053.005 | C:\Windows\System32\Tasks, TaskCache dans SOFTWARE | 4698, TaskScheduler 106/140/200 |
| Abonnement d'événements WMI | T1546.003 | C:\Windows\System32\wbem\Repository\OBJECTS.DATA | WMI-Activity 5861, Sysmon 19-21 |
| Winlogon Userinit / Shell | T1547.004 | SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon | Sysmon 13 |
| IFEO Debugger, SilentProcessExit | T1546.012 | ...\Image File Execution Options\<exe>, ...\SilentProcessExit\<exe> | Sysmon 13 |
| AppInit_DLLs | T1546.010 | SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows | Sysmon 13 |
| Détournement COM | T1546.015 | UsrClass.dat : Software\Classes\CLSID\{GUID} | Sysmon 13 |
| Jobs BITS | T1197 | C:\ProgramData\Microsoft\Network\Downloader\ | Bits-Client 3/59/60 |
| Fonctions d'accessibilité | T1546.008 | System32\sethc.exe, utilman.exe ou leurs clés IFEO | Prefetch, hashes de fichiers, Sysmon 1 |
| Création de compte local | T1136.001 | Ruche SAM | 4720, 4722, 4732 |
| Détournement de l'ordre de recherche des DLL | T1574.001 | Dossiers applicatifs, entrées du PATH accessibles en écriture | Sysmon 7 |
Les IDs ATT&CK sont à jour au moment de la rédaction, mais MITRE renomme ou fusionne parfois des sous-techniques (les versions récentes ont par exemple élargi T1574.001 pour y inclure le DLL side-loading). Vérifiez sur attack.mitre.org avant de citer des IDs dans un rapport.
Autostarts dans le registre
Clés Run et RunOnce
Le grand classique. Les valeurs sous ces clés se lancent à l'ouverture de session :
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Runet\RunOnce(tous les utilisateurs)HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Runet\RunOnce(vue 32 bits sur Windows 64 bits)HKCU\Software\Microsoft\Windows\CurrentVersion\Runet\RunOnce, stockées dans le NTUSER.DAT de chaque utilisateur...\Policies\Explorer\Run, normalement écrite uniquement par les stratégies de groupe
Les valeurs RunOnce sont supprimées avant leur exécution (sauf si elles sont préfixées par !) : une charge à usage unique peut donc ne laisser aucune trace dans la ruche. Les valeurs elles-mêmes n'ont pas d'horodatage ; la seule date disponible est le last write time de la clé, qui reflète la dernière modification de n'importe quelle valeur de cette clé. Depuis Windows 8, Explorer\StartupApproved\Run indique si une entrée est activée ou désactivée dans le Gestionnaire des tâches. Le détail est sur la fiche clés Run et dossiers Startup.
Winlogon : Userinit et Shell
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon contient Userinit (par défaut C:\Windows\system32\userinit.exe, avec une virgule finale) et Shell (par défaut explorer.exe). Tout ce qui est ajouté à ces valeurs s'exécute à chaque ouverture de session interactive. Une valeur Shell propre à l'utilisateur, dans NTUSER.DAT sous le même chemin, est aussi prise en compte. Comparez les chaînes exactes : un chemin supplémentaire séparé par une virgule dans Userinit passe facilement inaperçu dans une interface graphique.
IFEO Debugger et SilentProcessExit
Image File Execution Options (HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<nom.exe>) sert au débogage. Une valeur Debugger fait lancer le débogueur à la place de la cible, avec le chemin de la cible en argument : Debugger = C:\ProgramData\x.exe sur notepad.exe exécute la charge à chaque lancement du Bloc-notes.
La variante plus discrète est SilentProcessExit : on positionne GlobalFlag à 0x200 sur la clé IFEO, puis on crée ...\CurrentVersion\SilentProcessExit\<nom.exe> avec ReportingMode = 1 et MonitorProcess pointant vers la charge. Celle-ci s'exécute quand le processus surveillé se termine. Les deux clés sont décrites sur la fiche IFEO et Winlogon.
AppInit_DLLs
AppInit_DLLs sous HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows (et son jumeau WOW6432Node), avec LoadAppInit_DLLs = 1, charge les DLL listées dans chaque processus qui charge user32.dll. Depuis Windows 8, le mécanisme est désactivé quand Secure Boot est actif : sa présence sur une machine moderne avec Secure Boot traduit donc davantage une intention qu'une persistance fonctionnelle. Toute valeur non vide mérite malgré tout une explication.
Détournement COM
Quand un programme instancie un objet COM, Windows cherche le CLSID dans HKCU\Software\Classes\CLSID avant HKLM\SOFTWARE\Classes\CLSID. Un attaquant sans droits administrateur peut enregistrer le même CLSID dans la ruche utilisateur avec un InprocServer32 (DLL) ou un LocalServer32 (EXE) pointant vers sa charge, qui se charge ensuite chaque fois qu'Explorer ou une tâche planifiée instancie l'objet. Sur disque, HKCU\Software\Classes se trouve dans UsrClass.dat, pas dans NTUSER.DAT : collectez les deux. Cherchez les CLSID présents dans le UsrClass.dat d'un utilisateur qui existent aussi dans HKLM avec un chemin de serveur différent, et les serveurs situés dans des dossiers accessibles en écriture par l'utilisateur comme AppData.
Services
Les services sont définis sous HKLM\SYSTEM\CurrentControlSet\Services\<nom> ; sur une ruche hors ligne, retrouvez le control set actif via Select\Current. Les valeurs importantes :
ImagePath: l'exécutable ou le pilote, arguments compris. Cherchezcmd.exe /c,powershell, des chemins dansTemp,ProgramDataou les profils utilisateurs, et les noms aléatoires.Parameters\ServiceDll(parfois directement sous la clé du service) : la DLL chargée par un servicesvchost.exepartagé. La remplacer sur un service légitime est plus discret que d'en créer un nouveau.Start: 0 boot, 1 system, 2 automatique, 3 manuel, 4 désactivé.ObjectName: le compte d'exécution, généralementLocalSystem.FailureActionsetFailureCommand: une commande de récupération peut elle-même servir de point de persistance.
L'installation laisse un 7045 dans le journal System (nom du service, chemin, type de démarrage, compte) et, si Audit Security System Extension est activé, un 4697 dans Security. Le mouvement latéral façon PsExec produit les mêmes événements, d'où leur place centrale dans le guide mouvement latéral. Voir la fiche services.
# Sur hôte vivant : services avec leur binaire et leur compte
Get-CimInstance Win32_Service |
Select-Object Name, State, StartMode, StartName, PathName |
Sort-Object PathName
Tâches planifiées
Depuis Vista, une tâche laisse trois traces :
- Une définition XML dans
C:\Windows\System32\Tasks\<dossier>\<nom>(sans extension), avecActions,Triggers,PrincipalsetRegistrationInfo. - Des clés dans la ruche SOFTWARE sous
Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache:Tree\<chemin>(valeursId,Index,SD) etTasks\{GUID}(Path,Actions,Triggers,DynamicInfo). - Des événements : Security 4698 (création, avec le XML de la tâche, si Audit Other Object Access Events est activé), 4702 (modification), 4699 (suppression), et dans
Microsoft-Windows-TaskScheduler/Operational106 (enregistrement), 140 (modification), 141 (suppression), 200 (action démarrée) et 201 (action terminée).
La technique « Tarrask » attribuée à HAFNIUM masque une tâche en supprimant sa valeur SD sous TaskCache\Tree. La tâche continue de s'exécuter mais disparaît de schtasks /query et de la console du Planificateur. Toute sous-clé Tree sans valeur SD est une trouvaille ; comparez aussi entre elles les listes Tree, Tasks et fichiers XML, car une incohérence signale une manipulation. Les champs Author et Date du XML sont écrits par le créateur et peuvent être falsifiés. Détails sur la fiche tâches planifiées.
# Sur hôte vivant : toutes les tâches avec leur action, y compris celles marquées Hidden
Get-ScheduledTask | ForEach-Object {
[pscustomobject]@{
Path = $_.TaskPath + $_.TaskName
State = $_.State
Hidden = $_.Settings.Hidden
Execute = ($_.Actions | ForEach-Object { "$($_.Execute) $($_.Arguments)" }) -join ' | '
}
}
# Entrées Tree sans valeur SD (masquage façon Tarrask)
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree' -Recurse |
Where-Object { $_.GetValue('Id') -and ($_.GetValueNames() -notcontains 'SD') } |
Select-Object Name
Get-ScheduledTask n'affiche pas une tâche dont le SD a été supprimé : c'est précisément pour cela que la vérification dans le registre compte.
Abonnements d'événements WMI
Un abonnement WMI permanent combine trois objets, généralement dans root\subscription :
- un
__EventFiltercontenant une requête WQL (par exemple un déclenchement quelques minutes après le démarrage, ou au lancement d'un processus) ; - une sous-classe d'
__EventConsumerqui agit, typiquementCommandLineEventConsumer(exécute une commande) ouActiveScriptEventConsumer(exécute du VBScript ou du JScript) ; - un
__FilterToConsumerBindingqui relie les deux.
Le consumer s'exécute dans WmiPrvSE.exe en tant que SYSTEM, sans aucun fichier dans un dossier de démarrage. Tout est stocké dans le dépôt CIM, C:\Windows\System32\wbem\Repository\OBJECTS.DATA avec INDEX.BTR et les fichiers MAPPING*.MAP. Depuis Windows 10, le 5861 de Microsoft-Windows-WMI-Activity/Operational journalise chaque nouveau binding permanent avec la requête du filtre et le détail du consumer ; Sysmon 19, 20 et 21 capturent l'activité des filtres, consumers et bindings s'ils sont configurés. Des abonnements supprimés peuvent survivre dans les pages non allouées d'OBJECTS.DATA. Voir la fiche dépôt WMI.
# Énumération sur hôte vivant
Get-CimInstance -Namespace root/subscription -ClassName __EventFilter |
Select-Object Name, Query
Get-CimInstance -Namespace root/subscription -ClassName __EventConsumer |
Select-Object __CLASS, Name, CommandLineTemplate, ScriptText
Get-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding |
Select-Object Filter, Consumer
# Hors ligne : analyser le dépôt copié depuis une image
python PyWMIPersistenceFinder.py ./Repository/OBJECTS.DATA
Autres emplacements à vérifier
Dossiers Startup
Les raccourcis ou scripts déposés dans C:\Users\<utilisateur>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup ou C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp s'exécutent à l'ouverture de session. Ces fichiers ont des horodatages NTFS normaux, ce qui fournit une date de création que les valeurs Run n'ont pas. Vérifiez aussi User Shell Folders pour repérer un dossier Startup redirigé.
Jobs BITS
Les jobs du Background Intelligent Transfer Service peuvent télécharger une charge et, via bitsadmin /SetNotifyCmdLine, exécuter une commande quand le job se termine ou échoue. Ils peuvent rester actifs longtemps et être relancés, ce qui en fait un mécanisme discret de persistance et de téléchargement. Les traces se trouvent dans la base BITS (qmgr.db depuis Windows 10, qmgr0.dat/qmgr1.dat avant) et dans Microsoft-Windows-Bits-Client/Operational (3 création, 59 début de transfert avec l'URL, 60 arrêt). Voir la fiche jobs BITS.
Portes dérobées via les fonctions d'accessibilité
Remplacer C:\Windows\System32\sethc.exe (touches rémanentes, cinq fois Maj) ou utilman.exe (Win+U) par cmd.exe, ou leur associer un Debugger IFEO, donne un shell SYSTEM depuis l'écran de connexion, y compris en RDP. Comparez les hashes et les informations de version de sethc.exe, utilman.exe, osk.exe, Magnify.exe, Narrator.exe, DisplaySwitch.exe et AtBroker.exe avec une build saine de même version, cherchez des clés IFEO à ces noms, et examinez le Prefetch pour repérer des exécutions à des heures inhabituelles.
Nouveaux comptes locaux
Un nouvel administrateur local est une persistance qui survit à tout nettoyage des malwares. Cherchez les 4720 (création), 4722 (activation) et 4732 (ajout à un groupe local comme Administrateurs) dans Security, et analysez la ruche SAM pour les dates de création, la dernière connexion et l'appartenance aux groupes (voir la fiche comptes utilisateurs SAM). Un compte peut être masqué de l'écran de connexion avec un DWORD à 0 sous HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList\<nom>, et les noms se terminant par $ sont ignorés par certaines commandes d'énumération.
Détournement de l'ordre de recherche des DLL
Quand une application charge une DLL par son nom sans chemin complet, Windows parcourt une série de répertoires en commençant par le dossier de l'application. Déposer une DLL malveillante portant le nom attendu dans ce dossier, ou dans un répertoire accessible en écriture situé plus tôt dans l'ordre de recherche, la fait charger par un processus légitime et souvent signé. Les KnownDLLs (HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs) sont protégées contre ce détournement. Cherchez des DLL normalement présentes dans System32 apparaissant à côté d'exécutables dans ProgramData, AppData ou Temp, des DLL non signées à côté de binaires signés, et des chargements d'image Sysmon 7 depuis des chemins inhabituels. Amcache aide à dater la première apparition de la DLL.
Outils
Autoruns hors ligne
Autoruns (Sysinternals) couvre la plupart des autostarts du registre et du système de fichiers et signale les entrées non signées. autorunsc peut analyser un répertoire Windows hors ligne avec -z, en pointant vers le dossier Windows et un profil utilisateur d'une image montée.
# Sur hôte vivant, tous types d'entrées, CSV avec hashes et vérification des signatures
autorunsc.exe -accepteula -nobanner -a * -c -h -s > autoruns_live.csv
# Image hors ligne montée en F:
autorunsc.exe -accepteula -nobanner -a * -c -h -s -z F:\Windows F:\Users\alice > autoruns_offline.csv
Le mode hors ligne dépend des ruches qu'il peut lire : lancez-le une fois par profil utilisateur pertinent.
KAPE et RECmd
KAPE collecte en une passe les ruches, le XML des tâches, le dépôt WMI et les journaux, puis son module !EZParser lance les outils d'Eric Zimmerman. RECmd, avec un fichier batch (comme Kroll_Batch.reb fourni dans son dossier BatchExamples), extrait les clés de persistance connues de toutes les ruches dans un seul CSV, en tenant compte des journaux de transactions des ruches quand ils sont présents.
kape.exe --tsource C: --tdest E:\tout --target KapeTriage --mdest E:\mout --module !EZParser
RECmd.exe -d E:\tout\C --bn .\BatchExamples\Kroll_Batch.reb --csv E:\out\registry
Velociraptor
Sur un parc, Velociraptor exécute les mêmes vérifications partout à la fois. Artefacts utiles : Windows.Sysinternals.Autoruns, Windows.Persistence.PermanentWMIEvents, Windows.System.TaskScheduler, Windows.System.Services et Windows.Sys.StartupItems. Empiler (stacking) les résultats de nombreux hôtes est souvent plus rapide qu'examiner une machine en profondeur. Le guide acquisition et triage couvre le déploiement.
Erreurs fréquentes
- Ne regarder que HKLM. Les clés Run de HKCU, les objets COM par utilisateur dans UsrClass.dat et les dossiers Startup utilisateur ne demandent aucun droit administrateur, et c'est pour cela qu'ils sont prisés. Traitez les ruches de chaque utilisateur, comptes de service compris.
- Oublier WOW6432Node. Les entrées Run, IFEO et AppInit 32 bits se trouvent dans une branche distincte sur les systèmes 64 bits.
- Faire confiance aux signatures. Les attaquants font pointer leurs autostarts vers des LOLBins signés (
rundll32,mshta,regsvr32) avec des arguments malveillants. Lisez la ligne de commande, pas seulement le binaire. - Surinterpréter l'horodatage des clés. Un last write time date la dernière modification de la clé, pas celle de la valeur qui vous intéresse.
- Manquer les tâches cachées à l'API. Énumérez directement
TaskCacheet le dossierTasks, pas seulementschtasks. - S'arrêter à la première trouvaille. Les attaquants posent généralement plusieurs mécanismes : parcourez toute la liste.
Méthode de triage et comparaison à une baseline
- Collecter les ruches (SYSTEM, SOFTWARE, SAM, chaque NTUSER.DAT et UsrClass.dat, avec leurs journaux de transactions),
System32\Tasks, le dossierRepositoryde WMI, la base BITS, les dossiers Startup et tous les journaux d'événements. Le guide forensique du registre explique l'organisation des ruches. - Énumérer avec Autoruns (vivant ou
-z), la sortie batch de RECmd, le XML des tâches plus TaskCache, et un parseur WMI. - Vérifier les journaux : 7045, 4697, 4698, TaskScheduler 106/200, WMI-Activity 5861, Bits-Client 3/59, 4720/4732, en suivant le guide des journaux d'événements.
- Comparer à une baseline : sortie Autoruns d'une machine saine issue du même master, ou résultats empilés sur l'ensemble du parc. Les entrées présentes sur un ou deux hôtes sur plusieurs centaines remontent d'elles-mêmes.
- Filtrer par date : gardez les entrées dont le last write time de la clé, la date de création du fichier ou l'événement d'installation tombe dans la fenêtre d'intrusion.
- Valider chaque candidat : hash et signature de la cible, chemin du fichier, Prefetch ou Amcache pour l'exécution, et compte à l'origine de la création.
- Documenter chaque mécanisme avec son ID ATT&CK, son emplacement, sa date de création et les preuves d'exécution, puis les supprimer tous en même temps lors de la remédiation pour que l'attaquant ne puisse pas se servir de l'un pour restaurer les autres.
Domaine 07
Persistance
Les fiches artefacts derrière ce guide : emplacement selon la version de Windows, ce que prouve chacun et les outils pour l'analyser.