Skip to content

Analyse forensique de TaskCache : Tree, Tasks, DynamicInfo

Ce que la clé TaskCache de la ruche SOFTWARE stocke pour chaque tâche planifiée : Id/Index/SD, DynamicInfo, blobs Actions et Triggers, et Hash.

Publié le 9 min de lecture

En bref. TaskCache se compose de deux moitiés. Tree\<chemin> associe un nom de tâche à son GUID (Id), à une catégorie (Index) et à un descripteur de sécurité (SD). Tasks\{GUID} stocke Path, URI, Author, Date, Hash, Actions, Triggers et DynamicInfo, dont les FILETIME donnent en UTC la création, la dernière exécution et la dernière exécution réussie. Les structures binaires ont été rétro-ingéniérées par la communauté : fiez-vous aux champs bien corroborés et recoupez le reste.

Cet article est la plongée côté registre de la série qui commence avec le guide d'analyse forensique des tâches planifiées. Les sources principales sont l'analyse de cyber.wtf (Windows 10 1909, vérifiée sur Windows 7) et le winreg-kb de libyal. Microsoft ne documente pas ces valeurs.

Organisation de la clé

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache
├── Tree\<folder>\<task name>      Id, Index, SD
├── Tasks\{GUID}                   Path, URI, Author, Date, Hash, Actions, Triggers, DynamicInfo, ...
├── Boot\{GUID}
├── Logon\{GUID}
├── Plain\{GUID}
└── Maintenance\{GUID}

Tree reproduit l'arborescence des dossiers de C:\Windows\System32\Tasks. Tasks est à plat, avec une clé par GUID de tâche. Les quatre clés de catégorie contiennent une sous-clé par GUID de tâche appartenant à cette catégorie.

Tree : noms, catégories, permissions

ValeurTypeSignification
IdChaîneLe GUID de la tâche, par ex. {8A1B...}, qui pointe vers Tasks\{GUID}
IndexDWORDCatégorie. cyber.wtf donne 1 Boot, 2 Logon, 3 Plain, 4 Maintenance ; les dossiers n'ont pas d'Index
SDBinaireDescripteur de sécurité auto-relatif qui contrôle l'accès à la tâche

Trois points à vérifier sur chaque entrée de Tree :

  1. SD est-il présent ? Une clé de tâche sans SD est invisible pour schtasks et pour la console. C'est la technique de dissimulation de Tarrask (Microsoft, 2022).
  2. Le SD décodé refuse-t-il la lecture ? Binary Defense a montré qu'un descripteur valide refusant la lecture à tout le monde cache une tâche tout aussi bien, tout en ayant l'air normal (Binary Defense). Lisez le SDDL, ne vous contentez pas de constater sa présence.
  3. L'Index est-il plausible ? MITRE cite la modification de la valeur Index comme autre méthode de dissimulation (T1053.005). Une valeur 0 sur une tâche, ou un Index qui contredit la clé de catégorie sous laquelle figure le GUID, mérite d'être noté.

La date de dernière écriture de la clé Tree est un FILETIME UTC mis à jour dès qu'une valeur de cette clé change. Pour une tâche normale, elle est proche de l'enregistrement. Si elle est nettement postérieure à l'heure de création indiquée par DynamicInfo, quelque chose a réécrit la clé ; sur une tâche de type Tarrask, cela peut correspondre au moment où le SD a été supprimé. C'est une déduction, pas un enregistrement direct : formulez-le ainsi dans un rapport.

Tasks{GUID} : les données de la tâche

ValeurSignification
PathChemin de la tâche, par ex. \Microsoft\Windows\Defrag\ScheduledDefrag
URIIdentique à l'URI du XML, lorsqu'il existe
Author, Description, Source, Version, DocumentationCopies des champs de RegistrationInfo
DateChaîne de date d'enregistrement, au même format sans fuseau horaire que dans le XML
HashHash d'intégrité du fichier XML, voir plus bas
SchemaVersion du schéma, sous forme numérique
SecurityDescriptorSDDL facultatif issu du XML
ActionsSérialisation binaire des actions
TriggersSérialisation binaire des déclencheurs, du principal et des paramètres
DynamicInfoEnregistrement binaire de l'état d'exécution

Toutes les valeurs n'existent pas pour toutes les tâches. cyber.wtf note que seules Actions et Triggers semblent nécessaires pour que la tâche apparaisse dans la console.

DynamicInfo

DynamicInfo est la raison pour laquelle il faut toujours analyser TaskCache. Voici sa structure telle que décrite par cyber.wtf, cohérente avec les indications de taille de winreg-kb (28 octets sous Vista/7, 36 octets à partir de Windows 8) :

OffsetTailleChamp
04Version / magic, généralement 3
48FILETIME : création (enregistrement ou dernière mise à jour)
128FILETIME : dernière exécution
204État de la tâche
244Code du dernier résultat (HRESULT, par ex. 0x80070002 fichier introuvable)
288FILETIME : dernière exécution réussie (Windows 8 et ultérieurs uniquement)

winreg-kb qualifie les deux premiers horodatages d'« unknown » et suggère « last registered or update time? » et « launch time? » ; cyber.wtf les nomme comme ci-dessus. En pratique, la valeur « création » change lorsqu'une tâche est réenregistrée : lisez-la donc comme le dernier enregistrement plutôt que comme la création initiale. Le code du dernier résultat est souvent le champ le plus utile : une tâche de persistance qui s'est exécutée correctement affiche 0x0 ; une tâche dont le binaire a été supprimé affiche un HRESULT de fichier introuvable.

