Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
LogFileParser — Analyseur pour $LogFile sur NTFS | Kitploit
Outils/GitHubGitHub/jschicht/logfileparser
Criminalistique DisqueAnalyse ForensiqueRécupération de DonnéesCriminalistique NumériqueAnalyse de BinairesAnalyse de Journaux
GitHubjschicht/logfileparser

LogFileParser

Analyseur pour $LogFile sur NTFS

Voir le dépôt
218299il y a 3 moisVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Fonctionnalités Décoder et extraire les enregistrements $LogFile et les entrées de transaction. Décoder les modifications d'attributs NTFS. Résoudre optionnellement toutes les informations de liste de dataruns disponibles dans $LogFile. Option : « Reconstruct data runs ». Récupérer les transactions depuis l'espace résiduel (slack space) au sein de $LogFile. Choisir de reconstruire les en-têtes manquants ou endommagés des transactions trouvées dans le slack. Option : « Rebuild header ». Affiner optionnellement le résultat avec une valeur de niveau d'erreur LSN. Option : « LSN error level ». Journalise en csv et importe dans une base de données sqlite avec plusieurs tables. Importer optionnellement la sortie csv de mft2csv dans la base de données. Choisir parmi 6 formats d'horodatage différents. Choisir la précision de l'horodatage : None, MilliSec et NanoSec. Choisir le séparateur de précision à la milliseconde. Choisir le séparateur de précision à la nanoseconde. Choisir l'ajustement de région pour les horodatages. Par défaut, les horodatages sont présentés en UTC 0.0. Choisir le séparateur de sortie. Option : « Set separator ». Sortie UNICODE ou ANSI configurable. Option « Unicode ». Taille d'enregistrement MFT configurable (1024 ou 4096). Option « MFT record size ». Décoder optionnellement des transactions individuelles ou des transactions partielles (fragment). Option pour reconstruire les RCRD à partir d'une ou plusieurs transactions (fragments). Option pour configurer un $LogFile endommagé. Utile avec des RCRD extraits comme entrée. Option pour ignorer les fixups (pour un $LogFile endommagé, typiquement extrait de la mémoire). Sortie verbeuse détaillée dans debug.log. Liste configurable de lsn séparés par des virgules pour déclencher des informations ultra-verbeuses sur des transactions spécifiques dans debug.log. Configuration pour OS 32 bits. Configuration pour l'extraction de données binaires des mises à jour de données résidentes. sql autogénéré pour importer la sortie dans une base de données MySql. Option pour ignorer tout ce qui concerne sqlite3 afin d'accélérer l'analyse totale. Mode ligne de commande optionnel. Prend en charge errorlevel adapté aux scripts batch.

Contexte NTFS est conçu comme un système de fichiers récupérable. Cela se fait par la journalisation de toutes les transactions qui modifient la structure du volume. Ainsi, toute modification d'un fichier sur le volume nécessitera que quelque chose soit également journalisé dans $LogFile, afin de pouvoir être annulé en cas de défaillance du système à tout moment. Par conséquent, beaucoup d'informations sont écrites dans ce fichier, et comme il est circulaire, cela signifie que les nouvelles transactions écrasent les enregistrements plus anciens du fichier. Ainsi, la quantité de données historiques pouvant être récupérées à partir de ce fichier est quelque peu limitée. Là encore, cela dépendrait du type de volume et de la taille du $LogFile. Sur le disque système d'un système fréquemment utilisé, vous n'obtiendrez probablement que quelques heures d'historique, alors qu'un disque externe/secondaire contenant des fichiers de sauvegarde contiendra probablement plus d'informations historiques. Et un fichier de 2 Mo contiendra bien moins d'historique qu'un fichier de 256 Mo. Donc dans quelle plage de taille ce fichier peut-il être configuré ? De 256 Ko et plus. Configurer la taille à 2 Go peut se faire ainsi : « chkdsk D: /L:2097152 ». L'impact d'un fichier journal de grande taille sur les performances dépasse le cadre de ce texte. Le définir en dessous de 2048 n'est normalement pas possible. Cependant, c'est possible en patchant untfs.dll :

Télécharger l’outil
http://code.google.com/p/mft2csv/wiki/Tiny_NTFS

Intro Ce parseur décodera et extraira de nombreuses informations de transaction depuis le $LogFile sur NTFS. Plusieurs csv sont générés ainsi qu'une base de données sqlite nommée ntfs.db contenant toutes les informations pertinentes. La sortie est extrêmement détaillée et de très bas niveau, ce qui signifie qu'elle nécessite de bonnes connaissances NTFS pour être comprise. Les types de transactions Redo actuellement traités avec un décodage de sortie significatif sont :

