Le
système de fichiers Ext4FS
Auteur :
Sylvain Desharnais
Sommaire :
L’article suivant traite de la structure des données à bord d’une clé USB 128
Mo formatée en Ext4FS. Nous verrons la structure d’un secteur de démarrage, d’un
superbloc, d’un répertoire racine et d’une table d’inodes. Nous verrons ensuite
le fonctionnement des matriciels (« bitmaps ») pour terminer par
quelques commentaires sur la table des descripteurs de groupes de blocs et le
journal ExtFS.
1) Secteur
de démarrage : Pour
examiner un média formaté Ext4FS, il faut commencer par le secteur de
démarrage. Celui-ci est situé dans le secteur 0 (décompte fait à partir du
début physique du média). On y trouve notamment des informations sur les
partitions présentes sur le média. Dans le cas d’un média amovible, les
fonctions de formatage de la plupart des systèmes d’exploitation permettent
l’installation de seulement une partition. Voici un gabarit WinHex illustrant
le contenu du secteur de démarrage d’une clé USB de 128 Mo formaté à l’aide d’un
Linux Mint Cinamon. Seule la partition 1 est illustrée ci-dessous. Les autres
partitions n’étant pas créées, leurs paradonnées seront à zéro. Ces listes de
paradonnées commencent aux décalages 0x1CE, 0x1DE et 0x1EE présentent les mêmes
éléments dans le même ordre. La signature de fin de secteur de démarrage
(0x55AA) apparaît au décalage 0x1FE.
2) Super-bloc : Le super-bloc est un bloc de données
décrivant la partition dans laquelle il est situé. Ce bloc commence au décalage
0x400 à compter du début de la partition. Dans le cas de notre clé USB, la
partition commence au secteur 2048 tel qu’indiqué dans le secteur de démarrage
au décalage 0x1C6 du début physique du média. Ce super-bloc est donc situé dans
le bloc #2 de cette partition. Il est ensuite recopié au début de chaque groupe
de blocs de données. Le tableau ci-dessous présente les informations trouvées
dans ce super-bloc de notre clé USB. Le logiciel utilisé est WinHex. Le
décalage indiqué est calculé à partir du début physique du média.
Parmi les éléments à retenir,
signalons :
·
1049600
Nombre total d’inodes et 1049640 Nombre d’inodes par groupe de blocs. Le
premier divisé par le second donne le nombre de groupes de blocs de la
partition;
·
1049652
Nombre de fois où le média a été monté, 1049644/48 Dates et 1049736 Dernière
valeur de montage. À noter pour démontrer l’intégrité d’un média recueilli;
·
1049632
Nombre de blocs par groupe. Afin de comprendre l’organisation des données;
·
1049684
Premier inode non réservé (à la gestion du système de fichiers);
·
1049688
Taille des inodes. Sur les Ext4FS de médias fixes, la taille des inodes peut
aussi être de 156 ou de 256 octets;
·
1049690
Numéro de bloc assigné au super-bloc. Signifie que le bloc 11 est en fait le 13ième
bloc de ce groupe de bloc;
·
1049704
UUID du volume et 1049720 Nom du volume. Utiles pour distinguer ce média des
autres. C’est une trace qui est parfois laissée sur d’autres média ou dans des
flux de communication.
3) Répertoire
racine : Le
troisième endroit où regarder, c’est le répertoire racine. Pour chaque
répertoire créé, on aura deux champs standards de 12 octets, le premier nommé
« . » et le second « .. ». Le premier est le répertoire
local et le second désigne le répertoire parent (comme dans la commande
« cd .. » pour remonter d’un étage dans une arborescence de
répertoire en mode terminal). Dans le répertoire racine, le répertoire
« lost+found » est installé par défaut.
Une façon de retrouver le répertoire
racine dans un média auquel on n’a pas accès à l’arborescence est de faire une
recherche par mot-clé avec « lost+found » ou un nom de fichier dont
on sait qu’il existe. Pour notre barrette USB, la racine se trouve dans le
secteur logique 8018.
Une entrée de répertoire est constituée de
5 champs : Numéro d’inode où sont stockées les paradonnées de l’entité
dont c’est l’entrée (4 octets), la taille de l’entrée (2 octets), la taille du
nom (1 octet), le type d’entité (1 octet) et le nom de l’entité (taille
variable). Le type d’entité peut être, notamment, un répertoire (02) ou un
fichier (01) ou autres choses. Voyez l’aperçu d’écran suivant, pris dans FTK
Imager.
4) Table
d’inodes : La
table d’inodes de notre clé USB se situe au secteur logique 578. Les inodes ont
ici une taille de 128 octets. L’aperçu ci-dessous se rapporte au fichier
« Frette », l’inode #20. Les champs suivants sont ceux qui présentent
un certain intérêt (les décalages sont calculés par rapport au début de
l’inode). Le chiffre entre parenthèses est la longueur du champ en octets, GB
ou PB pour lecture gros ou petit boutiste.
·
0x00(2PB) :
Type de fichier et mode. Le tableau immédiatement sous l’aperçu FTKi décode
cette valeur. C’est à cet endroit qu’on inscrira les permissions relatives à ce
fichier/répertoire;
·
0x04(4PB) :
Taille logique du fichier en octets. Ici : 82,268,551;
·
0x08(4X4PB) :
Dates heures Unix 32 bits Petit Boutiste. Accès, changement, modification et
suppression;
·
0x1A(2PB) :
Nombre de liens « durs ». Si à 0, ça indique que le fichier a été
supprimé. 2 indique la présence d’un pointeur vers cet objet en plus du
pointeur pointant vers l’objet réel;
·
0x1C(4PB) :
Taille physique du fichier en nombre de blocs. Ici, 160684. Les blocs sont de
512 octets;
·
À
0x28(15X4PB) : Pointeurs vers les blocs. En principe. Mais ceci demande un
certain décodage. Voir deuxième tableau sous l’aperçu FTKi;
5) Matriciels : Les matriciels
(« bitmaps ») : Les matriciels sont des fichiers qu’on doit
interpréter au niveau du bit et non de l’octet. On lit un matriciel à partir du
bit le plus à droite d’un octet avant de passer au suivant. Ainsi, la séquence
0xFFFFC5 ne signifie pas qu’il y a 16,777,157 inodes occupés.
Remarque :
L’interprétation doit se
faire sans égard à la signification mathématique. Ainsi, dans l’exemple
ci-dessous, 0xFFFFC5 ne signifie pas non plus que les seize premiers inodes
soient occupés et que les 15 suivants le soient. Ça signifie que 8 + 8
consécutifs sont affectés, ainsi que 4 autres inodes, non-consécutifs. On
compte le nombre de « 1 » et on tient compte de leurs positions.
Supposons que dans l’exemple ci-dessous, ce soit un matriciel trouvé au
décalage 0x00 d’une table d’inodes.
0xFFFFC5
|
1111
1111
|
1111
1111
|
1100
0101
|
Inodes 0 à 7 occupés
|
Inodes 8 à 15 occupés
|
Inodes 16, 18, 22 et 23
sont occupés
|
Cette façon de faire existe aussi en NTFS
où il y a un $BITMAP servant à lister les grappes occupées (1) ou disponibles
(0);
6) Table
des descripteurs de groupes de blocs : La raison d’être de ces enregistrements de 32 octets
est d’optimiser les opérations entre inodes et blocs.
7) Journal : Les transactions (ajout,
modification, suppression de fichiers, par exemple) se font par le biais du
journal. Les transactions y sont écrites d’abord puis elles sont écrites sur le
média aussitôt que le système d’exploitation est disponible à cet effet. C’est
un problème classique en informatique judiciaire. Classique mais pas encore
bien résolu. Si on pouvait « rejouer » ce journal, on aurait
certainement des indices criants à utiliser. D’autant plus qu’il existe des
concepts équivalents en Mac OSx et en NTFS.
8) Conclusion : Une bonne lecture supplémentaire
est https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout.
Aucun commentaire:
Publier un commentaire