Tutorial 3: File Header


(Le File Header c'est l'entête d'un fichier (d'un programme), c'est sa carte d'identité. C'est ici qu'on trouve des informations sur lui. Sa date de création, la date de dernière exécution, le nombre de sections qu'il possède....)

Dans ce Tutorial, nous allons étudier la partie 'file header' qui appartient au PE header.

On va récapituler ce que nous avons appris jusqu'ici :

Dans ce Tutorial Nous allons encore en apprendre plus sur le PE header. Le nom officiel du PE header est IMAGE_NT_HEADERS. Pour vous rafraichir la mémoire, je vous le remontre ci-dessous.

IMAGE_NT_HEADERS STRUCT
    Signature dd ?
    FileHeader IMAGE_FILE_HEADER <>
    OptionalHeader IMAGE_OPTIONAL_HEADER32 <>
IMAGE_NT_HEADERS ENDS

Signature est la signature 'PE', "PE" suivi de deux zéros. Vous la connaissez déjà et employez déjà ce membre.
FileHeader est une structure qui contient des informations sur la configuration/propriétés physique du PE file en général.
OptionalHeader est également une structure qui contient des informations sur la configuration logique de l'intérieur du PE file.

L'information la plus intéressante est dans OptionalHeader. Cependant, certains paramètres contenus dans FileHeader sont aussi importants. Nous allons en apprendre pas mal sur le FileHeader dans ce Tutorial donc nous nous occuperons plutôt de l'étude d'OptionalHeader dans les Tutorials suivants.

IMAGE_FILE_HEADER STRUCT
    Machine WORD ?
    NumberOfSections WORD ?
    TimeDateStamp dd ?
    PointerToSymbolTable dd ?
    NumberOfSymbols dd ?
    SizeOfOptionalHeader WORD ?
    Characteristics WORD ?
IMAGE_FILE_HEADER ENDS

Noms des paramètres Signification
Machine est le type de CPU (la plate-forme) pour lequel est destiné le fichier. Pour les CPU de type Intel, la valeur est IMAGE_FILE_MACHINE_I386 (14Ch). J'ai essayé d'employer 14Dh et 14Eh comme c'est mis dans le PE.txt de LUEVELSMEYER mais Windows a refusé de le lancer. Ce paramètre a rarement d'intérêt pour nous sauf si on s'en sert comme une manière rapide d'empêcher un programme d'être exécuté.
NumberOfSections est le nombre de sections dans le fichier. Nous aurons besoin de modifier la valeur dans ce membre si nous ajoutons ou supprimons une section du fichier.
TimeDateStamp est la date à laquelle le fichier a été créé. C'est pas utile pour nous.
PointerToSymbolTable est utilisé lorsqu'on débug le programme.
NumberOfSymbols est utilisé lorsqu'on débug le programme.
SizeOfOptionalHeader est la taille du membre OptionalHeader qui suit immédiatement cette structure. On doit lui donner une valeur valide.
Characteristics contient les flags qui servent au fichier, comme : est-ce un fichier exe ou dll.

En résumé, seulement trois membres sont utiles pour nous : Machine, NumberOfSections et Characteristics. Normalement, vous ne devriez pas avoir à changer les valeurs de Machine et Characteristics mais vous devez utiliser la valeur qui est dans NumberOfSections lorsque vous vous baladez dans la table des sections.
Pour illustrer l'utilisation de NumberOfSections, j'ai besoin de faire une brève parenthèse sur la table des sections.

La table des sections est un tableau regroupant plusieurs structures. Chaque structure contient des informations sur une section particulière. Ainsi s'il y a 3 sections (ex : .data .data? .code), il y aura 3 membres dans ce tableau. Vous avez besoin de la valeur dans NumberOfSections ainsi vous connaîtrez combien de membres comporte ce tableau. On peut essayer de mettre la valeur dans NumberOfSections à une valeur supérieur à celle réelle, et bien Windows lance toujours le fichier sans problème. D'après ce que j'ai observé, je pense que Windows lit la valeur dans NumberOfSections et examine chaque structure dans la table des sections. Si Windows rencontre une structure qui ne contient que des zéros, il termine sa recherche. Sinon il continue jusqu'à ce que le nombre de structures (donc de sections) rencontrées soit le même que le nombre dans NumberOfSections. Pourquoi ne pouvons nous pas ignorer la valeur NumberOfSections ? Il y a plusieurs raisons à ça. En fait, le PE ne spécifie pas que le tableau qu'est la table des sections doit forcément finir par une structure remplie de zéros. C'est pourquoi il peut y avoir certaines situations dans lesquelles le dernier membre du tableau est directement accolé à la première section, sans espace vide du tout. Une autre raison a un rapport avec les limites des importations. Un nouveau type de limites c'est de placer les informations immédiatement à la suite de la dernière structure de la table des sections. C'est pourquoi vous aurez toujours besoin de NumberOfSections.


[Iczelion's Win32 Assembly Homepage]


Traduit par Morgatte