InitializeFileRecordSegment CreateAttribute DeleteAttribute UpdateResidentValue UpdateNonResidentValue UpdateMappingPairs SetNewAttributeSizes AddindexEntryRoot DeleteindexEntryRoot AddIndexEntryAllocation DeleteIndexEntryAllocation WriteEndOfIndexBuffer SetIndexEntryVcnRoot SetIndexEntryVcnAllocation UpdateFileNameRoot UpdateFileNameAllocation SetBitsInNonresidentBitMap ClearBitsInNonresidentBitMap OpenNonresidentAttribute OpenAttributeTableDump AttributeNamesDump DirtyPageTableDump TransactionTableDump UpdateRecordDataRoot UpdateRecordDataAllocation CompensationlogRecord

La liste des attributs actuellement pris en charge : $STANDARD_INFORMATION $ATTRIBUTE_LIST $FILE_NAME $OBJECT_ID $SECURITY_DESCRIPTOR $VOLUME_NAME $VOLUME_INFORMATION $DATA $INDEX_ROOT $INDEX_ALLOCATION $REPARSE_POINT $EA_INFORMATION $EA $LOGGED_UTILITY_STREAM

Donc, en gros, tous les attributs sont pris en charge.

Explication des différentes sorties générées :

LogFile.csv : Le csv principal généré par le parseur.

LogFile_DataRuns.csv Les informations d'entrée nécessaires à la reconstruction des dataruns

LogFile_DataRunsResolved.csv La sortie finale des dataruns reconstruits

LogFile_INDX_I30.csv Tous les enregistrements d'index extraits et décodés (IndexRoot/IndexAllocation)

LogFileJoined.csv Identique à LogFile.csv, mais avec les informations de nom de fichier jointes depuis le $UsnJrnl ou le csv de mft2csv.

MFTRecords.bin $MFT factice recréé à partir des enregistrements MFT trouvés dans les transactions InitializeFileRecordSegment. On peut utiliser mft2csv sur celui-ci (pensez à configurer correctement « broken MFT » et « Fixups »).

LogFile_lfUsnJrnl.csv Enregistrements pour le $UsnJrnl qui ont été décodés au sein de $LogFile

LogFile_UndoWipe_INDX_I30.csv Toutes les opérations d'annulation pour l'effacement des index de répertoire (INDX).

LogFile_AllTransactionHeaders.csv Tous les en-têtes des transactions décodées.

LogFile_BitsInNonresidentBitMap.csv Toutes les opérations SetBitsInNonresidentBitMap décodées.

LogFile_DirtyPageTable32bit.csv et LogFile_DirtyPageTable64bit.csv Toutes les entrées de chaque opération DirtyPageTableDump décodée pour les OS 32 bits et 64 bits.

LogFile_Mft_ObjectId_Entries.csv Attributs $ObjectId décodés.

LogFile_ObjIdO.csv Tous les décodages du fichier système $ObjId:$O.

LogFile_OpenAttributeTable.csv Toutes les entrées de chaque opération OpenAttributeTableDump décodée.

LogFile_QuotaO.csv Tous les décodages du fichier système $Quota:$O.

LogFile_QuotaQ.csv Tous les décodages du fichier système $Quota:$Q.

LogFile_RCRD.csv Tous les en-têtes des enregistrements RCRD décodés.

LogFile_ReparseR.csv Tous les décodages du fichier système $Reparse:$R.

LogFile_SecureSDH.csv Tous les décodages du fichier système $Secure:$SDH.

LogFile_SecureSII.csv Tous les décodages du fichier système $Secure:$SII.

LogFile_SecurityDescriptors.csv Descripteurs de sécurité décodés. La source peut provenir de $SECURITY_DESCRIPTOR ou de $Secure:$SDS.

LogFile_SlackAttributeNamesDump.csv Toutes les entrées des transactions AttributeNamesDump décodées trouvées dans l'espace résiduel.

LogFile_SlackOpenAttributeTable.csv Toutes les entrées des transactions OpenAttributeTableDump décodées trouvées dans l'espace résiduel.

LogFile_TransactionTable.csv Transactions TransactionTableDump décodées.

LogFile_Filenames.csv Tous les noms de fichiers résolus avec MftRef, MftRefSeqNo et Lsn.

LogFile_TxfData.csv Données décodées de $DATA:$TXF_DATA dans $LOGGED_UTILITY_STREAM.

LogFile_UpdateFileName_I30.csv Tous les décodages de UpdateFileNameRoot et UpdateFileNameAllocation pour les opérations redo et undo.

LogFile_CompensationlogRecord.csv Tous les décodages de CompensationlogRecord. Non pertinent pour nt5.x.

Ntfs.db Un fichier de base de données sqlite avec des tables presque équivalentes aux csv ci-dessus. La base de données contient 5 tables : DataRuns IndexEntries LogFile LogFileTmp (table temporaire utilisée lors de la recréation des dataruns). UsnJrnl

