
Parser per $LogFile su NTFS
Funzionalità Decodifica e dump dei record $LogFile e delle voci di transazione. Decodifica delle modifiche agli attributi NTFS. Risoluzione opzionale di tutte le informazioni della lista datarun disponibili in $LogFile. Opzione: "Reconstruct data runs". Recupero delle transazioni dallo slack space all'interno di $LogFile. Scelta di ricostruire header mancanti o danneggiati delle transazioni trovate nello slack. Opzione: "Rebuild header". Ottimizzazione opzionale del risultato con un valore di livello di errore LSN. Opzione: "LSN error level". Log su csv e importazione in database sqlite con diverse tabelle. Importazione opzionale dell'output csv di mft2csv nel db. Scelta tra 6 diversi formati di timestamp. Scelta della precisione del timestamp: None, MilliSec e NanoSec. Scelta del separatore di precisione a millisec. Scelta del separatore di precisione a nanosec. Scelta della regolazione del fuso orario per i timestamp. Il default è presentare i timestamp in UTC 0.0. Scelta del separatore di output. Opzione: "Set separator". Output configurabile UNICODE o ANSI. Opzione "Unicode". Dimensione del record MFT configurabile (1024 o 4096). Opzione "MFT record size". Decodifica opzionale di singole transazioni o transazioni parziali (frammenti). Opzione per ricostruire RCRD da singole o multiple transazioni (frammenti). Opzione per configurare $LogFile danneggiato. Utile con RCRD carved come input. Opzione per saltare i fixup (per $LogFile danneggiato, tipicamente carved dalla memoria). Output dettagliato verboso in debug.log. Lista configurabile separata da virgole di lsn per attivare informazioni ultra verbose su transazioni specifiche in debug.log. Configurazione per OS a 32-bit. Configurazione per l'estrazione di dati binari degli aggiornamenti di dati residenti. Sql autogenerato per importare l'output in un database MySql. Opzione per saltare tutto il codice sqlite3 per velocizzare il parsing totale. Modalità opzionale da riga di comando. Supporta errorlevel adatto per scripting batch.
Background NTFS è progettato come filesystem recuperabile. Questo avviene tramite il logging di tutte le transazioni che alterano la struttura del volume. Quindi qualsiasi modifica a un file sul volume richiederà che qualcosa venga registrato anche nel $LogFile, in modo che possa essere annullato in caso di guasto del sistema in qualsiasi momento. Pertanto molte informazioni vengono scritte in questo file, e poiché è circolare, significa che le nuove transazioni sovrascrivono i record più vecchi nel file. Quindi è alquanto limitato quanto dato storico può essere recuperato da questo file. Anche in questo caso, dipenderebbe dal tipo di volume e dalla dimensione del $LogFile. Sul systemdrive di un sistema usato frequentemente, probabilmente otterrai solo poche ore di storico, mentre un disco esterno/secondario con file di backup probabilmente conterrà più informazioni storiche. E un file da 2MB conterrà molto meno storico di uno da 256MB. Quindi in quale intervallo di dimensioni può essere configurato questo file? Da 256 KB in su. Configurare la dimensione a 2 GB può essere fatto così, "chkdsk D: /L:2097152". Come un logfile di grandi dimensioni impatti sulle prestazioni è al di fuori dello scopo di questo testo. Impostarlo a meno di 2048 normalmente non è possibile. Tuttavia è possibile patchando untfs.dll: http://code.google.com/p/mft2csv/wiki/Tiny_NTFS
Intro Questo parser decodificherà ed eseguirà il dump di molte informazioni sulle transazioni dal $LogFile su NTFS. Vengono generati diversi csv oltre a un database sqlite chiamato ntfs.db contenente tutte le informazioni rilevanti. L'output è estremamente dettagliato e di basso livello, il che significa che richiede una discreta conoscenza di NTFS per essere compreso. I tipi di transazione Redo attualmente gestiti con output decodificato significativo sono:
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 lista degli attributi attualmente supportati: $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
Quindi in pratica tutti gli attributi sono supportati.
Spiegazione dei diversi output generati:
LogFile.csv: Il csv principale generato dal parser.
LogFile_DataRuns.csv Le informazioni di input necessarie per ricostruire i datarun
LogFile_DataRunsResolved.csv L'output finale dei datarun ricostruiti
LogFile_INDX_I30.csv Tutti i record di indice (IndexRoot/IndexAllocation) di cui è stato eseguito il dump e la decodifica
LogFileJoined.csv Come LogFile.csv, ma con le informazioni sul nome file unite dal $UsnJrnl o dal csv di mft2csv.
MFTRecords.bin $MFT fittizio ricreato in base ai record MFT trovati nelle transazioni InitializeFileRecordSegment. È possibile usare mft2csv su questo (ricordarsi di configurare correttamente "broken MFT" e "Fixups").
LogFile_lfUsnJrnl.csv Record per il $UsnJrnl che è stato decodificato all'interno di $LogFile
LogFile_UndoWipe_INDX_I30.csv Tutte le operazioni di undo per la cancellazione degli indici di directory (INDX).
LogFile_AllTransactionHeaders.csv Tutti gli header delle transazioni decodificate.
LogFile_BitsInNonresidentBitMap.csv Tutte le operazioni SetBitsInNonresidentBitMap decodificate.
LogFile_DirtyPageTable32bit.csv e LogFile_DirtyPageTable64bit.csv Tutte le voci in ogni operazione DirtyPageTableDump decodificata sia per OS a 32bit che a 64bit.
LogFile_Mft_ObjectId_Entries.csv Attributi $ObjectId decodificati.
LogFile_ObjIdO.csv Tutte le decodifiche dal file di sistema $ObjId:$O.
LogFile_OpenAttributeTable.csv Tutte le voci in ogni operazione OpenAttributeTableDump decodificata.
LogFile_QuotaO.csv Tutte le decodifiche dal file di sistema $Quota:$O.
LogFile_QuotaQ.csv Tutte le decodifiche dal file di sistema $Quota:$Q.
LogFile_RCRD.csv Tutti gli header dei record RCRD decodificati.
LogFile_ReparseR.csv Tutte le decodifiche dal file di sistema $Reparse:$R.
LogFile_SecureSDH.csv Tutte le decodifiche dal file di sistema $Secure:$SDH.
LogFile_SecureSII.csv Tutte le decodifiche dal file di sistema $Secure:$SII.
LogFile_SecurityDescriptors.csv Security descriptor decodificati. La fonte può essere da $SECURITY_DESCRIPTOR o $Secure:$SDS.
LogFile_SlackAttributeNamesDump.csv Tutte le voci dalle transazioni AttributeNamesDump decodificate trovate nello slack space.
LogFile_SlackOpenAttributeTable.csv Tutte le voci dalle transazioni OpenAttributeTableDump decodificate trovate nello slack space.
LogFile_TransactionTable.csv Transazioni TransactionTableDump decodificate.
LogFile_Filenames.csv Tutti i nomi file risolti con MftRef, MftRefSeqNo e Lsn.
LogFile_TxfData.csv Dati decodificati da $DATA:$TXF_DATA in $LOGGED_UTILITY_STREAM.
LogFile_UpdateFileName_I30.csv Tutte le decodifiche di UpdateFileNameRoot e UpdateFileNameAllocation sia per operazioni redo che undo.
LogFile_CompensationlogRecord.csv Tutte le decodifiche di CompensationlogRecord. Non rilevante per nt5.x.
Ntfs.db Un file di database sqlite con tabelle quasi equivalenti ai csv sopra. Il database contiene 5 tabelle: DataRuns IndexEntries LogFile LogFileTmp (tabella temporanea usata durante la ricreazione dei datarun). UsnJrnl
Timestamp I default sono presentati in UTC 0.00, e con precisione al nanosecondo. Il formato predefinito è YYYY-MM-DD HH:MM:SS:MSMSMS:NSNSNSNS. Questi possono essere configurati. I diversi timestamp si riferiscono a: CTime significa File Create Time. ATime significa File Modified Time. MTime significa MFT Entry modified Time. RTime significa File Last Access Time.
Ricostruzione dei datarun.
Molte operazioni sul filesystem attiveranno una transazione nel $LogFile. Quelle relative all'attributo $DATA, cioè il contenuto di un file, sono finora identificate come;
InitializeFileRecordSegment CreateAttribute UpdateMappingPairs SetNewAttributeSizes
Lasciano tutte informazioni diverse nel $LogFile. Le modifiche ai dati residenti si comportano diversamente e non possono essere ricostruite così semplicemente, almeno su volumi NTFS provenienti da versioni moderne di Windows.
InitializeFileRecordSegment è quando viene creato un nuovo file. Quindi avrà l'attributo $FILE_NAME, così come il contenuto originale dell'attributo $DATA, inclusi i datarun. Poiché il $LogFile è circolare, e gli eventi più vecchi vengono sovrascritti da quelli più nuovi, la sfida con il $LogFile è ottenere informazioni sufficientemente indietro nel tempo. Tuttavia, se InitializeFileRecordSegment è presente, allora dovremmo essere in grado di ricostruire tutto, poiché anche tutti i record scritti dopo di esso saranno disponibili. Avremo anche informazioni sull'offset alla lista datarun. Questo è un offset relativo calcolato dall'inizio dell'attributo $DATA. Questa è un'informazione importante da avere quando si calcola dove nella lista datarun UpdateMappingPairs ha effettuato la sua modifica.
CreateAttribute è l'attributo originale quando è stato creato per la prima volta (se non scritto come parte di InitializeFileRecordSegment). Anche con questo, dovremmo essere in grado di ricostruire i datarun poiché abbiamo tutte le transazioni disponibili. Tuttavia, questo di per sé non ci fornirà il nome del file. Anche qui, abbiamo l'offset alla lista datarun disponibile che è estremamente utile quando si risolve UpdateMappingPairs.
UpdateMappingPairs è una transazione quando vengono eseguite modifiche al $DATA/datarun (il contenuto del file è cambiato). Le informazioni trovate in questa transazione non sono complete, e contengono solo i nuovi valori aggiunti alla lista datarun esistente. Contiene anche un offset relativo che ci dice dove nella lista datarun sono state scritte le modifiche. Questo offset è usato in combinazione con l'offset al datarun come trovato in InitializeFileRecordSegment e CreateAttribute.
SetNewAttributeSizes è una transazione che contiene informazioni su qualsiasi modifica relativa ai valori di dimensione fatta all'attributo $DATA. Questo è strettamente connesso a UpdateMappingPairs che contiene solo modifiche ai datarun.
Con le 4 diverse operazioni redo sopra, per un dato numero di riferimento (file distinto) è possibile ricostruire parte della storia delle modifiche del filesystem di un file. A causa della circolarità, abbiamo solo parte della storia, la più recente. L'estensione della storia che possiamo recuperare dipende fortemente dal tipo di volume di destinazione. Se è un volume di sistema, allora una settimana di storico è probabilmente più di quanto ci si possa aspettare, mentre un disco rimovibile o esterno o secondario conterrà molto più storico. Quindi potremmo ricostruire la storia completa di un file cancellato (con il suo record $MFT sovrascritto), e a sua volta ricreare la lista datarun su cui eseguire il recupero. In altri casi potremmo non essere in grado di ricostruire la storia completa, quindi può essere ricostruita solo una lista datarun parziale. Il file csv finale con i datarun modificati, LogFile_DatarunsModified.csv, avrà i datarun visualizzati diversamente.
Spiegazione: Quelli che iniziano con un "!" indicano che la lista datarun completa è stata ricreata. Quelli che iniziano con un "?" indicano un recupero parziale, con il numero di "**" che rappresenta i byte mancanti dalla lista datarun originale.
Per semplificare il recupero di un file basato su un datarun, si può usare il PoC allegato chiamato ExtractFromDataRuns. È abbastanza autoesplicativo. Basta inserire la lista datarun completa, la dimensione reale e la dimensione iniziale, e un nome per il file di output. Opzionalmente scegliere di elaborare file immagine (disco o partizione). Spuntare anche se è stato rilevato un flag compressed/sparse. Alimentarlo con una lista datarun parzialmente ricostruita non funzionerà! Si noti che gli alternate data stream possono essere distinti dalla presenza di un dataname e anche da valori OffsetInMft diversi per un dato fileref.
Il pacchetto di download separato "SampleTinyNtfsVolume.zip" contiene un'immagine di partizione con un piccolo volume NTFS su cui testarlo. Sul volume ci sono 2 file non-resident cancellati che hanno entrambi il record MFT sovrascritto da nuovi file. Qualsiasi software di recupero decente basato sulla ricerca di firme dovrebbe essere in grado di recuperare il file jpg (Tulips.jpg), perché è contiguo. Tuttavia, molto probabilmente non identificheranno il suo nome file, o altro sul file. Il secondo file probabilmente non sarà recuperabile usando strumenti standard, perché è frammentato (compresso), e avendo il suo record MFT sovrascritto, risolvere il file senza la lista datarun è impossibile. Usando il PoC possiamo identificare il nome file (suspicious.zip) ed estrarlo in perfetta forma (non preoccuparti, contiene solo una delle immagini di esempio fornite con Windows). Leggi il file readme.DataRunsResolved.txt per i dettagli sull'immagine di esempio e su come interpretare l'output e recuperare i file.
Ciò che abbiamo ottenuto con questo è recuperare file frammentati che hanno il loro record MFT sovrascritto. Poiché abbiamo ricostruito la storia parziale/completa dei datarun, possiamo con certezza (almeno se la storia completa è ricostruita) determinare se i dati di file slack sono appartenuti al dato file o no.
Limitazione. La ricostruzione dei datarun è rotta con UNICODE (ANSI va bene). L'importazione dell'output di Mft2Csv è rotta se il csv è UNICODE (ANSI va bene). Gli aggiornamenti parziali agli IndexRecords (IndexRoot/IndexAllocation) sono molto difficili da interpretare, poiché probabilmente non abbiamo conoscenza dell'indice originale. I record completi vanno bene però. La circolarità di un file da 65 MB pone una restrizione intrinseca e assoluta su quante transazioni storiche del FS. I systemdrive quindi hanno storico limitato in $LogFile, mentre i dischi esterni/secondari hanno più transazioni storiche memorizzate. È possibile aumentare la dimensione di $LogFile con chkdsk (chkdsk c: /L:262144). Le modifiche ai dati dei file residenti non sono memorizzate all'interno di $LogFile, viene memorizzata solo l'informazione che è stata fatta una modifica.
Nota Il $UsnJrnl contiene informazioni in modo più user-friendly. Per esempio ogni record contiene fileref, nome file, timestamp e spiegazione di ciò che è avvenuto. Contiene anche molte più informazioni storiche del $LogFile, sebbene senza molti dettagli. Se $UsnJrnl è attivo, allora tutte le transazioni scritte in esso durante il ciclo di vita del riciclo del $LogFile sono anche presenti all'interno di $LogFile. Questo significa che non c'è motivo di decodificare il $UsnJrnl per comprendere meglio il $LogFile.
Slack space In questo contesto slack space significa lo spazio all'interno di un record RCRD che è il rimanente nel record oltre l'ultima transazione. Non credo che questo sia stato descritto prima, quindi lasciami spiegare. Il volume slack è lo spazio inutilizzato tra la fine del filesystem e la fine della partizione dove risiede il filesystem. Lo slack del record MFT è più o meno lo stesso, ma si riferisce allo spazio trovato dopo la firma di fine record (0xFFFFFFFF) fino alla fine fisica del record (0x400 o 0x1000). E lo slack space all'interno del $LogFile è quindi lo spazio trovato oltre l'ultima transazione e fino alla fine del record RCRD (di solito 0x1000). Queste transazioni dallo slack sono in realtà lì da prima che il $LogFile fosse riciclato (sovrascritto). C'è anche un algoritmo che identifica transazioni valide dallo slack space. Inoltre possono esistere anche diversi strati di tale slack space. Esempio: Diciamo che l'ultima transazione in un dato record RCRD è terminata all'offset 0x00007D27. Da questo offset fino a 0x00007FFF abbiamo 0x2D8 byte di slack space. Potrebbe quindi essere che i byte che iniziano a 0x00007D28 non siano un header di transazione valido perché è nel mezzo di una transazione. Il programma allora (se configurato per farlo) tenterà di ricostruire un pseudo header con valori validi per decodificare la transazione. Se fallisce nel ricostruire qualsiasi header valido, considera che troppe informazioni dall'header originale sono perse, e considererà questi byte come persi, e continuerà a scansionare il resto dello slack space per qualsiasi header di transazione valido. I byte persi saranno registrati in debug.log per la tua analisi. D'altra parte, se è stato in grado di ricostruire un header valido, le informazioni su questo si troveranno nel campo lf_TextInformation. Diciamo che ha identificato una transazione che inizia all'offset 0x00007D48 e con dimensione 0xB0. Poi un'altra buona transazione è stata identificata immediatamente dopo all'offset 0x00007DF8 con dimensione 0xE0. Tuttavia all'offset 0x00007ED8 non c'era alcun header di transazione valido. Questo significa che siamo ora al secondo strato di slack space all'interno di quel record RCRD. Ora diciamo che il programma, dopo aver ri-scansionato, è stato in grado di identificare un header di transazione valido all'offset 0x00007F18. Questa transazione sarebbe contrassegnata nel csv con un valore di 2 nel campo FromRcrdSlack. Tuttavia, considera la dimensione totale della transazione che spinge l'offset oltre la dimensione del record RCRD. In sostanza, questa sarebbe una transazione parzialmente recuperata, che potrebbe decodificare bene, ma sarà trovata con un valore di 1 nel campo IncompleteTransaction. Ricorda che debug.log è molto dettagliato e aiuterà a comprendere l'output decodificato, specialmente ciò che proviene dallo slack space.
Configurazione 32-bit vs 64-bit. Questa impostazione è importante da impostare correttamente. Significa quale OS ha gestito il volume di destinazione. Il punto è che la gestione di OpenAttributeTable differisce da OS a 32-bit a 64-bit. Ci possono essere naturalmente casi (per esempio disco usb) dove il volume è stato gestito da diversi OS, nel qual caso potrebbe essere complicato ottenere questa impostazione corretta al 100%. Dalla versione 2.0.0.8 è stato implementato un meccanismo di autodetect. Tuttavia è ancora raccomandato tentare di impostare correttamente questa configurazione. Nel campo TextEinformation verrà stampato un messaggio "Mixed OS detected" quando rileva un formato OpenAttributeTableDump che differisce dalla configurazione o quando vengono rilevati entrambi i tipi. In ogni caso, potrebbe essere utile esaminare LogFile_OpenAttributeTable.csv per valutare l'output. Se vedi voci con colonne contenenti valori strani, allora questa particolare impostazione potrebbe essere sbagliata. Se è così, allora la maggior parte dei valori sono molto sbagliati. Per esempio la maggior parte dei campi AttributeType sono UNKNOWN, Lsn non è all'interno dell'intervallo corrente, MftRef è troppo alto e MftRefSeqNo è 0. Attenzione che AttributeType viene risolto come UNKNOWN per le voci non inizializzate nella tabella, ma queste sono facili da individuare poiché tutti i valori dopo AllocatedOrNextFree sono 0 ed è perfettamente valido. Queste sfide sembrano risolte con l'autodetect implementato nella versione 2.0.0.8.Estrazione degli aggiornamenti degli attributi residenti (UpdateResidentValue). L'operazione UpdateResidentValue serve per gli aggiornamenti al contenuto degli attributi residenti. La configurazione "Extract resident updates of min size" consente di estrarre la modifica binaria dell'attributo residente. Il campo di input indica la dimensione minima in byte da estrarre. L'uso probabilmente più interessante di questa funzionalità è con i volumi gestiti da Nt5.x (XP, 2003), dove gli aggiornamenti completi dell'attributo $DATA (normale contenuto del file) sono memorizzati nei campi redo e undo con UpdateResidentValue. I file con contenuto $DATA residente sono file di dimensioni ridotte, al massimo 744 byte (con dimensione del record MFT di 1024) ma di solito meno. I dati estratti vengono scritti in una sottocartella denominata ResidentExtract. I file di output sono denominati con una logica di questo tipo: MFT($MFTRef)$OffsetInMft$AttributeOffset_LSN($Lsn)$Operation.bin. Ad esempio MFT(1643)_0x0098_0x00B8_LSN(1415242628)redo.bin significherebbe record MFT numero 1643, l'offset dell'attributo di destinazione nell'MFT è 0x98, l'offset della modifica all'interno dell'attributo di destinazione è 0xB8, l'LSN della transazione è 1415242628, e questa era un'operazione redo. Le estrazioni per le operazioni undo contengono quindi i dati presenti a quell'offset prima della modifica. L'attivazione di questa funzionalità genererà alcuni output irrilevanti e non interessanti. La maggior parte dei falsi positivi viene filtrata automaticamente, ma alcuni sono inevitabili. Ad esempio, possono essere inclusi aggiornamenti di $INDEX_ROOT, $ATTRIBUTE_LIST e $BITMAP. È comunque possibile risalire manualmente agli attributi per filtrare quelli non-$DATA confrontando l'OffsetInMft con quanto trovato nel relativo InitializeFileRecordSegment o, se applicabile, nell'$MFT stesso. Dalla versione 2.0.0.13 è stata aggiunta l'estrazione di $EA. Vedere la nota sugli attributi $EA.
Filenames csv Dalla versione 2.0.0.6 è stata implementata una nuova funzionalità per esportare tutti i nomi di file identificati. La fonte di queste voci proviene da InitializeFileRecordSegment, UpdateNonResidentValue, AddindexEntryRoot, DeleteindexEntryRoot, AddIndexEntryAllocation, DeleteIndexEntryAllocation e WriteEndOfIndexBuffer. Il csv con questi nomi di file, LogFile_FileNames.csv, contiene quindi una storia ricostruita di tutti i filename, MftRef e MftRefSeqNo per la durata della storia del $LogFile. Sarà quindi possibile vedere tutti i vari nomi di file che un dato record MFT ha avuto durante l'intervallo di tempo coperto dal $LogFile. Quando un file viene rinominato, il MftrefSeqNo non viene incrementato. Quando un record MFT viene contrassegnato come eliminato e successivamente riutilizzato, il MftRefSeqNo viene incrementato di uno con la nuova inizializzazione.
$TXF_DATA Con Transactional NTFS (TxF), si verificheranno occorrenze dello stream denominato $TXF_DATA nell'attributo $LOGGED_UTILITY_STREAM. È sempre residente, e possono essercene diversi per file. L'uso non è diffuso, e Microsoft incoraggia effettivamente metodi alternativi. [quote]Microsoft raccomanda vivamente agli sviluppatori di utilizzare mezzi alternativi per soddisfare le esigenze delle proprie applicazioni.[/quote]. Sembra che solo pochi meccanismi di aggiornamento software lo utilizzino. Ogni file/cartella creato con esso ottiene un fileref univoco (da non confondere con i numeri di record MFT). Questo fileref univoco è il nome che il file avrà quando verrà eliminato successivamente (e spostato nella cartella $Extend$RmMetadata$Txf). L'attributo $DATA standard senza nome del file $Tops contiene informazioni su dove nel $TxfLogContainer00000000000000000001 andrà la prossima transazione. Lo stream $DATA denominato $T del $Tops contiene i dati effettivi (dalle operazioni sui file transazionali) che vengono riciclati. All'interno di $TXF_DATA c'è anche un campo chiamato LsnUserData che è un offset nel $TxfLogContainer00000000000000000001 dove si trovano molti più dettagli sulla transazione. Anche LsnNtfsMetadata contiene un offset nello stesso file $TxfLogContainer00000000000000000001. Si noti che questi offset possono essere modificati in una fase successiva, e vengono quindi referenziati in un'operazione UpdateResidentValue nel $LogFile. Il campo MftRef_RM_Root è il numero di record del file della radice del resource manager responsabile della transazione associata a questo file (il valore predefinito è 5, che è la directory radice). Per gli aggiornamenti a $TXF_DATA tramite UpdateResidentValue, il testo "Partial update" viene aggiunto nel campo TextInformation. Per questo motivo, possono esistere anche valori come 0x0000000000007E-- in LsnUserData. Questo perché un UpdateResidentValue di dimensione 31 byte significa che mancano i primi 3 membri della struttura completa, e manca anche 1 byte da LsnUserData. Il byte mancante è il "byte basso", quindi 2 caratteri/nibble di "-" ciascuno, come sostituzione per indicare il byte sconosciuto mancante (in realtà solo il byte esistente). Se UpdateResidentValue fosse a 32 byte, allora non sarebbero necessari caratteri/nibble di sostituzione poiché l'intero LsnUserData sarebbe stato fornito.
debug.log In questo log vengono scritti messaggi di errore e informazioni verbose. Se vengono trovati valori o commenti strani nell'output, cercare l'lsn in debug.log. Di solito viene scaricata l'intera transazione, il che potrebbe aiutare a comprendere. Per facilitare le indagini sulle transazioni, potrebbe essere utile inserire una lista separata da virgole di lsn nel campo di input. Verranno quindi stampate informazioni verbose per questi lsn.
$EA L'attributo $EA è un insieme di coppie nome-valore e si ritiene che sia presente per compatibilità con OS/2. È raramente visto in uso, sebbene alcuni malware lo abbiano utilizzato. Possono esserci diverse coppie per attributo, ma la dimensione massima di tutte è 65535 byte. Può esserci solo 1 attributo $EA per file. Contenuti più grandi possono essere distribuiti su più file come mostrato nel PoC EaTools; https://github.com/jschicht/EaTools Gli attributi $EA esistenti non possono essere modificati direttamente. Coppie nome/valore aggiuntive possono essere aggiunte in qualsiasi momento purché la dimensione di tutte le coppie sia inferiore a 0xFFFF byte. Il comportamento strano di questo attributo è che tutto il contenuto dell'intero $EA viene scritto nel $LogFile per ogni nuova coppia. Questo vale sia per il contenuto $EA residente che non residente. Ciò significa che se viene aggiunta una terza coppia nome/valore a un $EA, tutte e 3 le coppie vengono scritte nel $LogFile tramite UpdateResidentValue o UpdateNonResidentValue.
Todo Implementare ulteriori analisi dei dati presenti in ntfs.db. Attualmente richiederà un certo livello di conoscenza di NTFS per comprendere l'output. Esportare il contenuto $EA non residente.
Uso da riga di comando Se non vengono forniti parametri, la GUI si avvierà per impostazione predefinita. Gli switch validi sono:
Switch: /LogFileFile: Input $LogFile estratto. Obbligatorio a meno che non venga utilizzato /LogFileFragmentFile:. /LogFileFragmentFile: Opzionalmente input di un frammento di $LogFile. Può essere qualsiasi frammento rotto con almeno 1 transazione. /MftCsvFile: Il csv di output dell'ultimo Mft2Csv. Opzionale. /OutputPath: Il percorso di output di tutto l'output del parser. Predefinito alla directory del programma. /TimeZone: Un valore stringa per il fuso orario. Vedere le note più avanti per i valori validi. /OutputFormat: Il formato di output del csv. I valori validi possono essere l2t, BodyFile, all. /BrokenMft: Valore booleano per la gestione di MFT con formato errato. Il valore predefinito è 0. Può essere 0 o 1. /SkipFixups: Valore booleano per saltare i fixup. Utilizzato principalmente con i dump di memoria. Il valore predefinito è 0. Può essere 0 o 1. /Separator: Il separatore da usare nel csv. Il valore predefinito è | /Unicode: Valore booleano per la decodifica delle stringhe unicode. Il valore predefinito è 0. Può essere 0 o 1. /TSFormat: Un intero da 1 a 6 per specificare il formato del timestamp. Avviare la gui per vedere cosa significano. Il valore predefinito è 6. /TSPrecision: Quale precisione usare nel timestamp. I valori validi sono None, MilliSec e NanoSec. Il valore predefinito è NanoSec. /TSPrecisionSeparator: Il separatore da inserire nella separazione della precisione. Il valore predefinito è ".". Avviare la gui per vedere cosa significa. /TSPrecisionSeparator2: Il separatore da inserire tra MilliSec e NanoSec nella precisione del timestamp. Il valore predefinito è vuoto/nulla. Avviare la gui per vedere cosa significa. /TSErrorVal: Un valore di errore personalizzato da inserire con gli errori nella decodifica del timestamp. Il valore predefinito è '0000-00-00 00:00:00', che è compatibile con MySql, e rappresenta un valore di timestamp non valido per NTFS. /ReconstructDataruns: Valore booleano per specificare se deve essere eseguita la ricostruzione dei datarun. Il valore predefinito è 0. Può essere 0 o 1. /MftRecordSize: La dimensione dei record MFT. I valori validi sono 1024 e 4096. Il valore predefinito è 1024. /RebuildHeadersSlack: Valore booleano per specificare se tentare di ricostruire l'header da transazioni rotte recuperate dallo slack. Il valore predefinito è 0. Può essere 0 o 1. /SectorsPerCluster: Numero di settori per cluster. Il valore predefinito è 8. Può essere 1,2,4,8,16,32,64 e 128. /LsnErrorLevel: Un valore tra 0 e 1 (100%), come soglia per identificare transazioni valide/non valide dallo slack, in base all'lsn precedente. Il valore predefinito è 0.1 (10%). /SourceIs32bit: Valore booleano per specificare se il volume proviene da un sistema a 32 bit. Il valore predefinito è 0 (x64). Può essere 0 o 1. /ExtractDataUpdates: Valore booleano per specificare se deve essere eseguita l'estrazione del contenuto dei dati residenti. Il valore predefinito è 0. Può essere 0 o 1. /ExtractDataUpdatesSize: Valore per impostare la dimensione minima in byte per ciò che deve essere estratto. Utilizzato solo con l'impostazione ExtractDataUpdates. Il valore predefinito è 2 (byte) come minimo. /VerboseLsnList: Una lista separata da virgole di lsn che attiverà la modalità verbose. Le informazioni di logging verbose si trovano in debug.log. /SkipSqlite3: Valore booleano per specificare se il parser deve omettere tutte le operazioni sqlite3. Se il ntfs.db generato (ricostruzione dei datarun, importazione del csv mft) non viene utilizzato, questo può essere tranquillamente ignorato/omesso. Il valore predefinito è 0. Può essere 0 o 1. /VerifyFragment: Valore booleano per attivare una semplice validazione solo su un frammento, e non sull'intero parser. Può essere 0 o 1. Per impostazione predefinita scriverà il frammento corretto in OutFragment.bin a meno che non sia specificato diversamente in /OutFragmentName: /OutFragmentName: Il nome del file di output in cui scrivere il frammento corretto, se /VerifyFragment: è impostato a 1. Se omesso, il nome file predefinito è OutFragment.bin. /SkipFixups: Valore booleano per saltare i fixup. Utilizzato con frammenti ricostruiti. Vedere gli esempi. Il valore predefinito è 0. Può essere 0 o 1. /BrokenLogFile: Valore booleano per trattare il $LogFile come rotto. Utilizzato con RCRD ricostruiti e bypasserà diversi controlli di validazione. Il valore predefinito è 0. Può essere 0 o 1.
I TimeZone disponibili da utilizzare sono: -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
Livelli di errore Gli attuali codici di uscita (errore) sono stati implementati in modalità riga di comando, il che lo rende più adatto per lo scripting batch.
Quindi se si ottiene %ERRORLEVEL% == 1 significa che nulla è stato decodificato, e se si ottiene %ERRORLEVEL% == 2 allora molto probabilmente il parametro SectorsPerCluster è stato impostato in modo errato.
Esempi: 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
L'ultimo esempio è un esempio di base che utilizza valori predefiniti comuni che funzionano bene in molti casi. Compatibile anche con le importazioni MySql.
Riferimenti: 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