Ce qu'enregistre FSEvents
macOS tient un journal persistant des modifications du système de fichiers, écrit par le démon fseventsd pour que Time Machine, Spotlight et les clients de synchronisation puissent savoir ce qui a changé depuis un point donné. Chaque volume dispose d'un dossier caché .fseventsd contenant des fichiers journaux compressés en gzip. Chaque enregistrement comprend un chemin, un identifiant d'événement sur 64 bits et un ensemble de flags (création, suppression, renommage, modification, attribut étendu modifié, montage, …) ; les formats récents ajoutent le node ID du fichier.
Pour une investigation, c'est un historique du volume au niveau des chemins, qui inclut souvent des fichiers qui n'existent plus : une archive restée brièvement dans Downloads, un LaunchAgent écrit puis supprimé, des documents rassemblés dans un dossier caché, ou le contenu d'une clé USB.
Ce que décode le parseur
- Fichiers journaux gzip, y compris tronqués ou endommagés (tout ce qui est récupérable est conservé et le dommage est signalé), plusieurs membres gzip par fichier, et pages déjà décompressées.
- Pages dans les trois formats sur disque : 1SLD (chemin, identifiant d'événement, flags), 2SLD (+ node ID, macOS 10.13 et versions ultérieures) et 3SLD (+ un champ supplémentaire de 4 octets, macOS 14 et versions ultérieures), plusieurs pages par fichier.
- Chaque bit de flag décodé en un nom clair, avec la valeur brute et les noms utilisés par FSEventsParser et mac_apt.
- fseventsd-uuid (identité du flux et début de l'historique) et marqueurs no_log, un volume par dossier .fseventsd (volume Data, racine du volume ou disque externe).
- Fenêtres temporelles de chaque fichier journal déduites des dates de modification, paires de renommage par node ID, arborescence des chemins, et exports CSV, Timesketch et JSON.
Les questions auxquelles il aide à répondre
- Ce fichier ou ce dossier a-t-il existé sur le Mac, et a-t-il été créé, modifié, renommé ou supprimé ?
- Un LaunchAgent ou un LaunchDaemon a-t-il été écrit, et quand (approximativement) ?
- Des documents ont-ils été rassemblés dans un dossier caché, copiés sur un volume externe, puis supprimés ?
- L'attribut de quarantaine a-t-il probablement été retiré d'un téléchargement, ou une autorisation de confidentialité (TCC) modifiée ?
- Qu'est-ce qui a été écrit sur une clé USB, d'après le propre .fseventsd de la clé ?
Limites à garder en tête
- Pas d'horodatage : les enregistrements n'ont qu'un identifiant d'événement. Les heures sont des fenêtres entre les dates de modification des fichiers journaux, et ne valent que ce que la collecte en a préservé.
- Ni utilisateur ni processus : FSEvents n'indique pas qui a effectué une modification. Le champ supplémentaire 3SLD est décodé comme un identifiant d'utilisateur par FSEventsParser ; sa signification n'est pas documentée par Apple.
- Fusion : plusieurs modifications d'un même chemin peuvent être regroupées en un seul enregistrement (ex. Created + Modified + Removed) ; leur ordre au sein de l'enregistrement est inconnu.
- Rétention : fseventsd purge les anciens journaux selon son propre calendrier ; quelques semaines à quelques mois d'historique sont courants, sans garantie.
- Non journalisés : volumes en lecture seule, partages réseau, et les événements les plus récents encore en mémoire au moment de la copie des journaux.
Le collecter en une commande
- Mac allumé, Terminal avec l'Accès complet au disque (Full Disk Access) : sudo tar -czf ~/Desktop/fseventsd.tar.gz -C /System/Volumes/Data .fseventsd, puis déposez l'archive ici.
- UAC : le profil ir_triage (ou l'artefact files/logs/macos.yaml seul) collecte chaque dossier .fseventsd dans un tar.gz que cette page lit tel quel.
- Image disque : montez-la en lecture seule, puis archivez le .fseventsd du volume Data de la même façon.
FAQ
Mes fichiers sont-ils envoyés quelque part ?
Non. Le parseur est écrit en Rust, compilé en WebAssembly et s'exécute dans un Web Worker de votre navigateur. Les fichiers ne quittent jamais votre machine ; une fois chargée, la page fonctionne hors ligne.
Pourquoi n'y a-t-il pas d'horodatage exact ?
Les enregistrements FSEvents n'en contiennent pas. Un fichier journal est écrit lorsque fseventsd le vide sur disque : sa date de modification est donc une borne supérieure pour ses enregistrements, et la date du fichier journal précédent une borne inférieure approximative. Le parseur affiche cette fenêtre pour chaque enregistrement et indique comment elle a été calculée.
Quelles versions de macOS sont prises en charge ?
Les trois formats sur disque : 1SLD (anciennes versions de macOS), 2SLD (macOS 10.13 High Sierra et versions ultérieures, ajoute les node IDs) et 3SLD (macOS 14 Sonoma et versions ultérieures, ajoute un champ de 4 octets). Les dossiers mixtes sont gérés.
Peut-il lire directement une collecte UAC ?
Oui. Déposez le tar.gz UAC : la page le lit en flux, ne conserve que les fichiers .fseventsd et utilise les dates de modification stockées dans l'archive. Les ZIP Aftermath et Velociraptor ainsi que les simples dossiers fonctionnent aussi.
Que se passe-t-il avec un fichier journal tronqué ou corrompu ?
Tout ce qui peut être décompressé est analysé, les enregistrements complets sont conservés, et le fichier est marqué Partiel avec la raison (gzip tronqué, CRC incorrect, page dépassant les données, enregistrement endommagé).
Comment se compare-t-il à FSEventsParser et mac_apt ?
Il décode les mêmes structures sur disque et les mêmes bits de flags (les noms des deux outils sont affichés), ajoute des fenêtres temporelles, l'appariement des renommages, une arborescence des chemins et des constats, et ne nécessite ni Python ni installation. Pour un usage judiciaire, validez les enregistrements importants avec un second outil.