Horodatages Les valeurs par défaut sont présentées en UTC 0.00, et avec une précision à la nanoseconde. Le format par défaut est YYYY-MM-DD HH:MM:SS:MSMSMS:NSNSNSNS. Ceux-ci peuvent être configurés. Les différents horodatages font référence à : CTime signifie File Create Time (heure de création du fichier). ATime signifie File Modified Time (heure de modification du fichier). MTime signifie MFT Entry modified Time (heure de modification de l'entrée MFT). RTime signifie File Last Access Time (heure du dernier accès au fichier).

Reconstruction des dataruns.

De nombreuses opérations sur le système de fichiers déclencheront une transaction dans le $LogFile. Celles relatives à l'attribut $DATA, c'est-à-dire au contenu d'un fichier, sont jusqu'à présent identifiées comme suit :

InitializeFileRecordSegment CreateAttribute UpdateMappingPairs SetNewAttributeSizes

Elles laissent toutes des informations différentes dans le $LogFile. Les modifications de données résidentes se comportent différemment et ne peuvent pas être reconstruites aussi simplement, du moins sur les volumes NTFS provenant de versions modernes de Windows.

InitializeFileRecordSegment correspond à la création d'un nouveau fichier. Ainsi, il aura l'attribut $FILE_NAME, ainsi que le contenu original de l'attribut $DATA, y compris les dataruns. Comme le $LogFile est circulaire et que les événements plus anciens sont écrasés par les plus récents, le défi avec le $LogFile est d'obtenir des informations remontant suffisamment loin dans le temps. Cependant, si InitializeFileRecordSegment est présent, alors nous devrions pouvoir tout reconstruire, puisque tous les enregistrements écrits après celui-ci seront également disponibles. Nous aurons également des informations sur l'offset vers la liste de dataruns. Il s'agit d'un offset relatif calculé depuis le début de l'attribut $DATA. C'est une information importante à avoir pour calculer où, dans la liste de dataruns, UpdateMappingPairs a effectué sa modification.

CreateAttribute est l'attribut original lors de sa première création (s'il n'est pas écrit dans le cadre d'InitializeFileRecordSegment). Avec celui-ci aussi, nous devrions pouvoir reconstruire les dataruns puisque nous avons toutes les transactions à notre disposition. Cependant, celui-ci ne nous fournira pas en lui-même le nom du fichier. Ici aussi, nous avons l'offset vers la liste de dataruns disponible, ce qui est extrêmement utile pour résoudre UpdateMappingPairs.

UpdateMappingPairs est une transaction effectuée lors de modifications du $DATA/dataruns (le contenu du fichier a changé). Les informations trouvées dans cette transaction ne sont pas complètes, et elle contient uniquement les nouvelles valeurs ajoutées à la liste de dataruns existante. Elle contient également un offset relatif qui nous indique où, dans la liste de dataruns, les modifications ont été écrites. Cet offset est utilisé en combinaison avec l'offset vers le datarun tel que trouvé dans InitializeFileRecordSegment et CreateAttribute.

SetNewAttributeSizes est une transaction qui contient des informations sur toute modification liée à une valeur de taille effectuée sur l'attribut $DATA. Celle-ci est étroitement liée à UpdateMappingPairs qui ne contient que les modifications de dataruns.

