File system · Lezione 1 di 8
Dischi, partizioni e volumi
12 min di lettura
Prima di poter analizzare un file system, un esaminatore deve sapere dove inizia. Questa lezione spiega come viene indirizzato un disco, come MBR e GPT ne descrivono lo spazio, in cosa differiscono partizioni e volumi e come ricavare da una voce della tabella delle partizioni l'offset esatto da cui dipende ogni strumento utilizzato successivamente.
Settori e indirizzamento LBA
Un disco si presenta come una sequenza numerata di blocchi di dimensione fissa chiamati settori. I sistemi moderni li indirizzano mediante il Logical Block Addressing (LBA): il primo settore è LBA 0, il successivo LBA 1 e così via. L'offset in byte di qualsiasi settore è semplicemente LBA × dimensione del settore logico.
Per decenni la dimensione dei settori è stata di 512 byte. Le unità Advanced Format utilizzano settori fisici da 4.096 byte e sono disponibili in due varianti:
| Formato | Settore logico | Settore fisico | Cosa vedono il sistema operativo e l'immagine |
|---|---|---|---|
| 512n (tradizionale) | 512 byte | 512 byte | LBA da 512 byte |
| 512e (emulazione) | 512 byte | 4.096 byte | LBA da 512 byte; l'unità associa 8 settori logici a ciascun settore fisico |
| 4Kn (nativo) | 4.096 byte | 4.096 byte | LBA da 4.096 byte |
Tutte le strutture di partizionamento contano in settori logici. La maggior parte delle unità USB e delle immagini utilizza settori logici da 512 byte, ma occorre registrare la dimensione del settore dal registro di acquisizione o dai metadati E01 anziché presumerla. Una partizione che inizia a LBA 2.048 comincia al byte 1048576 su un disco con settori da 512 byte e al byte 8388608 su un disco 4Kn.
Il Master Boot Record (MBR)
Lo schema MBR, chiamato anche tabella delle partizioni DOS, occupa il settore 0. I suoi 512 byte sono organizzati come segue:
| Offset (decimale) | Dimensione | Contenuto |
|---|---|---|
| 0 | 446 byte | Codice di avvio (Windows memorizza anche una firma del disco di 4 byte all'offset 440) |
| 446 (0x1BE) | 64 byte | Quattro voci di partizione da 16 byte ciascuna |
| 510 (0x1FE) | 2 byte | Firma di avvio, byte 55 AA (letti come valore little-endian 0xAA55) |
Ogni voce di partizione da 16 byte contiene:
| Offset nella voce | Dimensione | Campo |
|---|---|---|
| 0 | 1 | Indicatore di avvio (0x80 = attiva, 0x00 = non attiva) |
| 1 | 3 | Indirizzo iniziale nel formato tradizionale CHS (cilindro-testina-settore) |
| 4 | 1 | Byte del tipo di partizione |
| 5 | 3 | Indirizzo CHS finale |
| 8 | 4 | LBA iniziale, little-endian a 32 bit |
| 12 | 4 | Dimensione in settori, little-endian a 32 bit |
I campi CHS sono obsoleti; occorre basarsi sui campi LBA. Tra i byte di tipo più comuni figurano 0x07 (NTFS, exFAT), 0x0B e 0x0C (FAT32, varianti CHS e LBA), 0x05 e 0x0F (partizione estesa), 0x83 (file system Linux), 0x8E (Linux LVM) e 0xEE (protezione GPT). Il byte del tipo è soltanto un'etichetta; occorre confermare il contenuto leggendo il primo settore della partizione.
Partizioni estese e logiche
Quattro voci non erano sufficienti, quindi MBR consente che una voce sia una partizione estesa (tipo 0x05 o 0x0F). Il primo settore della partizione estesa contiene un Extended Boot Record (EBR) con la stessa struttura dell'MBR, inclusi i byte 55 AA. La prima voce descrive una partizione logica, con un LBA iniziale relativo a tale EBR. La seconda voce punta all'EBR successivo, relativamente all'inizio della partizione estesa. Il risultato è una lista concatenata, la catena EBR, che termina con un EBR la cui seconda voce è vuota. Un collegamento interrotto nasconde tutte le partizioni logiche successive.
Il limite di 2 TiB
Poiché l'LBA iniziale e la dimensione sono valori a 32 bit, MBR può descrivere al massimo 2^32 settori. Con settori da 512 byte, ciò corrisponde a 2^32 × 512 = 2.199.023.255.552 byte, ovvero 2 TiB.
La GUID Partition Table (GPT)
GPT è lo schema di partizionamento definito nella specifica UEFI. Mantiene il settore 0 come MBR protettivo: un normale MBR con un'unica voce di tipo 0xEE, che inizia a LBA 1 e copre il disco (o 0xFFFFFFFF settori se il disco è più grande di quanto MBR possa descrivere). Il suo scopo è impedire agli strumenti che supportano soltanto MBR di considerare vuoto il disco.
Le strutture effettive sono:
- Intestazione GPT a LBA 1. Inizia con la firma di 8 byte
EFI PART(esadecimale45 46 49 20 50 41 52 54) ed è lunga 92 byte nella revisione 1.0. Registra il proprio LBA, l'LBA dell'intestazione di backup, il primo e l'ultimo LBA utilizzabili, il GUID del disco, l'LBA iniziale dell'array delle voci di partizione, il numero di voci, la dimensione di ciascuna voce e due somme di controllo CRC32: una sull'intestazione stessa (calcolata con il campo CRC impostato a zero) e una sull'array delle voci di partizione. - Array delle voci di partizione, normalmente a partire da LBA 2, con 128 voci da 128 byte ciascuna. Si tratta di 16.384 byte, quindi su un disco con settori da 512 byte occupa gli LBA da 2 a 33 e il primo LBA utilizzabile è 34. Su un disco 4Kn occupa gli LBA da 2 a 5.
- GPT di backup alla fine del disco. L'intestazione di backup si trova all'ultimo LBA e una copia dell'array delle voci si trova immediatamente prima.
Ogni voce da 128 byte contiene un GUID del tipo di partizione di 16 byte, un GUID univoco della partizione di 16 byte, un primo LBA a 64 bit, un ultimo LBA a 64 bit (incluso), 8 byte di flag di attributo e un nome UTF-16LE di 72 byte. Un GUID del tipo composto interamente da zeri contrassegna una voce non utilizzata. GUID dei tipi più comuni:
| Partizione | GUID del tipo |
|---|---|
| Partizione di sistema EFI (ESP) | C12A7328-F81F-11D2-BA4B-00A0C93EC93B |
| Partizione riservata Microsoft (MSR) | E3C9E316-0B5C-4DB8-817D-F92DF00215AE |
| Dati di base Microsoft | EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 |
| Ambiente ripristino Windows | DE94BBA4-06D1-4D40-A16A-BFD50179D6AC |
| Dati del file system Linux | 0FC63DAF-8483-4772-8E79-3D69D8477DE4 |
Sul disco, i primi tre gruppi di un GUID sono memorizzati in little-endian, quindi il GUID dei dati di base appare in esadecimale come A2 A0 D0 EB E5 B9 33 44 87 C0 68 B6 B7 26 99 C7. Occorre cercare questo ordine di byte, non la forma stampata.
Se l'intestazione primaria o l'array non supera il controllo CRC32, il firmware e gli strumenti ricorrono al backup. Un'intestazione primaria e una di backup che superano entrambe la verifica ma non concordano meritano di essere segnalate: possono derivare da un ridimensionamento, dalla clonazione su un disco di dimensione diversa o da modifiche deliberate.
Disco, partizione e volume
Queste tre parole sono spesso usate in modo intercambiabile, ma indicano livelli diversi:
- Un disco è l'intero dispositivo indirizzabile o la sua immagine.
- Una partizione è un intervallo contiguo di settori descritto da una tabella delle partizioni.
- Un volume è un'area di archiviazione logica utilizzata da un file system o da un sistema operativo. Spesso corrisponde esattamente a una partizione, ma non sempre.
La corrispondenza non è sempre uno a uno. Una partizione può non contenere alcun file system: la MSR è un'area riservata grezza e una partizione può contenere un contenitore crittografato o appartenente a un pool anziché un file system. Un volume può anche estendersi su più partizioni o dischi. Tra la partizione e il file system possono interporsi diversi livelli. BitLocker trasforma una partizione in un volume crittografato il cui primo settore normalmente presenta la firma -FVE-FS- all'offset 3 (i volumi BitLocker To Go su unità rimovibili possono invece mostrare MSWIN4.1). Linux LVM riunisce i volumi fisici in gruppi di volumi e ne ricava volumi logici. Spazi di archiviazione di Windows e i precedenti dischi dinamici raggruppano le risorse di archiviazione nello stesso modo. Per ogni partizione, occorre chiedersi quale livello inizi in quel punto prima di scegliere uno strumento.
Disposizioni tipiche di Windows
Un'installazione UEFI di Windows 10 o 11 su un disco GPT contiene solitamente:
| Partizione | Dimensione tipica | Contenuto |
|---|---|---|
| Partizione di sistema EFI | 100 MiB (260 MiB sui dischi 4Kn) | FAT32; gestore di avvio e dati di configurazione di avvio |
| Riservata Microsoft (MSR) | 16 MiB | Nessun file system |
| Windows | La maggior parte del disco | NTFS; il sistema operativo e i dati degli utenti |
| Ripristino | Diverse centinaia di MiB | NTFS; Ambiente ripristino Windows |
Le dimensioni, l'ordine e il numero delle partizioni di ripristino o OEM variano in base alla versione di Windows, al programma di installazione e al produttore; occorre quindi leggere la tabella anziché presumere la disposizione. Le partizioni sono normalmente allineate a 1 MiB, motivo per cui la prima inizia a LBA 2.048 su un disco con settori da 512 byte. Le installazioni BIOS meno recenti utilizzano MBR con una piccola partizione NTFS attiva "Riservato per il sistema" prima della partizione Windows.
Individuazione degli intervalli vuoti e dello spazio non partizionato
Non tutti i settori appartengono a una partizione. Occorre confrontare la fine di ciascuna partizione con l'inizio della successiva e con la fine del disco. Gli intervalli vuoti tipici sono i settori da 1 a 2.047 prima della prima partizione allineata su un disco MBR, lo spazio residuo di allineamento tra le partizioni e lo spazio inutilizzato alla fine. Gli intervalli vuoti possono contenere residui di partizioni precedenti, dati nascosti intenzionalmente oppure nulla. Per trovare una partizione precedente, occorre cercare settori di avvio dei volumi nello spazio non partizionato. Un settore di avvio NTFS contiene NTFS all'offset 3, un settore di avvio FAT32 contiene FAT32 all'offset 82 e un settore di avvio exFAT contiene EXFAT all'offset 3. La lezione 1.2 tratta lo spazio non allocato all'interno di un file system, che è una cosa diversa.
Esempio svolto: dalla voce di partizione all'offset in byte
I 16 byte all'offset 446 di un'immagine di un'unità USB sono:
00 20 21 00 0C FE FF FF 00 08 00 00 00 B8 D3 01
- Indicatore di avvio
00: non attiva. - Byte del tipo
0C: FAT32 con indirizzamento LBA. - LBA iniziale, byte da 8 a 11:
00 08 00 00. Invertendo l'ordine per il formato little-endian: 0x00000800 = 2.048. - Dimensione, byte da 12 a 15:
00 B8 D3 01. Invertiti: 0x01D3B800 = 30.652.416 settori.
Con settori da 512 byte:
- Offset in byte della partizione = 2.048 × 512 = 1048576 (0x100000).
- Ultimo settore = 2.048 + 30.652.416 − 1 = 30.654.463.
- Dimensione della partizione = 30.652.416 × 512 = 15.694.036.992 byte (circa 14,6 GiB).
Elencare le partizioni con The Sleuth Kit
The Sleuth Kit legge direttamente le immagini raw e, quando viene compilato con libewf, le immagini E01. mmls usb.E01 rileva lo schema e stampa ciascuna voce in settori. Per l'unità precedente mostrerebbe quanto segue (in forma abbreviata):
| Posizione | Inizio | Fine | Lunghezza | Descrizione |
|---|---|---|---|---|
| Meta | 0 | 0 | 1 | Tabella primaria (#0) |
| ------- | 0 | 2.047 | 2.048 | Non allocato |
| 000:000 | 2.048 | 30.654.463 | 30.652.416 | Win95 FAT32 (0x0c) |
| ------- | 30.654.464 | 30.719.999 | 65.536 | Non allocato |
Le righe "Non allocato" sono gli intervalli vuoti di cui occorre rendere conto. Su un disco GPT, mmls elenca anche la tabella di sicurezza (protettiva), l'intestazione GPT e la tabella delle partizioni come righe Meta.
La maggior parte degli strumenti TSK accetta l'inizio del file system tramite -o, in settori: fsstat -o 2048 usb.E01 riporta il tipo di file system, il numero di serie del volume, l'etichetta e la geometria, mentre fls -o 2048 usb.E01 elenca i file. Altri strumenti richiedono invece un offset in byte, ad esempio un montaggio loop in sola lettura su Linux con offset=1048576. Confondere settori e byte è una causa comune del messaggio "nessun file system trovato". Occorre registrare nelle proprie note sia l'offset sia la relativa unità.
Il caso superfloppy
L'esame pratico CFX fornisce un'immagine E01 di un'unità USB. Questa può essere partizionata con MBR oppure non essere affatto partizionata. In quest'ultimo caso è un superfloppy: il file system inizia al settore 0 e non esiste alcuna tabella delle partizioni. Il settore 0 termina comunque con 55 AA, perché i record di avvio dei volumi utilizzano la stessa firma; pertanto, la sola firma non dimostra la presenza di un MBR. Occorre invece esaminare l'inizio del settore. Un settore di avvio comincia con un'istruzione di salto (tipicamente EB xx 90) seguita da un nome OEM di 8 byte come MSDOS5.0, EXFAT o NTFS . In questo caso mmls segnala solitamente di non riuscire a determinare il tipo di partizione e si esegue fsstat senza offset, il che significa offset 0.
Focus sull'esame: Occorre saper convertire i campi little-endian delle voci di partizione in un settore iniziale, un settore finale, una dimensione o un offset in byte e applicare la dimensione corretta del settore. È necessario conoscere le posizioni fisse:55 AAa 510, le voci a 446,EFI PARTa LBA 1, l'array delle voci normalmente a LBA 2 e l'intestazione di backup all'ultimo LBA. Nella parte pratica, occorre stabilire se l'immagine USB sia partizionata con MBR o sia un superfloppy prima di utilizzare qualsiasi strumento per file system.
Punti chiave
- Gli offset sono sempre
LBA × dimensione del settore logico; le unità 512e utilizzano LBA da 512 byte e le unità 4Kn utilizzano LBA da 4.096 byte. - Le voci MBR iniziano all'offset 446 e sono di 16 byte ciascuna, con il byte del tipo a +4, l'LBA iniziale a +8 e la dimensione in settori a +12, questi ultimi entrambi little-endian a 32 bit. Ciò limita MBR a 2 TiB con settori da 512 byte.
- GPT utilizza un MBR protettivo (tipo 0xEE), un'intestazione con
EFI PARTa LBA 1, normalmente 128 voci da 128 byte a partire da LBA 2, controlli CRC32 e un'intestazione di backup all'ultimo LBA. - Una partizione è un intervallo di settori e un volume è ciò che il sistema utilizza. Tra i due possono interporsi livelli di crittografia, LVM e raggruppamento in pool, e alcune partizioni, come la MSR, non contengono alcun file system.
- Occorre rendere conto di ogni settore: gli intervalli vuoti prima, tra e dopo le partizioni possono contenere partizioni precedenti o dati nascosti.
55 AAnel settore 0 non dimostra la presenza di un MBR; un superfloppy ha il proprio file system all'offset 0.