Qu'est-ce qu'un abonnement aux événements WMI ?
WMI (Windows Management Instrumentation) peut exécuter une action lorsqu'un événement se produit. Un abonnement permanent aux événements comporte trois parties : un __EventFilter (une requête WQL décrivant l'événement), un consommateur d'événements (l'action : exécuter une ligne de commande, un VBScript/JScript, écrire une ligne de journal, une entrée du journal d'événements ou un e-mail) et un __FilterToConsumerBinding qui relie les deux.
Les abonnements sont stockés dans le dépôt WMI (CIM) et survivent aux redémarrages. Leurs actions s'exécutent en tant que SYSTEM — une ligne de commande lancée par l'hôte des fournisseurs WMI (WmiPrvSE.exe), ou un script exécuté par scrcons.exe — sans rien dans une clé Run ni dans une tâche planifiée. C'est pourquoi les attaquants les utilisent pour la persistance (MITRE ATT&CK T1546.003), et pourquoi ils passent facilement inaperçus.
Où ils sont stockés
- C:\Windows\System32\wbem\Repository\OBJECTS.DATA — chaque définition de classe et instance, en pages de 8 Kio. Les pages libérées conservent leur ancien contenu jusqu'à leur réutilisation.
- INDEX.BTR — un B-tree de clés telles que NS_<hash>\CI_<hash>\IL_<hash>.<page>.<record>.<length>, où chaque hachage est le SHA-256 (MD5 sous XP) d'un nom en majuscules.
- MAPPING1.MAP, MAPPING2.MAP, MAPPING3.MAP — tables de correspondance entre pages logiques et physiques pour OBJECTS.DATA et INDEX.BTR ; Windows conserve trois générations et utilise la plus récente.
- Les abonnements résident normalement dans l'espace de noms root\subscription, mais n'importe quel espace de noms fonctionne.
Ce que montre cet outil
- Chaque liaison associée à son filtre (la requête déclencheuse) et à son consommateur (la ligne de commande, le script, le fichier journal ou la cible du journal d'événements).
- Deux manières de trouver chaque objet, toujours indiquées : structurée (via INDEX.BTR et le fichier MAPPING courant, comme python-cim) et carving (un parcours de tout OBJECTS.DATA à la recherche d'en-têtes d'enregistrement et du texte des liaisons, comme PyWMIPersistenceFinder).
- Les objets supprimés et les anciennes versions d'objets récupérés dans les pages libérées et l'espace résiduel des pages, distingués des objets actifs lorsque les fichiers MAPPING sont présents.
- Des constats motivés : PowerShell encodé, chemins modifiables par l'utilisateur, consommateurs de script, déclencheurs de persistance (uptime, ouverture de session, minuteurs), liaisons hors de root\subscription, éléments non liés ou cassés, et abonnements par défaut de Windows (SCM Event Log et BVT) reconnus par leur nom et leur contenu.
- Sur les machines équipées du client Configuration Manager : CCM_RecentlyUsedApps comme preuve d'exécution — chemin, utilisateur, LastUsedTime, nombre de lancements et informations de version, y compris les anciennes copies récupérées dans l'espace libéré, avec une plage horaire et des constats.
Limites
- Les objets d'abonnement WMI ne portent aucun horodatage documenté. Chaque en-tête d'instance contient deux FILETIME non documentés, affichés à titre de pistes ; les vues d'abonnements n'ont pas de filtre temporel (la vue SCCM en a un : LastUsedTime est une vraie date).
- Les enregistrements récupérés par carving n'ont pas d'espace de noms, et un enregistrement réparti sur des pages libérées non adjacentes peut n'être que partiellement lisible.
- Sans INDEX.BTR ni fichier MAPPING, les structures de classes proviennent d'une copie intégrée des classes Windows standard (validée sur chaque enregistrement), et les enregistrements actifs et supprimés ne peuvent pas être distingués.
- Les fichiers MOF, la liste AutoRecover et les autres emplacements de persistance sont hors périmètre ; la structure Windows XP est prise en charge avec moins de tests.
Comment obtenir les fichiers
- Collectez l'intégralité du dossier Repository avec KAPE (cible WBEM), Velociraptor (Windows.Triage.Targets, WBEM) ou depuis une image disque.
- Sur un système en fonctionnement, lisez les fichiers depuis un cliché instantané de volume pour qu'ils proviennent tous du même instant. N'arrêtez jamais le service WMI pour les copier.
- Conservez aussi les copies plus anciennes (clichés instantanés, Windows.old) : un abonnement supprimé peut encore s'y trouver.
Crédits et méthode
- flare-wmi / python-cim — Willi Ballenthin, FireEye (now Mandiant). Les structures du dépôt — fichiers MAPPING, pages d'INDEX.BTR, table des matières d'OBJECTS.DATA, en-têtes de définitions de classes et d'instances — sont portées depuis python-cim, et le mode structuré suit son résolveur d'objets. Apache-2.0.
- PyWMIPersistenceFinder — David Pany, Mandiant. La passe de carving de texte reprend son idée : trouver le texte __FilterToConsumerBinding et ses références EventConsumer.Name / __EventFilter.Name n'importe où dans OBJECTS.DATA, et traiter les liaisons BVT et SCM Event Log comme des défauts courants. MIT.
- WMI Attacks, Defense and Forensics (DEF CON 23) — William Ballenthin, Matt Graeber, Claudiu Teodorescu (FireEye, 2015). La présentation (et le livre blanc associé) qui a documenté le format du dépôt et la persistance WMI ; les diapositives et démos sont conservées dans le dépôt flare-wmi.
- [MS-WMIO]: WMI Encoding Version 1.0 Protocol — Microsoft. La spécification publique de l'encodage des objets dans chaque enregistrement : parties de classe, NdTable, table des valeurs, heap et chaînes encodées.
FAQ
Mon dépôt est-il envoyé quelque part ?
Non. Le parseur est écrit en Rust, compilé en WebAssembly, et s'exécute dans un Web Worker de votre navigateur. Il n'existe aucun point de téléversement.
OBJECTS.DATA suffit-il ?
Oui pour trouver les abonnements : le mode carving parcourt chaque octet à la recherche d'enregistrements de filtres, de consommateurs et de liaisons, y compris supprimés. Avec INDEX.BTR et les fichiers MAPPING, vous obtenez en plus les espaces de noms et une distinction fiable entre actif et supprimé.
Que signifient « Index », « Enregistrement récupéré » et « Correspondance texte » ?
Ils indiquent comment un objet a été trouvé. Index : via INDEX.BTR et le fichier MAPPING courant, l'objet est donc actif. Enregistrement récupéré : son en-tête d'enregistrement a été trouvé en parcourant OBJECTS.DATA ; s'il n'est pas également indexé, il se trouve dans l'espace libéré. Correspondance texte : seul le texte de la liaison a subsisté, à la manière dont PyWMIPersistenceFinder trouve les liaisons.
SCM Event Log Consumer et BVTConsumer sont-ils malveillants ?
Non, lorsqu'ils correspondent à ce que Windows installe : la liaison SCM Event Log est livrée avec Windows Vista et ultérieur, et la liaison BVT (cscript KernCap.vbs) est un reliquat inoffensif des images de l'époque Windows 7. L'outil vérifie aussi le contenu et signale un nom par défaut associé à un contenu différent.
Peut-il indiquer quand un abonnement a été créé ?
Pas de manière fiable. Le dépôt ne stocke aucun horodatage documenté par objet. Chaque en-tête d'instance contient deux FILETIME qui suivent souvent le moment où l'instance a été écrite ; ils sont affichés à titre de pistes. Corrélez avec l'événement 5861 de Microsoft-Windows-WMI-Activity/Operational, qui journalise les nouveaux consommateurs permanents.
Qu'est-ce que la vue Preuves d'exécution (SCCM) ?
Sur les machines équipées du client Configuration Manager (SCCM / ConfigMgr), le dépôt contient aussi CCM_RecentlyUsedApps dans root\ccm\SoftwareMeteringAgent : un enregistrement par exécutable et par utilisateur avec LastUsedTime (le dernier lancement par cet utilisateur, un CIM DATETIME qui porte son décalage UTC), un nombre de lancements et les informations de version du fichier. L'outil le lit dans le même OBJECTS.DATA, récupère les anciennes copies dans l'espace libéré et ajoute une plage horaire. Sans client ConfigMgr, ces données n'existent pas.