Le XML d'une tâche planifiée Windows, élément par élément
Lire le XML d'une tâche planifiée en enquêteur : RegistrationInfo, Triggers, Principals, Settings, Actions, et les heures locales sans fuseau de Date et StartBoundary.
En bref. Le XML d'une tâche comporte cinq sections qui comptent : RegistrationInfo (qui et quand, selon ses propres dires), Triggers (quand elle se déclenche), Principals (quel compte, quels privilèges), Settings (cachée, activée, limites) et Actions (ce qui s'exécute). Deux pièges : Date et StartBoundary sont généralement en heure locale sans décalage, et Author est un texte libre. Lisez le fichier comme un ensemble d'affirmations et confrontez-les à TaskCache et aux journaux d'événements.
Le format est documenté dans le Task Scheduler Schema de Microsoft, avec l'espace de noms http://schemas.microsoft.com/windows/2004/02/mit/task. Cet article le lit du point de vue de l'enquêteur. L'emplacement des fichiers est traité dans emplacements et acquisition des tâches planifiées.
Un exemple minimal
Une tâche enregistrée avec schtasks sur un poste de travail ressemble généralement à ceci. L'exemple est un extrait du jeu de données fictif FIN-WKS-07 utilisé sur l'ensemble de ce site, configuré en UTC+02:00 :
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2026-09-14T12:09:58.4413872</Date>
<Author>FIN-WKS-07\svc_backup</Author>
<Description>Intel graphics telemetry</Description>
<URI>\IntelGfxTelemetry</URI>
</RegistrationInfo>
<Triggers>
<BootTrigger><Enabled>true</Enabled></BootTrigger>
<TimeTrigger>
<Repetition><Interval>PT1H</Interval></Repetition>
<StartBoundary>2026-09-14T12:15:00</StartBoundary>
<Enabled>true</Enabled>
</TimeTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>S-1-5-18</UserId>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<Hidden>true</Hidden>
<Enabled>true</Enabled>
</Settings>
<Actions Context="Author">
<Exec>
<Command>C:\ProgramData\Intel\m64.exe</Command>
<Arguments>-svc</Arguments>
</Exec>
</Actions>
</Task>
Le fichier sur disque est généralement en UTF-16LE avec indicateur d'ordre des octets (BOM), même si la déclaration XML circule parfois en UTF-8. Un parser qui suppose de l'UTF-8 affichera des caractères illisibles ; c'est déjà une raison suffisante d'utiliser un outil conçu pour ce format.
RegistrationInfo : les métadonnées déclarées
| Élément | Ce qu'il indique | Quel crédit lui accorder |
|---|---|---|
URI | Chemin de la tâche dans la bibliothèque, par ex. \Microsoft\Windows\Defrag\ScheduledDefrag | Doit correspondre au chemin du fichier et à la clé Tree de TaskCache ; toute divergence mérite d'être notée |
Author | Qui a enregistré la tâche | Texte libre. La console et schtasks écrivent DOMAIN\user ; les programmes d'installation écrivent souvent un nom d'éditeur ; certaines tâches Microsoft utilisent une référence de ressource comme $(@%SystemRoot%\system32\...) |
Date | Date d'enregistrement | Généralement en heure locale, sans décalage (voir plus bas) |
Description | Description lisible | Texte libre ; les attaquants recopient les formulations de Microsoft |
SecurityDescriptor | SDDL facultatif pour la tâche | Rare dans le XML ; le descripteur effectif est la valeur SD de TaskCache |
Source, Version, Documentation | Facultatifs | Parfois utiles pour attribuer une tâche à un éditeur |
Des notes de praticiens comme les Windows forensic artifacts de Psmths relèvent que l'Author d'une tâche créée à distance peut révéler le compte d'origine, mais rien n'empêche un XML importé de porter un auteur falsifié. Comparez avec le SubjectUserName de l'événement 4698 ou 106 lorsque vous en disposez.
Triggers : quand elle se déclenche
Le schéma autorise jusqu'à 48 déclencheurs par tâche : BootTrigger, LogonTrigger, RegistrationTrigger, IdleTrigger, TimeTrigger, CalendarTrigger, EventTrigger et SessionStateChangeTrigger. Tous partagent Enabled, StartBoundary, EndBoundary, Repetition et ExecutionTimeLimit.
Lecture côté enquête :
- Les déclencheurs Boot et Logon sont de la persistance classique. Un
LogonTriggersansUserIdse déclenche pour n'importe quel utilisateur. - RegistrationTrigger se déclenche une fois, à l'enregistrement de la tâche : un moyen courant d'exécuter quelque chose immédiatement tout en ayant l'air d'une tâche planifiée.
- Un TimeTrigger avec un intervalle
Repetitioncourt (par exemplePT5M) évoque un comportement de beacon. - EventTrigger embarque une requête XPath
Subscription; il peut faire se déclencher une tâche sur un event ID précis, ce qui passe facilement inaperçu. - SessionStateChangeTrigger (
SessionUnlock,RemoteConnect) est moins courant et mérite un second regard.
Principals : quel compte, quels privilèges
| Élément | Valeurs | Signification |
|---|---|---|
UserId | Nom de compte ou SID (S-1-5-18 pour SYSTEM, S-1-5-19 pour LOCAL SERVICE, S-1-5-20 pour NETWORK SERVICE) | Le contexte de sécurité |
GroupId | Nom de groupe ou SID | S'exécute pour les membres d'un groupe, par ex. S-1-5-32-545 (Users) |
LogonType | InteractiveToken, Password, S4U, InteractiveTokenOrPassword | Manière dont le compte est ouvert ; voir S4U |
RunLevel | LeastPrivilege, HighestAvailable | Utilisation ou non d'un jeton administrateur ; voir niveau d'exécution |
Une tâche non Microsoft qui s'exécute en S-1-5-18 avec HighestAvailable est la combinaison à trier en priorité. Un LogonType à Password signifie que des identifiants ont été stockés pour que la tâche puisse s'exécuter en l'absence de l'utilisateur ; les recommandations de Microsoft sur l'événement 4698 conseillent de lever une alerte dans ce cas, car le mot de passe stocké peut être récupéré par un administrateur.
Settings : les options qui masquent ou brident
Les éléments à lire en premier sont Hidden, Enabled, ExecutionTimeLimit (PT0S signifie aucune limite), MultipleInstancesPolicy, StartWhenAvailable, DisallowStartIfOnBatteries, WakeToRun, RunOnlyIfNetworkAvailable et DeleteExpiredTaskAfter.
Hidden=true masque seulement la tâche dans la console, sauf si "Show Hidden Tasks" est coché. Elle reste visible pour schtasks, l'API et le registre. Les techniques de dissimulation plus efficaces se jouent dans le registre, voir Tarrask et les tâches planifiées cachées. DeleteExpiredTaskAfter combiné à un EndBoundary fait qu'une tâche s'efface d'elle-même : son absence ultérieure ne prouve pas qu'elle n'a jamais existé.
Actions : ce qui s'exécute
| Action | Contenu | Remarques |
|---|---|---|
Exec | Command, Arguments, WorkingDirectory | L'immense majorité des tâches |
ComHandler | ClassId (CLSID), Data facultatif | Exécute un objet COM, généralement une DLL chargée dans taskhostw.exe ; voir action COM handler |
SendEmail | Serveur, To, Subject... | Déprécié par Microsoft ; rare sur les systèmes récents |
ShowMessage | Title, Body | Déprécié ; rare |
L'élément Actions possède un attribut Context qui désigne le principal. Jusqu'à 32 actions sont autorisées et elles s'exécutent dans l'ordre : lisez-les toutes, car une première action anodine peut précéder une seconde action malveillante.
Pour ComHandler, résolvez le CLSID dans la ruche SOFTWARE (Classes\CLSID\{...}\InprocServer32) pour retrouver la DLL. Détourner un CLSID déjà utilisé par une tâche légitime est une forme de persistance plus discrète que la création d'une nouvelle tâche.
Le temps : des valeurs locales sans fuseau
Le schéma type Date, StartBoundary et EndBoundary en xs:dateTime. L'API de scripting documente le format YYYY-MM-DDTHH:MM:SS(+-)HH:MM avec un décalage (Trigger.StartBoundary). En pratique, les tâches créées dans la console ou avec schtasks n'enregistrent aucun décalage, et l'heure est l'heure locale de la machine au moment où la tâche a été enregistrée. Certaines tâches stockent un Z ou un décalage explicite ; la plupart non.
Cela devient important dès que vous comparez avec des sources en UTC. Dans l'exemple 4698 de Microsoft, le TimeCreated de l'événement vaut 2015-09-23T02:03:06Z et le Date du XML 2015-09-22T19:03:06.9258653 : le même instant, à sept heures d'écart.
Plusieurs moyens de retrouver le décalage :
- TaskCache :
DynamicInfocontient un FILETIME de création en UTC pour la même tâche ; l'écart avecDatedonne le décalage, arrondi au quart d'heure le plus proche. Voir l'analyse forensique du registre TaskCache. - Ruche SYSTEM :
TimeZoneInformationindique le fuseau configuré ; n'oubliez pas que l'heure d'été s'applique à la date de l'événement, pas à celle de la collecte. - Événement 4698 :
TimeCreateden UTC face auDateembarqué.
Le Scheduled Tasks Parser applique automatiquement la première méthode : il compare les dates d'enregistrement du XML aux FILETIME de TaskCache, propose un décalage et vous laisse le modifier.
StartBoundary présente une subtilité supplémentaire : c'est le moment où le déclencheur devient actif, qui peut se situer dans le passé (les tâches créées « maintenant » reçoivent souvent la minute de création) ou loin dans le futur. Ce n'est pas une heure d'exécution. Les heures d'exécution proviennent du DynamicInfo de TaskCache et des événements 200/201.
FAQ
Dans quel fuseau horaire est exprimé le Date du XML d'une tâche planifiée ?
Généralement aucun. Le schéma autorise un décalage, mais les tâches créées dans la console ou avec schtasks enregistrent en principe l'heure locale sans aucun décalage. Déduisez le décalage d'une source UTC, comme les FILETIME de TaskCache ou le TimeCreated de l'événement 4698, avant de comparer avec d'autres traces.
Le champ Author prouve-t-il qui a créé la tâche ?
Non. Author est un texte libre écrit par ce qui a enregistré la tâche. La console et schtasks y inscrivent le compte créateur, mais un script ou un XML importé peut y mettre n'importe quoi. Considérez-le comme une affirmation à vérifier dans les journaux d'événements.
Que signifie Hidden=true ?
La tâche n'apparaît pas dans la console du Planificateur de tâches, sauf si l'utilisateur active Show Hidden Tasks. Elle reste listée par schtasks et par l'API. De nombreuses tâches Microsoft sont cachées : ce drapeau compte donc surtout pour les tâches non Microsoft.