Les trois FILETIME sont en UTC. Ils servent donc de point d'ancrage pour la Date du XML, qui n'a pas de fuseau horaire, comme expliqué dans l'anatomie du XML des tâches.

Le blob Actions

La valeur Actions commence par un mot de version, suivi de la chaîne du contexte du principal, puis d'un enregistrement par action identifié par une valeur magic (cyber.wtf) :

MagicAction
0x6666Exec : commande, arguments, répertoire de travail
0x7777ComHandler : CLSID et données
0x8888SendEmail
0x9999ShowMessage

Les chaînes sont en UTF-16, précédées de leur longueur. Quand le fichier XML a disparu, c'est ce blob qui permet encore de savoir ce que la tâche exécutait. Comparez-le avec le XML quand les deux existent : un attaquant qui modifie directement le registre peut changer l'action sans toucher au fichier, ou inversement.

Le blob Triggers

Triggers commence par un en-tête (version, puis un « job bucket » contenant des flags, un CRC32, l'identifiant du principal, des informations sur l'utilisateur et des paramètres facultatifs), suivi d'enregistrements de déclencheurs de différents types, chacun avec son propre magic et un alignement sur 8 octets. La structure de l'en-tête est raisonnablement bien comprise ; celle des enregistrements de déclencheurs varie selon la version de Windows et reste moins établie. Un parseur peut extraire de façon fiable l'en-tête et le principal (le compte sous lequel la tâche s'exécute) ; considérez les détails des déclencheurs décodés depuis le blob comme un meilleur effort, et privilégiez le XML quand vous l'avez.

Hash

La valeur Hash permet au service de détecter qu'un fichier XML a été modifié en dehors de son contrôle. winreg-kb l'indique comme un SHA-256, ou un CRC32 sur les systèmes antérieurs à la mise à jour KB2305420. Sur les systèmes Windows 10 et 11 actuels, on observe qu'il s'agit du SHA-256 du contenu du fichier XML sans son BOM UTF-16 de deux octets.

Le recalculer offre un contrôle d'intégrité peu coûteux :

  • Correspondance : le XML sur disque est bien celui que le service a enregistré.
  • Divergence : le fichier a été modifié après l'enregistrement, ou bien l'entrée de registre, ou encore le fichier a été restauré depuis un autre emplacement. Dans tous les cas, les deux copies ne concordent pas : lisez les deux.
  • Pas de XML : le fichier a été supprimé ; le registre est la seule définition restante.

Corréler TaskCache avec les fichiers XML

Associez chaque clé Tree au fichier XML situé au même chemin relatif sous System32\Tasks. Dressez ensuite la liste suivante :

SituationExplication habituelleQue faire
XML et TaskCache, hash concordantNormalTrier sur le contenu
TaskCache seul (pas de XML)XML supprimé à la main ou par un outil de nettoyage ; la tâche peut encore s'exécuterPriorité haute : décoder Actions
XML seul (pas de TaskCache)Fichier déposé mais jamais enregistré, registre nettoyé, ou ruche « dirty »Vérifier l'état de la ruche et les journaux d'événements
Tree sans SDTâche cachée (type Tarrask)Priorité haute
Hash divergentFichier ou registre modifié après l'enregistrementComparer les deux définitions

Une réserve avant de déclarer quoi que ce soit « manquant » : si la ruche SOFTWARE a été copiée à chaud sans rejouer ses journaux de transactions, des modifications récentes du registre peuvent en être absentes. Voir emplacements et acquisition des tâches planifiées.

Le Scheduled Tasks Parser réalise cette corrélation, recalcule le hash, décode le SD en SDDL ainsi que DynamicInfo, Actions et l'en-tête de Triggers, et signale les tâches présentes uniquement dans le registre, uniquement sur disque ou dépourvues de SD. Pour un travail plus poussé sur le registre, le Registry parser couvre le reste de la ruche.

FAQ

Qu'est-ce que la clé de registre TaskCache ?

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache est l'endroit où le service Planificateur de tâches conserve sa copie de chaque tâche enregistrée : noms et descripteurs de sécurité sous Tree, données de la tâche sous Tasks\{GUID}, et listes par catégorie sous Boot, Logon, Plain et Maintenance.

Quels horodatages contient DynamicInfo ?

Sous Windows 8 et versions ultérieures, la valeur fait généralement 36 octets : un DWORD de version, un FILETIME couramment interprété comme l'heure de création ou d'enregistrement de la tâche, un FILETIME de dernière exécution, un DWORD d'état de la tâche, un code du dernier résultat et un FILETIME de dernière exécution réussie. Cette structure provient de recherches communautaires, pas de la documentation Microsoft.

Qu'est-ce que la valeur Hash dans TaskCache\Tasks ?

Un hash d'intégrité du XML de la tâche. Sur les systèmes actuels, on observe qu'il s'agit du SHA-256 du fichier XML sans son indicateur d'ordre des octets (BOM) de deux octets ; les systèmes plus anciens utilisaient CRC32. Une divergence avec le XML sur disque signifie que l'un des deux a changé après l'enregistrement.

Articles liés

Les tâches planifiées Windows de bout en bout : fichiers XML, clé de registre TaskCache, fichiers .job hérités, journaux d'événements et corrélation.
Pas à pas : chargez XML, fichiers .job et ruche SOFTWARE dans un parser gratuit, lisez tâches cachées et registre seul, corrigez le fuseau et exportez. Cas fictif.
Checklist pour repérer les tâches planifiées malveillantes : chemins inscriptibles, PowerShell encodé, LOLBins, SYSTEM, tâches cachées, écarts XML/registre.