Analisi della sequenza temporale · Lezione 1 di 5
Formati dei timestamp: FILETIME, Unix, Apple e DOS
12 min di lettura
Un timestamp è soltanto un numero finché non se ne conoscono quattro caratteristiche: la sua epoca (l'istante da cui inizia il conteggio), la sua unità, la sua dimensione e l'ordine dei byte, e se registra l'ora UTC o l'ora locale. Sbagliare anche una sola di queste caratteristiche trasforma un valore corretto in una risposta errata, talvolta con uno scarto di decenni e talvolta di poche ore, più difficile da notare. Nei moduli precedenti sono stati decodificati singoli timestamp man mano che si presentavano. Questa lezione riunisce i formati in un unico riferimento, mostra come riconoscere un formato da un valore grezzo e decodifica uno stesso istante in diversi formati. La lezione 3.5 tratta gli errori di fuso orario e dell'orologio; qui ci si limita a indicare se ciascun formato memorizza l'ora UTC o l'ora locale.
Tabella di riferimento
| Formato | Epoca | Unità e dimensione | Ordine dei byte | Fuso orario | Dove si incontra |
|---|---|---|---|---|---|
| FILETIME | 1601-01-01 | 100 ns, 64 bit senza segno | Little-endian | UTC | NTFS, registro, EVTX, Prefetch, LNK |
| Tempo Chrome/WebKit | 1601-01-01 | microsecondi, intero a 64 bit | Intero SQLite | UTC | Browser basati su Chromium (modulo 4) |
| Tempo Unix | 1970-01-01 | secondi, 32 o 64 bit | Little-endian in ext4 e Windows; spesso testo | UTC | ext4, DWORD del registro, intestazioni PE, log |
| Millisecondi / microsecondi Unix | 1970-01-01 | ms o µs, 64 bit | Variabile | UTC | JavaScript, archiviazione dei browser, PRTime di Firefox |
| APFS | 1970-01-01 | nanosecondi, 64 bit senza segno | Little-endian | UTC | Inode APFS |
| Mac Absolute Time | 2001-01-01 | secondi, spesso un double a 64 bit | Big-endian nei plist binari | UTC | plist, database SQLite di Apple |
| HFS+ | 1904-01-01 | secondi, 32 bit senza segno | Big-endian | UTC (vedere sotto) | Catalogo HFS+, immagini disco meno recenti |
| Data OLE Automation | 1899-12-30 | giorni, double a 64 bit | Little-endian | Dipende dal programma che scrive il valore | Database ESE come SRUM, Office |
| Data/ora DOS | 1980-01-01 | 2 s, due word a 16 bit | Little-endian | Locale (UTC negli elementi della shell) | FAT, exFAT, ZIP, elementi della shell |
| SYSTEMTIME | nessuna (campi) | 8 × WORD a 16 bit, 16 byte | Little-endian | Dipende dal programma che scrive il valore | Profili NetworkList, file .job legacy |
| ISO 8601 / RFC 3339 | nessuna (testo) | testo, precisione arbitraria | n/d | Indicato nella stringa, se presente | Log, XML, JSON, XML degli eventi |
Formati Windows
FILETIME è un conteggio a 64 bit di intervalli di 100 nanosecondi a partire da 1601-01-01T00:00:00Z. La struttura contiene due metà a 32 bit (dwLowDateTime, poi dwHighDateTime), quindi su disco gli otto byte sono in ordine little-endian e devono essere invertiti prima della lettura. Per decodificarlo, dividere per 10.000.000 per ottenere i secondi trascorsi dal 1601, quindi sottrarre 11.644.473.600, il numero di secondi dal 1601 al 1970, per ottenere il tempo Unix. Alcuni artefatti memorizzano FILETIME come testo: il valore MRU di Office [T01DCB128E569DA00] (lezione 2.4) è già nell'ordine di lettura e non deve essere invertito.
SYSTEMTIME è una struttura di 16 byte composta da otto WORD little-endian: wYear, wMonth, wDayOfWeek (0 = domenica), wDay, wHour, wMinute, wSecond, wMilliseconds. Non ha un'epoca, quindi i campi si leggono direttamente. L'uso dell'ora UTC o locale dipende dal programma che ha scritto il valore. I valori DateCreated e DateLastConnected dei profili di rete in SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles sono SYSTEMTIME in ora locale. Il campo del giorno della settimana offre un controllo di coerenza immediato: deve corrispondere alla data.
La data OLE Automation (il tipo COM DATE) è un numero in virgola mobile a 64 bit che esprime i giorni trascorsi da 1899-12-30T00:00:00. La parte intera indica il giorno e la parte frazionaria l'ora del giorno, quindi 0,5 corrisponde a mezzogiorno. I database ESE memorizzano in questo modo le colonne di data e ora. Il campo TimeStamp di SRUM (lezione 2.8) ne è un esempio, in UTC, ma altri programmi memorizzano l'ora locale. Per decodificarlo: datetime(1899,12,30) + timedelta(days=v) in Python.
La data/ora DOS codifica una data e un'ora in due word a 16 bit:
| Word | Bit 15–9 / 15–11 | Bit 8–5 / 10–5 | Bit 4–0 |
|---|---|---|---|
| Data | anno − 1980 (7 bit) | mese (4 bit) | giorno (5 bit) |
| Ora | ora (5 bit) | minuto (6 bit) | secondi ÷ 2 (5 bit) |
Quindi data = (anno − 1980) << 9 | mese << 5 | giorno, e ora = ora << 11 | minuto << 5 | secondo ÷ 2. Il campo dell'anno copre l'intervallo dal 1980 al 2107 e l'ora ha una risoluzione di 2 secondi. In una voce di directory FAT, l'ora di scrittura si trova all'offset 0x16 e la data di scrittura a 0x18, quindi la word dell'ora viene prima. L'ora di creazione a 0x0E ha un byte associato a 0x0D che aggiunge unità di 10 millisecondi, mentre la data dell'ultimo accesso a 0x12 non contiene alcuna ora. FAT e le intestazioni ZIP di base memorizzano l'ora locale (i campi aggiuntivi ZIP possono aggiungere tempi Unix in UTC). exFAT usa la stessa disposizione in un campo a 32 bit, ma aggiunge incrementi di 10 ms e un campo per lo scostamento da UTC. Gli elementi della shell di Windows (lezione 2.5) usano la stessa disposizione, ma memorizzano l'ora UTC. La sola disposizione non permette mai di determinare il fuso orario.
Formati basati su Unix
Il tempo Unix conta i secondi trascorsi da 1970-01-01T00:00:00Z, ignorando i secondi intercalari. Un valore a 32 bit con segno termina a 2.147.483.647, che corrisponde a 2038-01-19T03:14:07Z. Si incontra in valori del registro come InstallDate e i tempi di concessione DHCP (lezione 2.2), nel campo TimeDateStamp dell'intestazione PE (sebbene molti file binari moderni, compresa la maggior parte dei binari Windows a partire da Windows 10, vi memorizzino un hash di compilazione riproducibile anziché un'ora) e in innumerevoli log. Le varianti cambiano soltanto l'unità: millisecondi in Date.now() di JavaScript e in molti dati archiviati da browser e app, microsecondi nel PRTime di Firefox (per esempio visit_date in places.sqlite) e nanosecondi in APFS.
ext4 conserva i secondi a 32 bit e li estende con i campi _extra: 2 bit di epoca più 30 bit di nanosecondi (lezione 1.6). APFS memorizza nanosecondi a 64 bit senza segno a partire dal 1970 UTC (lezione 1.7).
Il tempo Chrome/WebKit conta i microsecondi trascorsi da 1601-01-01 UTC, usando l'epoca di FILETIME con un'unità meno fine. Il modulo 4 tratta i database dei browser che lo utilizzano.
Formati Apple
Mac Absolute Time, chiamato anche tempo Cocoa o Core Data, conta i secondi trascorsi da 2001-01-01T00:00:00Z. Tempo Unix = Mac Absolute + 978.307.200. Di solito è un double con una parte frazionaria. Le property list binarie memorizzano le date in questo modo, come double a 64 bit big-endian, mentre i plist XML le mostrano come testo ISO 8601, per esempio <date>2026-03-14T09:21:07Z</date>. Alcuni database Apple più recenti, come il database di Messaggi chat.db, memorizzano invece nanosecondi trascorsi dal 2001.
HFS+ memorizza secondi a 32 bit senza segno big-endian a partire da 1904-01-01; l'intervallo termina a 2040-02-06T06:28:15. Tempo Unix = HFS+ − 2.082.844.800. Le date del catalogo HFS+ sono in UTC, con un'eccezione documentata: la data di creazione nell'intestazione del volume è in ora locale. HFS classico (Mac OS Standard) memorizzava tutte le date in ora locale.
Formati testuali: ISO 8601 e RFC 3339
ISO 8601 rappresenta date e ore come testo, per esempio 2026-03-14T09:21:07Z o 2026-03-14T06:21:07-03:00. RFC 3339 ne è un profilo più restrittivo per i protocolli Internet: una data e un'ora complete con Z o uno scostamento numerico obbligatori. La vista XML del Visualizzatore eventi mostra i FILETIME di EVTX in questo modo, come SystemTime="2026-03-14T09:21:07.2500000Z". Una stringa senza Z e senza scostamento non specifica alcun fuso orario; ISO 8601 la considera ora locale, quindi non va indicata come UTC a meno che sia documentato che il programma che l'ha scritta usa UTC. L'esame CFX richiede risposte in ISO 8601 con Z.
Esempio svolto: un istante, cinque codifiche
Si consideri 2026-03-14T09:21:07Z, su un sistema impostato su UTC−3.
Secondi Unix. Da 1970-01-01 a 2026-03-14 trascorrono 20.526 giorni. 20.526 × 86.400 = 1.773.446.400. Aggiungendo 9 h 21 min 7 s = 33.667 s si ottiene: 1.773.480.067.
FILETIME. (1.773.480.067 + 11.644.473.600) × 10.000.000 = 13.417.953.667 × 10.000.000 = 134.179.536.670.000.000 = 0x01DCB393E3578380. Memorizzato in ordine little-endian: 80 83 57 E3 93 B3 DC 01.
Mac Absolute Time. 1.773.480.067 − 978.307.200 = 795.172.867 (come double, 795.172.867,0).
Microsecondi WebKit. 13.417.953.667 s dal 1601 × 1.000.000 = 13.417.953.667.000.000.
DOS (locale). L'ora locale è 09:21:07 − 3 h = 2026-03-14 06:21:07.
- Data: (2026 − 1980) << 9 | 3 << 5 | 14 = 46 × 512 + 96 + 14 = 23.662 = 0x5C6E, byte
6E 5C. - Ora: 6 << 11 | 21 << 5 | 7 ÷ 2 = 12.288 + 672 + 3 = 12.963 = 0x32A3, byte
A3 32. - In una voce FAT a 0x16, i quattro byte sono
A3 32 6E 5C. La decodifica restituisce 3 × 2 = 06 secondi: 2026-03-14 06:21:06 in ora locale, oppure 09:21:06Z. Il secondo dispari è andato perso: la formula lo tronca, mentre alcuni programmi, incluso Windows quando copia un file su FAT, arrotondano invece al secondo pari successivo (08) (lezione 3.5).
Per confronto, la stessa ora locale in formato SYSTEMTIME è EA 07 03 00 06 00 0E 00 06 00 15 00 07 00 00 00 (2026, marzo, sabato = 6, giorno 14, 06:21:07.000).
Di quale formato si tratta?
L'ordine di grandezza è l'indizio più rapido. Valori per il 2026:
| Valore grezzo intorno a | Cifre | Formato probabile |
|---|---|---|
1,34 × 10^17; i byte terminano con DC 01 o DD 01 | 18 | FILETIME |
| 1,34 × 10^16 | 17 | Microsecondi WebKit |
| 1,77 × 10^18 | 19 | Nanosecondi Unix o APFS |
| 1,77 × 10^15 | 16 | Microsecondi Unix (PRTime) |
| 1,77 × 10^12 | 13 | Millisecondi Unix |
| 1,77–1,80 × 10^9 | 10 | Secondi Unix |
| 7,9–8,2 × 10^8, spesso con una parte frazionaria | 9 | Mac Absolute Time |
| 7,9 × 10^17 | 18 | Nanosecondi Mac Absolute |
| 3,85–3,88 × 10^9 | 10 | Secondi HFS+ |
| 46.023–46.388 con una parte frazionaria | 5 + parte frazionaria | Data OLE Automation |
L'ordine di grandezza restringe la scelta, ma non costituisce una prova. Il valore Mac Absolute 795.172.867 letto come secondi Unix restituisce 1995-03-14T09:21:07Z, una data dall'aspetto perfettamente valido. Confermare sempre con una seconda fonte: la documentazione del campo o il parser, un artefatto correlato che registra lo stesso evento, oppure la plausibilità rispetto alla data di installazione del sistema e al momento dell'acquisizione.
Esercizio. Identificare e decodificare ciascun valore: (a) byte 80 B6 F9 4D 6B E7 DC 01; (b) 1.779.180.097; (c) 800.872.897,0 in un plist; (d) 13.423.653.697.000.000 in una colonna SQLite; (e) byte FAT32 a 0x16 32 2D B3 5C, sistema impostato su UTC−3.
Soluzione. (a) FILETIME 0x01DCE76B4DF9B680 = 134.236.536.970.000.000; ÷ 10^7 − 11.644.473.600 = 1.779.180.097 = 2026-05-19T08:41:37Z. (b) Secondi Unix, lo stesso istante. (c) Mac Absolute: + 978.307.200 = 1.779.180.097, ancora lo stesso istante; letto come Unix restituirebbe erroneamente 1995-05-19. (d) WebKit: ÷ 10^6 = 13.423.653.697 s dal 1601, meno 11.644.473.600 = 1.779.180.097. (e) Ora 0x2D32: ora 5, minuto 41, 18 × 2 = 36 s; data 0x5CB3: 1980 + 46 = 2026, mese 5, giorno 19. L'ora locale 2026-05-19 05:41:36 corrisponde a 08:41:36Z, ancora una volta con una risoluzione di due secondi. Cinque fonti che concordano entro due secondi costituiscono esattamente il riscontro su cui si basa la lezione 3.4.
Precisione e accuratezza
La precisione è il più piccolo intervallo che un formato può rappresentare: 100 ns per FILETIME, 1 ns per APFS, 2 s per le ore di scrittura DOS, poco meno di un microsecondo per una data OLE nel 2026. L'accuratezza indica quanto il valore memorizzato sia vicino all'istante reale e dipende dall'orologio di sistema e dal programma che lo ha scritto. Molti FILETIME terminano con sette zeri perché il programma disponeva soltanto di secondi interi. Riportare la precisione effettiva della fonte e, quando un'attività richiede i secondi, troncare anziché arrotondare. Un FILETIME da 100 ns non è più affidabile di un'ora DOS da 2 secondi se l'orologio era errato.
Strumenti di decodifica
Gli strumenti sono ausili, non autorità. DCode decodifica la maggior parte dei formati sopra elencati da un'unica casella di input. CyberChef offre operazioni come "Da Filetime Windows a timestamp UNIX" e "Da timestamp UNIX". In Python, datetime(1601,1,1,tzinfo=timezone.utc) + timedelta(microseconds=ft//10) decodifica un FILETIME e datetime.fromtimestamp(u, timezone.utc) decodifica i secondi Unix. Senza timezone.utc, fromtimestamp converte implicitamente nel fuso orario locale della macchina di analisi. Verificare ogni strumento usando un valore calcolato manualmente.
Focus sull'esame: Sono previsti valori grezzi, spesso sotto forma di byte esadecimali little-endian, da identificare e convertire in ISO 8601 UTC con Z. Conoscere le costanti 11.644.473.600 e 978.307.200, la disposizione dei bit DOS e la sua risoluzione di 2 secondi, e quali formati memorizzano l'ora locale (DOS, HFS classico) o dipendono dal programma che scrive il valore (SYSTEMTIME, OLE). I distrattori sono spesso il numero corretto decodificato con l'epoca sbagliata.
Punti chiave
- Ogni timestamp richiede quattro informazioni: epoca, unità, dimensione e ordine dei byte, e ora UTC o locale.
- FILETIME e WebKit contano dal 1601 (100 ns e µs); Unix, APFS ed ext4 contano dal 1970; Mac Absolute conta dal 2001; HFS+ dal 1904; le date OLE da 1899-12-30; DOS dal 1980.
- La data/ora DOS è locale, ha una risoluzione di 2 secondi e copre gli anni 1980–2107; SYSTEMTIME e le date OLE sono in ora UTC o locale a seconda del programma che scrive il valore.
- L'ordine di grandezza e il numero di cifre suggeriscono il formato, ma una seconda fonte deve confermarlo.
- La precisione è ciò che il formato può rappresentare; l'accuratezza dipende dall'orologio e dal programma che scrive il valore.