Developpez.com - Delphi
X

Choisissez d'abord la catégorieensuite la rubrique :


PARTIE 3 : Entête de fichier

Date de publication : 18/09/2005

Par Iczelion (Iczelion's Win32 Assembly Homepage)
 Traduction et adaptation par Olivier Lance (Accueil)
 

Dans ce tutoriel nous étudierons l'entête de fichier de l'entête PE. Article original : Retour à Tutoriel précédent : Tutoriel suivant :


Voyons tout d'abord ce que nous avons appris jusqu'ici :

L'entête DOS MZ est appelée TImageDosHeader. Seuls deux de ses membres ont un intérêt pour nous : e_magic qui contient le texte "MZ" et _lfanew qui contient l'offset de l'entête PE dans le fichier.
On utilise la valeur de e_magic pour vérifier que le fichier a un entête DOS valide, en la comparant à la valeur de IMAGE_DOS_SIGNATURE. Si les deux valeurs correspondent, on considère que le fichier a un entête DOS valide.
Pour aller à l'entête PE, il faut se déplacer dans le fichier à l'offset indiqué par la valeur de _lfanew.
Le premier DWord de l'entête PE doit contenir le texte "PE" suivi de deux zéros. La valeur de ce DWord est comparée à la valeur IMAGE_NT_SIGNATURE. Si elles correspondent, alors on considère que l'entête PE est valide.

Nous en apprendrons plus sur l'entête PE dans ce tutoriel. Le nom de l'entête PE dans l'unité windows.pas est TImageNtHeaders. Pour rappel, voici sa composition :
_IMAGE_NT_HEADERS = packed record
  Signature: DWORD;
  FileHeader: TImageFileHeader;
  OptionalHeader: TImageOptionalHeader;
end;

TImageNtHeaders = _IMAGE_NT_HEADERS;
Les informations les plus intéressantes sont dans l'entête facultatif. Cependant, certains champs de l'entête de fichier ont également leur importance. Nous étudierons l'entête de fichier dans ce tutoriel, pour nous intéresser à l'entête facultatif dans le prochain tutoriel.
Déclaration de l'entête de fichier
_IMAGE_FILE_HEADER = packed record
  Machine: Word;
  NumberOfSections: Word;
  TimeDateStamp: DWORD;
  PointerToSymbolTable: DWORD;
  NumberOfSymbols: DWORD;
  SizeOfOptionalHeader: Word;
  Characteristics: Word;
end;

TImageFileHeader = _IMAGE_FILE_HEADER;
Champ Contenu
Machine Le processeur pour lequel le fichier est prévu. Pour une plateforme Intel, la valeur est IMAGE_FILE_MACHINE_I86 ($14C)(1). Ce champ est d'un rare intérêt pour nous, si ce n'est qu'il constitue une manière rapide d'empêcher un programme de s'exécuter sur une plateforme inadaptée.
NumberOfSections Le nombre de sections dans le fichier. Nous aurons besoin de modifier cette valeur lors de l'ajout ou de la suppression d'une section dans le fichier.
TimeDateStamp La date et l'heure auxquelles le fichier a été créé. Inutile pour nous.
PointerToSymbolTable Utilisé pour le débogage. Semble être toujours 0.
NumberOfSymbols Utilisé pour le débogage. Semble être toujours 0.
SizeOfOptionalHeader Taille de la structure OptionalHeader qui suit immédiatement l'entête fichier. Elle doit être initialisée avec une valeur correcte.
Characteristics Contient des flags pour le fichier, comme par exemple pour indiquer s'il s'agit d'un EXE ou d'une DLL.
Pour résumer, seuls trois membres nous seront quelque peu utiles : Machine, NumberOfSections et Characteristics. Vous n'aurez normalement aucune raison de modifier les valeurs de Machine ou de Characteristics, mais il faudra utiliser NumberOfSections pour parcourir la table des sections.
Je prends un peu d'avance ici, mais pour illustrer l'utilisation de NumberOfSections, il faut dériver un peu sur la table des sections elle-même.

La table des sections est un tableau de structures. Chaque structure contient les informations d'une section. Ainsi s'il y a trois sections, il y aura trois membres dans cette table. La valeur de NumberOfSections est donc nécessaire pour connaître le nombre de membres présents dans ce tableau. Vous songerez éventuellement que chercher une structure contenant uniquement des zéros pourrait aider. Windows semble utiliser cette approche. Vous pouvez le vérifier en changeant la valeur de NumberOfSections en un nombre supérieur à la valeur originale. Windows lancera le fichier sans problème.
D'après mes observations, je pense que Windows lit la valeur de NumberOfSections et examine chaque structure dans la table des sections. S'il trouve une structure qui ne contient que des zéros, il arrête sa recherche. Sinon il continue jusqu'à avoir inspecté autant de structures qu'indiqué par NumberOfSections.
Pourquoi alors ne pas ignorer la valeur de NumberOfSections ? Il y a plusieurs raisons à cela. La spécification du format PE n'indique pas que le tableau de la table des sections doit se terminer par une structure ne contenant que des zéros. Ainsi on peut se trouver dans une situation où le dernier membre du tableau est contigu à la première section, sans aucune forme d'espace libre. Une autre raison concerne les importations. La nouvelle méthode de liaison insère les informations directement après le dernier membre du tableau de la table des sections. Vous avez donc toujours besoin de NumberOfSections.


Liens

Tutoriel suivant : Entête facultatif



(1)Iczelion indique avoir essayé d'utiliser $14D et $14E comme indiqué dans le fichier pe.txt de Luevelsmeyer, mais Windows refuse alors de lancer le fichier, indiquant que l'exe n'est pas une application Win32 valide.

Valid XHTML 1.1!Valid CSS!

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.

Responsables bénévoles de la rubrique Delphi : Gilles Vasseur - Alcatîz -