Avec les 4 différentes opérations redo ci-dessus, on peut, pour un numéro de référence donné (fichier distinct), reconstruire une partie de l'historique des modifications du système de fichiers pour ce fichier. En raison de sa circularité, nous n'avons qu'une partie de l'historique, la plus récente. L'étendue de l'historique que nous pouvons récupérer dépend fortement du type de volume cible. S'il s'agit d'un volume système, alors une semaine d'historique est probablement plus que ce que vous pouvez espérer, tandis qu'un disque amovible, externe ou secondaire contiendra bien plus d'historique. Ainsi, nous pouvons reconstruire l'historique complet d'un fichier supprimé (dont l'enregistrement $MFT a été écrasé), et recréer à son tour la liste de dataruns pour effectuer une récupération. Dans d'autres cas, nous ne pourrons peut-être pas reconstruire l'historique complet, de sorte que seule une liste de dataruns partielle pourra être reconstruite. Le fichier csv final avec les dataruns ajustés, LogFile_DatarunsModified.csv, affichera les dataruns différemment.

Explication : Ceux commençant par un « ! » indiquent que la liste complète de dataruns a été recréée. Ceux commençant par un « ? » indiquent une récupération partielle, le nombre de « ** » représentant les octets manquants de la liste de dataruns originale.

Pour simplifier la récupération d'un fichier à partir d'un datarun, on peut utiliser le PoC joint appelé ExtractFromDataRuns. Il est assez explicite. Il suffit de renseigner la liste complète de dataruns, la taille réelle et la taille initiale, ainsi qu'un nom pour le fichier de sortie. On peut optionnellement choisir de traiter des fichiers image (disque ou partition). Cochez également si un indicateur compressed/sparse a été détecté. Lui fournir une liste de dataruns partiellement reconstruite ne fonctionnera pas ! Veuillez noter que les flux de données alternatifs peuvent être distingués par la présence d'un dataname et également par des valeurs OffsetInMft différentes pour un fileref donné.

Le package de téléchargement séparé « SampleTinyNtfsVolume.zip » contient une image de partition avec un petit volume NTFS pour tester. Sur le volume se trouvent 2 fichiers non résidents supprimés dont l'enregistrement MFT a été écrasé par de nouveaux fichiers. Tout logiciel de récupération décent basé sur la recherche de signatures devrait pouvoir récupérer le fichier jpg (Tulips.jpg), car il est contigu. Cependant, ils n'identifieront très probablement pas son nom de fichier, ni rien d'autre à propos du fichier. Le second fichier ne sera probablement pas récupérable avec des outils standards, car il est fragmenté (compressé), et comme son enregistrement MFT a été écrasé, résoudre le fichier sans la liste de dataruns est impossible. En utilisant le PoC, nous pouvons identifier le nom du fichier (suspicious.zip) et l'extraire en parfait état (ne vous inquiétez pas, il ne contient qu'une des images d'exemple fournies avec Windows). Lisez le fichier readme.DataRunsResolved.txt pour les détails concernant l'image d'exemple et la façon d'interpréter la sortie et de récupérer les fichiers.

Ce que nous avons accompli avec cela est de récupérer des fichiers fragmentés dont l'enregistrement MFT a été écrasé. Comme nous avons reconstruit un historique partiel/complet des dataruns, nous pouvons avec certitude (du moins si l'historique complet est reconstruit) déterminer si les données résiduelles d'un fichier ont appartenu ou non au fichier donné.

Limitation. La reconstruction des dataruns est cassée avec UNICODE (ANSI fonctionne). L'import de la sortie Mft2Csv est cassé si le csv est en UNICODE (ANSI fonctionne). Les mises à jour partielles des IndexRecords (IndexRoot/IndexAllocation) sont très difficiles à interpréter, car nous n'avons probablement pas connaissance de l'index original. Les enregistrements complets sont toutefois OK. La circularité d'un fichier de 65 Mo impose une restriction inhérente et absolue sur le nombre de transactions FS historiques. Les disques système ont donc un historique limité dans $LogFile, tandis que les disques externes/secondaires ont plus de transactions historiques stockées. On peut augmenter la taille de $LogFile avec chkdsk (chkdsk c: /L:262144). Les modifications des données des fichiers résidents ne sont pas stockées dans $LogFile, seule l'information qu'une modification a été effectuée est stockée.

Note Le $UsnJrnl contient des informations d'une manière plus conviviale. Par exemple, chaque enregistrement contient fileref, nom de fichier, horodatage et explication de ce qui s'est produit. Il contient également bien plus d'informations historiques que $LogFile, mais sans beaucoup de détails. Si $UsnJrnl est actif, alors toutes les transactions qui y ont été écrites pendant la durée de vie de recyclage du $LogFile sont également présentes dans $LogFile. Cela signifie qu'il n'y a aucune raison de décoder le $UsnJrnl pour mieux comprendre $LogFile.

