mercredi 8 mars 2017

Le système de fichiers Ext4FS



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