Skip to content

Format des valeurs BAM : FILETIME, chemins et internes

Une valeur BAM octet par octet : le REG_BINARY de 24 octets, le FILETIME, chemins de périphérique ou noms de package, Version, SequenceNumber et horodatages.

Publié le 7 min de lecture

TL;DR. Chaque valeur BAM suit le schéma nom = exécutable, données = REG_BINARY. Les 8 premiers octets des données sont un FILETIME little-endian (tics de 100 ns depuis le 1601-01-01 UTC) ; sur les builds étudiés, les données font 24 octets et les 16 derniers ne servent pas à lire l'heure. Les noms de valeur sont soit des chemins de périphérique NT (\Device\HarddiskVolume3\…), soit des noms de famille de package. Version et SequenceNumber sont des valeurs de gestion, pas des programmes. L'heure de dernière écriture de la clé SID est un horodatage supplémentaire, offert.

Si vous ne lisez BAM qu'à travers un outil, cet article vous explique ce que fait l'outil et où il peut se tromper. Pour le contexte : le guide complet BAM/DAM et l'emplacement de la clé BAM.

Anatomie d'une clé SID

Une clé bam\State\UserSettings\<SID> typique ressemble à ceci (données d'exemple fictives du site) :

Nom de la valeurTypeDonnées (hex)
VersionREG_DWORD01 00 00 00
SequenceNumberREG_DWORD76 00 00 00
\Device\HarddiskVolume3\Users\alice\Downloads\Invoice_2026-0914.pdf.exeREG_BINARY80 0d 7c 1d 29 44 dd 01 + 16 octets
MSTeams_8wekyb3d8bbweREG_BINARY24 octets

Trois types de valeurs, trois règles :

  1. DWORD de gestion — Version et SequenceNumber. Ignorez-les quand vous listez les programmes. Leur sémantique n'est pas documentée publiquement ; toute interprétation (par exemple que SequenceNumber augmente à chaque mise à jour) reste une hypothèse à tester sur votre propre système de référence.
  2. Entrées d'exécutables — REG_BINARY, le nom est un chemin, les données font au moins 8 octets.
  3. Tout le reste — une valeur qui n'est pas REG_BINARY ou qui fait moins de 8 octets n'est pas un enregistrement BAM. Un parseur robuste l'ignore au lieu de planter. Le nôtre fait exactement cela, et signale les valeurs illisibles sous forme d'avertissements au lieu de les écarter en silence.

Décoder le FILETIME

Un FILETIME est un compteur 64 bits d'intervalles de 100 nanosecondes depuis le 1er janvier 1601 UTC (Microsoft Learn). Il est stocké en little-endian : lisez les octets de droite à gauche.

bytes      80 0d 7c 1d 29 44 dd 01
as u64     0x01DD44291D7C0D80 = 134338507270000000
seconds    13433850727            (÷ 10,000,000)
minus      11644473600            (1601 → 1970 offset)
unix       1789377127             → 2026-09-14 09:12:07 UTC

Deux points à garder en tête :

  • C'est de l'UTC. Le registre ne stocke pas le fuseau horaire de la machine dans la valeur. La ruche SYSTEM enregistre en revanche le fuseau configuré (Control\TimeZoneInformation\TimeZoneKeyName), que notre outil affiche dans l'en-tête pour raisonner en heure locale. Le bouton « Local » de l'outil convertit vers le fuseau de votre navigateur, pas celui de la machine étudiée.
  • Précision. Le FILETIME a une résolution de 100 ns. Date en JavaScript ne descend qu'à la milliseconde : les outils web qui passent par Date arrondissent. Le BAM/DAM Parser conserve les sept décimales en vue UTC et exporte le FILETIME brut sous forme de chaîne décimale (un entier 64 bits ne tient pas sans perte dans un nombre JSON).

Quel événement marque l'horodatage

L'analyse de bam.sys par Maxim Suhanov montre que l'horodatage est mis à jour à la création du processus et à sa terminaison (BAM internals). La valeur est donc le plus récent de ces événements que BAM a enregistré. Pour les programmes restés longtemps ouverts, parlez plutôt de « dernière activité enregistrée » dans vos rapports, et appuyez-vous sur Prefetch ou sur les journaux de création de processus si vous avez besoin de l'heure de lancement.

Les 16 octets restants

Sur les builds de Windows 10 étudiés par Suhanov, les valeurs BAM font 24 octets : le FILETIME, puis 16 octets de plus. Son analyse relie l'un des DWORD finaux à l'état de modération (l'utilisateur a-t-il laissé Windows gérer l'activité en arrière-plan ou modifié le réglage pour cette application ?) et note que les entrées dont l'état n'est pas celui par défaut échappent au nettoyage par ancienneté (source). Au-delà, la structure n'est pas documentée publiquement.

Conséquences pratiques :

  • Ne supposez pas une taille fixe de 24 octets ; lisez les 8 premiers octets et conservez le reste.
  • Gardez les octets bruts dans votre export. Notre outil affiche les données complètes dans le panneau de détail (« Données brutes ») et dans la colonne CSV DataHex, pour que vous puissiez revenir sur les octets finaux si de nouvelles recherches paraissent.

Noms de valeur : chemins de périphérique et packages

Chemins de périphérique NT

La plupart des noms ressemblent à \Device\HarddiskVolume3\Windows\System32\cmd.exe. C'est le chemin de périphérique NT du noyau : l'objet volume, puis le chemin sur ce volume. Il n'y a pas de lettre de lecteur, car les lettres sont une correspondance établie en mode utilisateur (Microsoft Learn : définir un nom de périphérique MS-DOS).

Pour rattacher HarddiskVolumeN à une lettre hors ligne :

  • La plupart du temps, le volume système est celui qui porte les entrées \Windows\System32\… ; tout ce qui a ce numéro de volume est sur C:.
  • Pour les autres numéros, recoupez avec des artefacts qui enregistrent les deux formes — par exemple les fichiers Prefetch, qui stockent les chemins de périphérique et les numéros de série des volumes (format libscca). Une sortie de collecte à chaud qui a noté à la fois le chemin de périphérique et la lettre aide aussi. (La clé MountedDevices de la même ruche relie les lettres à des identifiants de volume, pas aux numéros HarddiskVolumeN : elle n'aide que partiellement.)
  • Les numéros de volume sont attribués par le système en fonctionnement et ne sont pas un identifiant stable d'une machine à l'autre, ni même forcément après des changements de configuration sur une même machine.

Noms de famille de package

Les applications empaquetées (Store, MSIX) apparaissent sous leur nom de famille de package : Microsoft.WindowsCalculator_8wekyb3d8bbwe. La partie après le tiret bas est le hash d'identifiant de l'éditeur, la partie avant est le nom du package (Microsoft Learn : identité de package). Il n'y a ni chemin ni nom d'exécutable. Notre parseur affiche le nom du package comme programme, marque la ligne comme application et n'applique pas les heuristiques de chemin.

Autres formes

Il arrive de rencontrer un nom qui n'est ni l'un ni l'autre — par exemple un chemin sans le préfixe \Device\. Ne le jetez pas : l'outil le classe en « autre » et décode quand même l'horodatage.

L'heure de dernière écriture de la clé SID

Chaque clé de registre possède un FILETIME de dernière écriture dans son nœud de clé (spécification msuhanov/regf). Pour une clé SID BAM, cette heure bouge dès que n'importe quelle valeur en dessous change. Elle vous donne :

  • Un contrôle de cohérence : l'heure de la clé doit être égale ou postérieure à l'heure de la valeur la plus récente de cet utilisateur. Une heure de clé très postérieure à toutes les valeurs suggère qu'une entrée a été supprimée ou réécrite ensuite — voir l'anti-forensique BAM.
  • Une borne inférieure de la dernière mise à jour de la ruche pour cet utilisateur.

Notre outil l'affiche sous « Dernière écriture de la clé SID » dans le panneau de détail et l'exporte sous SidKeyLastWriteUtc.

Les champs de la ruche qui comptent

Quelques champs du bloc de base changent la confiance à accorder aux valeurs (libregf) :

OffsetChampPourquoi c'est important pour BAM
0Signature regfConfirme qu'il s'agit bien d'une ruche
4 / 8Numéros de séquence primaire / secondaireValeurs différentes = ruche dirty : des écritures BAM récentes peuvent être dans les journaux
12FILETIME de dernière écritureDernière écriture du fichier principal
48Nom de fichier intégréDistingue SYSTEM de SOFTWARE, SAM… quand les fichiers ont été renommés

Comment le parseur restitue tout cela

Colonne de sortieSource
LastExecutionUtc8 premiers octets des données, en ISO-8601 à 100 ns
FileTimeMême valeur, en décimal brut
ProgramNom du fichier, ou nom du package sans le hash de l'éditeur
Path, VolumeNom de la valeur ; HarddiskVolumeN quand il existe
SID, UserNom de la clé ; compte issu de la ProfileList ou libellé de SID bien connu
Service, ControlSet, ActiveControlSet, LegacyLayoutEmplacement de la clé dans la ruche
SidKeyLastWriteUtcHorodatage du nœud de clé
DataHexDonnées complètes de la valeur

Déposez une ruche dans le BAM/DAM Parser et ouvrez le panneau de détail d'une ligne pour voir tous ces champs côte à côte. Pour le même exercice avec d'autres artefacts du registre, Registry Parser couvre le reste de la ruche.

Sources

Articles liés