PARTIE 4 : Entête facultatif

Iczelion

Traducteur

Traduction et adaptation par Olivier Lance

Nous avons vu l'entête DOS et quelques membres de l'entête PE. Voici le dernier, le plus gros et certainement le plus important membre de l'entête PE : l'entête facultatif.
Article original : Tutorial 4: Optional Header

Retour à la liste des tutoriels

Tutoriel précédent : Entête de fichier
Tutoriel suivant : La table des sections

- Titre : PARTIE 4 : Entête facultatif

- Auteur : Iczelion

- Traducteur : Traduction et adaptation par Olivier Lance

- Parution : 8 octobre 2005

- Mise à jour : 6 janvier 2020

- Licence : Copyright ® 2005 Olivier Lance. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

Pour mémoire, l'entête facultatif est le dernier membre de la structure TImageNtHeaders. Il contient des informations sur l'organisation logique du fichier PE. Cette structure comporte 31 champs.
Certains d'entre eux sont cruciaux et d'autres ne sont pas utiles. Nous verrons uniquement les champs qui sont réellement utiles. Un mot revient fréquemment en relation avec le format PE : RVA. RVA signifie Relative Virtual Address. Vous savez ce qu'est une adresse virtuelle(1). RVA est un terme un peu rebutant pour un concept aussi simple. Pour parler simplement, une RVA est une distance à partir d'un point de référence dans l'espace d'adressage virtuel. J'imagine que vous savez ce qu'est un offset fichier : une RVA est exactement la même chose qu'un offset fichier. Toutefois, elle est relative à une adresse virtuelle plutôt qu'au début d'un fichier.
Voici un exemple :
Si un fichier PE est chargé à l'adresse $400000 dans l'espace d'adressage virtuel et que le programme commence son exécution à l'adresse $401000, on peut dire que le programme débute à la RVA $1000. Une RVA est relative à l'adresse virtuelle du premier octet du module.
Pourquoi le format PE utilise-t-il des RVA ? Le but est de réduire le temps de chargement du PE Loader. Sachant qu'un module peut être déplacé n'importe où dans l'espace d'adressage virtuel, ce serait infernal pour le PE Loader de fixer les adresses de chaque élément à position variable du module(2). Par opposition, si tous les éléments ayant une position variable dans le fichier utilisent des RVA, le PE Loader n'a alors pas besoin de fixer quoi que ce soit : il déplace simplement tout le module à une nouvelle adresse virtuelle. Tout cela rejoint le concept de chemin relatif et chemin absolu : une RVA est assimilable à un chemin relatif, une adresse virtuelle à un chemin absolu.

Voici les champs intéressants de l'entête facultatif :

Champ

Contenu

AddressOfEntryPoint

Il s'agit de la RVA de la première instruction qui sera exécutée lorsque le PE Loader sera prêt à lancer le fichier. Si vous souhaitez détourner le flux d'exécution dès le démarrage du programme, vous devez changer cette valeur pour une autre RVA, et l'instruction à cette nouvelle RVA sera alors exécutée en premier.

ImageBase

C'est l'adresse de chargement souhaitable pour le fichier PE. Par exemple, si la valeur de ce champ est $400000, le PE Loader tentera de charger le fichier dans l'espace d'adressage virtuel à l'adresse $400000. Le mot "souhaitable" signifie que le PE Loader peut ne pas charger le fichier à cette adresse si un autre module l'occupe déjà.

SectionAlignment

La granularité de l'alignement des sections en mémoire. Par exemple, si la valeur est 4096 ($1000), chaque section doit débuter à un multiple de 4096 octets. Si la première section est à l'adresse $401000 et que sa taille est de 10 octets, la prochaine section doit se trouver à l'adresse $402000, même si l'espace entre $401000 et $402000 sera pour la plupart inutilisé.

FileAlignment

La granularité de l'alignement des sections dans le fichier. Par exemple, si la valeur est 512 ($200), chaque section doit débuter à un multiple de 512 octets. Si la première section est à l'adresse $200 et que sa taille est de 10 octets, la prochaine section doit se trouver à l'offset fichier $400 : l'espace entre les offsets 522 et 1024 est inutilisé/indéfini.

MajorSubSystemVersion
MinorSubSystemVersion

La version du système Win32. Si le fichier PE a été créé pour Win32, la version doit être 4.0 sans quoi les dialogues n'auront pas d'apparence 3D.

SizeOfImage

La taille totale du fichier PE en mémoire. C'est la somme de tous les entêtes et des sections alignées avec la valeur SectionAlignment.

SizeOfHeaders

La taille de tous les entêtes et de la table des sections. Cette valeur est égale à la taille du fichier moins la taille de toutes les sections du fichier. Vous pouvez utiliser cette valeur comme l'offset fichier de la première section dans le fichier PE.

Subsystem

Donne pour quel sous-système NT le fichier PE est prévu. Pour la plupart des programmes Win32, seules deux valeurs sont utilisées : Windows GUI (IMAGE_SUBSYSTEM_WINDOWS_GUI) et Windows GUI (console) (IMAGE_SUBSYSTEM_WINDOWS_CUI).

DataDirectory

Un tableau de structures IMAGE_DATA_DIRECTORY. Chaque structure fournit la RVA d'une structure de données importantes, comme la table d'importation.

Liens

- MSDN : Image Help Library

- MSDN : IMAGE_OPTIONAL_HEADER

Tutoriel suivant : La table des sections

(1)Pour ceux qui ne savent pas : il s'agit de l'adresse de données non pas sur un disque logique, mais dans la mémoire vive.

(2)La position de certains éléments varie du fait de la taille également variable de certains champs des entêtes.