Espace résiduel (slack space) Dans ce contexte, l'espace résiduel désigne l'espace au sein d'un enregistrement RCRD qui reste dans l'enregistrement au-delà de la dernière transaction. Je ne pense pas que cela ait été décrit auparavant, alors laissez-moi expliquer. Le slack de volume est l'espace inutilisé entre la fin du système de fichiers et la fin de la partition où réside le système de fichiers. Le slack d'enregistrement MFT est à peu près la même chose, mais fait référence à l'espace trouvé après la signature de fin d'enregistrement (0xFFFFFFFF) jusqu'à la fin physique de l'enregistrement (0x400 ou 0x1000). Et l'espace résiduel au sein du $LogFile est donc l'espace trouvé au-delà de la dernière transaction et jusqu'à la fin de l'enregistrement RCRD (généralement 0x1000). Ces transactions provenant du slack sont en fait là depuis avant que le $LogFile ne soit recyclé (écrasé). Il existe également un algorithme identifiant les transactions valides depuis l'espace résiduel. De plus, il peut également exister plusieurs couches de cet espace résiduel. Exemple : Disons que la dernière transaction d'un enregistrement RCRD donné se terminait à l'offset 0x00007D27. De cet offset jusqu'à 0x00007FFF, nous avons 0x2D8 octets d'espace résiduel. Il se pourrait alors que les octets commençant à 0x00007D28 ne soient pas un en-tête de transaction valide car ils se trouvent au milieu d'une transaction. Le programme tentera alors (s'il est configuré pour) de reconstruire un pseudo en-tête avec des valeurs valides afin de décoder la transaction. S'il échoue à reconstruire un en-tête valide, il considère que trop d'informations de l'en-tête original sont perdues, et il considérera ces octets comme perdus, puis continuera à scanner le reste de l'espace résiduel à la recherche d'un en-tête de transaction valide. Les octets perdus seront journalisés dans debug.log pour que vous puissiez les examiner. En revanche, s'il a pu reconstruire un en-tête valide, les informations à ce sujet se trouveront dans le champ lf_TextInformation. Disons qu'il a identifié une transaction commençant à l'offset 0x00007D48 et de taille 0xB0. Ensuite, une autre transaction valide a été identifiée immédiatement après à l'offset 0x00007DF8 avec une taille de 0xE0. Cependant, à l'offset 0x00007ED8, il n'y avait pas d'en-tête de transaction valide. Cela signifie que nous sommes maintenant à la deuxième couche d'espace résiduel au sein de cet enregistrement RCRD. Maintenant, disons que le programme, après un nouveau scan, a pu identifier un en-tête de transaction valide à l'offset 0x00007F18. Cette transaction serait marquée dans le csv avec une valeur de 2 dans le champ FromRcrdSlack. Cependant, considérez la taille totale de la transaction poussant l'offset au-delà de la taille de l'enregistrement RCRD. En substance, il s'agirait d'une transaction partiellement récupérée, qui pourrait se décoder correctement, mais qui sera trouvée avec une valeur de 1 dans le champ IncompleteTransaction. Rappelez-vous que le debug.log est très détaillé et aidera à comprendre la sortie décodée, en particulier ce qui provient de l'espace résiduel.

Configuration 32 bits vs 64 bits. Ce paramètre est important à définir correctement. Il indique quel OS a traité le volume cible. Le point est que la gestion de OpenAttributeTable diffère entre un OS 32 bits et 64 bits. Il peut bien sûr y avoir des cas (par exemple un disque usb) où le volume a été traité par plusieurs OS différents, auquel cas il peut être délicat d'obtenir ce paramètre 100 % correct. À partir de la version 2.0.0.8, un mécanisme d'autodétection a été implémenté. Cependant, il est toujours recommandé de tenter de définir correctement cette configuration. Dans le champ TextEinformation, un message « Mixed OS detected » sera imprimé lorsqu'il détecte un format OpenAttributeTableDump différent de la configuration ou lorsque les deux types sont détectés. Quoi qu'il en soit, il peut être utile d'examiner le LogFile_OpenAttributeTable.csv pour évaluer la sortie. Si vous voyez des entrées avec des colonnes contenant des valeurs étranges, alors ce paramètre particulier est peut-être erroné. Si c'est le cas, alors la plupart des valeurs sont complètement fausses. Par exemple, la plupart des champs AttributeType sont UNKNOWN, Lsn n'est pas dans la plage actuelle, MftRef est trop élevé et MftRefSeqNo vaut 0. Attention, AttributeType est résolu comme UNKNOWN pour les entrées non initialisées de la table, mais celles-ci sont faciles à repérer car toutes les valeurs après AllocatedOrNextFree sont à 0 et sont parfaitement valides. Ces défis semblent résolus avec l'autodétection implémentée dans la version 2.0.0.8.Extraction des mises à jour d'attributs résidents (UpdateResidentValue). L'opération UpdateResidentValue concerne les mises à jour du contenu des attributs résidents. La configuration « Extract resident updates of min size » vous permettra d'extraire la modification binaire de l'attribut résident. Le champ de saisie correspond à la taille minimale en octets à extraire. L'utilisation la plus intéressante de cette fonctionnalité concerne probablement les volumes gérés par Nt5.x (XP, 2003), où les mises à jour complètes de l'attribut $DATA (contenu normal d'un fichier) sont stockées dans les champs redo et undo avec UpdateResidentValue. Les fichiers dont le contenu $DATA est résident sont des fichiers de taille réduite, au maximum 744 octets (avec une taille d'enregistrement MFT de 1024) mais généralement moins. Les données extraites sont écrites dans un sous-dossier nommé ResidentExtract. Les fichiers de sortie sont nommés selon une logique de ce type : MFT($MFTRef)$OffsetInMft$AttributeOffset_LSN($Lsn)$Operation.bin. Par exemple MFT(1643)_0x0098_0x00B8_LSN(1415242628)redo.bin signifierait que l'enregistrement MFT numéro 1643, l'offset de l'attribut cible dans la MFT est 0x98, l'offset de la modification au sein de l'attribut cible est 0xB8, le LSN de la transaction est 1415242628, et qu'il s'agissait d'une opération redo. Les extractions pour les opérations undo contiennent donc les données à cet offset avant la modification. L'activation de cette fonctionnalité déclenchera des sorties quelque peu non pertinentes et sans intérêt. La plupart des faux positifs sont automatiquement filtrés, mais certains sont inévitables. Par exemple, les mises à jour de $INDEX_ROOT, $ATTRIBUTE_LIST et $BITMAP peuvent être incluses. Il est toutefois possible de retracer manuellement les attributs pour filtrer les non-$DATA en comparant l'OffsetInMft avec ce qui se trouve dans l'InitializeFileRecordSegment pertinent ou, le cas échéant, dans la $MFT elle-même. À partir de la version 2.0.0.13, l'extraction de $EA a été ajoutée. Voir la note sur les attributs $EA.

Filenames csv À partir de la version 2.0.0.6, une nouvelle fonctionnalité a été implémentée pour exporter tous les noms de fichiers identifiés. La source de ces entrées provient de InitializeFileRecordSegment, UpdateNonResidentValue, AddindexEntryRoot, DeleteindexEntryRoot, AddIndexEntryAllocation, DeleteIndexEntryAllocation et WriteEndOfIndexBuffer. Le csv contenant ces noms de fichiers, LogFile_FileNames.csv, contient donc un historique reconstruit de tous les noms de fichiers, MftRef et MftRefSeqNo pendant toute la durée de l'historique du $LogFile. Vous pourrez ainsi voir tous les différents noms de fichiers qu'un enregistrement MFT donné a eus pendant la période couverte par le $LogFile. Lorsqu'un fichier est renommé, le MftrefSeqNo n'est pas incrémenté. Lorsqu'un enregistrement MFT est marqué comme supprimé, puis réutilisé ultérieurement, le MftRefSeqNo est incrémenté de un lors de la nouvelle initialisation.

$TXF_DATA Avec Transactional NTFS (TxF), il y aura des occurrences du flux nommé $TXF_DATA dans l'attribut $LOGGED_UTILITY_STREAM. Il est toujours résident, et il peut y en avoir plusieurs par fichier. L'usage n'est pas répandu, et Microsoft encourage d'ailleurs des méthodes alternatives. [quote]Microsoft recommande fortement aux développeurs d'utiliser des moyens alternatifs pour répondre aux besoins de vos applications.[/quote]. Il semble que seuls quelques mécanismes de mise à jour logicielle l'utilisent. Chaque fichier/dossier créé avec celui-ci obtient un fileref unique (à ne pas confondre avec les numéros d'enregistrement MFT). C'est ce fileref unique qui servira à nommer le fichier lorsqu'il sera supprimé ultérieurement (et déplacé dans le dossier $Extend$RmMetadata$Txf). L'attribut $DATA standard non nommé du fichier $Tops contient des informations sur l'endroit où la prochaine transaction irait dans le $TxfLogContainer00000000000000000001. Le flux $DATA nommé $T du $Tops contient les données réelles (issues des opérations de fichiers transactionnelles) qui sont recyclées. Dans $TXF_DATA, il existe également un champ appelé LsnUserData qui est un offset dans le $TxfLogContainer00000000000000000001 où l'on trouve beaucoup plus de détails sur les transactions. LsnNtfsMetadata contient également un offset dans le même fichier $TxfLogContainer00000000000000000001. Notez que ces offsets peuvent être modifiés ultérieurement, et sont alors référencés dans une opération UpdateResidentValue dans le $LogFile. Le champ MftRef_RM_Root est le numéro d'enregistrement de fichier de la racine du gestionnaire de ressources responsable de la transaction associée à ce fichier (la valeur par défaut est 5, qui est le répertoire racine). Pour les mises à jour de $TXF_DATA via UpdateResidentValue, le texte « Partial update » est ajouté dans le champ TextInformation. Pour cette raison, il peut également exister des valeurs comme 0x0000000000007E-- dans LsnUserData. En effet, un UpdateResidentValue de 31 octets signifie que les 3 premiers membres de la structure complète sont manquants, et qu'un octet de LsnUserData est également manquant. L'octet manquant est l'« octet de poids faible », donc 2 caractères/nibbles de « - » chacun, en remplacement pour indiquer l'octet inconnu manquant (en réalité simplement l'octet existant). Si UpdateResidentValue était à 32 octets, alors aucun caractère/nibble de remplacement ne serait nécessaire puisque le LsnUserData complet aurait été fourni.

debug.log Dans ce journal sont écrits les messages d'erreur et les informations verbeuses. Si des valeurs ou commentaires étranges sont trouvés dans la sortie, recherchez le lsn dans debug.log. Généralement, la transaction entière est exportée, ce qui peut aider à comprendre. Pour faciliter les investigations sur les transactions, il peut être utile de renseigner une liste de lsn séparés par des virgules dans le champ de saisie. Les informations verbeuses pour ces lsn seront alors affichées.

$EA L'attribut $EA est un ensemble de paires nom-valeur et est supposé exister pour des raisons de compatibilité avec OS/2. Il est rarement vu utilisé, bien que certains malwares l'aient employé. Il peut y avoir plusieurs paires par attribut, mais la taille maximale de l'ensemble est de 65535 octets. Il ne peut y avoir qu'un seul attribut $EA par fichier. Un contenu plus volumineux peut être réparti sur plusieurs fichiers comme le montre le PoC EaTools ; https://github.com/jschicht/EaTools Les attributs $EA existants ne peuvent pas être modifiés directement. Des paires nom/valeur supplémentaires peuvent être ajoutées à tout moment tant que la taille de toutes les paires reste inférieure à 0xFFFF octets. Le comportement étrange de cet attribut est que tout le contenu de l'ensemble du $EA est écrit dans le $LogFile pour toute nouvelle paire. Cela vaut à la fois pour le contenu $EA résident et non résident. Cela signifie que si une troisième paire nom/valeur est ajoutée à un $EA, les 3 paires sont écrites dans le $LogFile soit via UpdateResidentValue, soit via UpdateNonResidentValue.

Todo Implémenter davantage d'analyse des données présentes dans ntfs.db. Actuellement, un certain niveau de connaissance de NTFS est nécessaire pour comprendre la sortie. Exporter le contenu $EA non résident.

Utilisation en ligne de commande Si aucun paramètre n'est fourni, l'interface graphique se lancera par défaut. Les commutateurs valides sont :

Commutateurs : /LogFileFile: $LogFile d'entrée extrait. Requis sauf si /LogFileFragmentFile: est utilisé. /LogFileFragmentFile: Permet éventuellement de fournir un fragment de $LogFile. Peut être n'importe quel fragment cassé contenant au moins 1 transaction. /MftCsvFile: Le csv de sortie du dernier Mft2Csv. Optionnel. /OutputPath: Le chemin de sortie de toute la sortie du parseur. Par défaut, le répertoire du programme. /TimeZone: Une valeur de chaîne pour le fuseau horaire. Voir les notes plus bas pour les valeurs valides. /OutputFormat: Le format de sortie du csv. Les valeurs valides peuvent être l2t, BodyFile, all. /BrokenMft: Valeur booléenne pour la gestion des MFT au format incorrect. Par défaut 0. Peut être 0 ou 1. /SkipFixups: Valeur booléenne pour ignorer les fixups. Principalement utilisé avec les dumps mémoire. Par défaut 0. Peut être 0 ou 1. /Separator: Le séparateur à utiliser dans le csv. Par défaut | /Unicode: Valeur booléenne pour le décodage des chaînes unicode. Par défaut 0. Peut être 0 ou 1. /TSFormat: Un entier de 1 à 6 pour spécifier le format d'horodatage. Lancez l'interface graphique pour voir ce qu'ils signifient. Par défaut 6. /TSPrecision: La précision à utiliser dans l'horodatage. Les valeurs valides sont None, MilliSec et NanoSec. Par défaut NanoSec. /TSPrecisionSeparator: Le séparateur à placer dans la séparation de la précision. Par défaut « . ». Lancez l'interface graphique pour voir ce que cela signifie. /TSPrecisionSeparator2: Le séparateur à placer entre MilliSec et NanoSec dans la précision de l'horodatage. Par défaut vide/rien. Lancez l'interface graphique pour voir ce que cela signifie. /TSErrorVal: Une valeur d'erreur personnalisée à placer avec les erreurs de décodage d'horodatage. La valeur par défaut est '0000-00-00 00:00:00', qui est compatible avec MySql, et représente une valeur d'horodatage invalide pour NTFS. /ReconstructDataruns: Valeur booléenne pour spécifier si la reconstruction des dataruns doit être effectuée. Par défaut 0. Peut être 0 ou 1. /MftRecordSize: La taille des enregistrements MFT. Les valeurs valides sont 1024 et 4096. Par défaut 1024. /RebuildHeadersSlack: Valeur booléenne pour spécifier si l'on doit tenter de reconstruire l'en-tête à partir de transactions cassées récupérées dans le slack. Par défaut 0. Peut être 0 ou 1. /SectorsPerCluster: Nombre de secteurs par cluster. Par défaut 8. Peut être 1,2,4,8,16,32,64 et 128. /LsnErrorLevel: Une valeur entre 0 et 1 (100%), comme seuil pour identifier une transaction valide/invalide à partir du slack, en se basant sur le lsn précédent. Par défaut 0.1 (10%). /SourceIs32bit: Valeur booléenne pour spécifier si le volume provient d'un système 32 bits. Par défaut 0 (x64). Peut être 0 ou 1. /ExtractDataUpdates: Valeur booléenne pour spécifier si l'extraction du contenu de données résident doit être effectuée. Par défaut 0. Peut être 0 ou 1. /ExtractDataUpdatesSize: Valeur pour définir la taille minimale en octets de ce qu'il faut extraire. Utilisé uniquement avec le paramètre ExtractDataUpdates. Par défaut 2 (octets) comme minimum. /VerboseLsnList: Une liste de lsn séparés par des virgules qui déclenchera le mode verbeux. Les informations de journalisation verbeuse se trouvent dans debug.log. /SkipSqlite3: Valeur booléenne pour spécifier si le parseur doit omettre toutes les opérations sqlite3. Si le ntfs.db généré (reconstruction des dataruns, import du csv mft) n'est pas utilisé, cela peut être ignoré/omis sans risque. Par défaut 0. Peut être 0 ou 1. /VerifyFragment: Valeur booléenne pour activer une validation simple sur un fragment uniquement, et non sur le parseur complet. Peut être 0 ou 1. Écrira par défaut le fragment corrigé dans OutFragment.bin sauf indication contraire dans /OutFragmentName: /OutFragmentName: Le nom de fichier de sortie dans lequel écrire le fragment corrigé, si /VerifyFragment: est défini à 1. Si omis, le nom de fichier par défaut est OutFragment.bin. /SkipFixups: Valeur booléenne pour ignorer les fixups. Utilisé avec les fragments reconstruits. Voir les exemples. Par défaut 0. Peut être 0 ou 1. /BrokenLogFile: Valeur booléenne pour traiter le $LogFile comme cassé. Utilisé avec les RCRD reconstruits et contournera plusieurs vérifications de validation. Par défaut 0. Peut être 0 ou 1.

Les TimeZone disponibles à utiliser sont : -12.00 -11.00 -10.00 -9.30 -9.00 -8.00 -7.00 -6.00 -5.00 -4.30 -4.00 -3.30 -3.00 -2.00 -1.00 0.00 1.00 2.00 3.00 3.30 4.00 4.30 5.00 5.30 5.45 6.00 6.30 7.00 8.00 8.45 9.00 9.30 10.00 10.30 11.00 11.30 12.00 12.45 13.00 14.00

Niveaux d'erreur Les codes de sortie (erreur) actuels ont été implémentés en mode ligne de commande, ce qui le rend plus adapté aux scripts batch.

  1. Aucune transaction valide n'a pu être décodée. Sortie vide.
  2. Un paramètre d'entrée probablement incorrect a été détecté. Le plus souvent il s'agira de SectorsPerCluster, et plus rarement de MftRecordSize. La valeur par défaut est SectorsPerCluster=8 et MftRecordSize=1024.
  3. Le fragment a échoué à la validation.
  4. Échec de l'écriture du fragment corrigé dans la sortie. La validation du fragment a toutefois réussi.

Ainsi, si vous obtenez %ERRORLEVEL% == 1, cela signifie que rien n'a été décodé, et si vous obtenez %ERRORLEVEL% == 2, alors le paramètre SectorsPerCluster a très probablement été défini de manière incorrecte.

Exemples : LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:2.00 /MftRecordSize:4096 /ExtractDataUpdates:1 /ExtractDataUpdatesSize:8 /SectorsPerCluster:64 /TSFormat:1 /TSPrecision:NanoSec /Unicode:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:-5.00 /MftRecordSize:1024 /SectorsPerCluster:1 /TSFormat:1 /TSPrecision:MilliSec /Unicode:0 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TSFormat:3 /ReconstructDataruns:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:7.00 /MftRecordSize:1024 /TSFormat:2 /TSPrecision:None /SourceIs32bit:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /TimeZone:7.00 /MftRecordSize:1024 /TSFormat:2 /TSPrecision:None /SourceIs32bit:1 /SkipSqlite3:1 LogFileParser.exe /LogFileFile:c:\temp$LogFile /OutputPath:E:\LFP-Output LogFileParser.exe /LogFileFile:c:\temp$LogFile /MftCsvFile:c:\temp$MFT LogFileParser.exe /LogFileFragmentFile:c:\temp\fragment.bin /OutputPath:E:\LFP-Output LogFileParser.exe /LogFileFragmentFile:c:\temp\fragment.bin /OutputPath:E:\LFP-Output /VerifyFragment:1 LogFileParser.exe /LogFileFragmentFile:c:\temp\fragment.bin /OutputPath:E:\LFP-Output /VerifyFragment:1 /OutFragmentName:FragmentsRCRDCollection.bin LogFileParser.exe /LogFileFile:E:\LFP-Output\FragmentsRCRDCollection.bin /OutputPath:E:\LFP-Output /SkipFixups:1 /BrokenLogFile:1

Le dernier exemple est un exemple de base qui utilise des valeurs par défaut courantes qui fonctionnent très bien dans de nombreux cas. Également compatible avec les imports MySql.

Références : Windows Internals 6th Edition http://www.opensource.apple.com/source/ntfs/ntfs-80/kext/ntfs_logfile.h https://dl.dropbox.com/s/c0u980a53ipaq7h/CEIC-2012_Anti-Anti_Forensics.pptx?dl=1