Developpez.com

Télécharger gratuitement le magazine des développeurs, le bimestriel des développeurs avec une sélection des meilleurs tutoriels

Developpez.com - Delphi
X

Choisissez d'abord la catégorieensuite la rubrique :


PARTIE 2 : Vérifier la validité d'un fichier PE

Date de publication : 08/09/2005

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

Dans cette partie, nous verrons comment vérifier qu'un fichier donné respecte le format . Article original : Retour à Tutoriel précédent : Tutoriel suivant :



Théorie

Comment savoir si un fichier est un fichier PE valide ?
C'est une question à laquelle il est difficile de répondre. Cela dépend du temps que vous voulez passez à faire la vérification. Vous pouvez vérifier chaque donnée de chaque structure définie dans les spécifications du format PE, ou simplement vous satisfaire de la vérification des données cruciales que ces structures contiennent.
La plupart du temps, il est relativement inutile de vérifier les données une à une dans le fichier. Si les structures principales sont valides, on peut considérer le fichier comme un fichier PE valide. Nous nous bornerons à cette considération.

La principale structure que nous vérifierons est l'entête PE lui-même. Nous avons donc besoin d'en savoir un peu plus à son sujet, du point de vue programmation.
L'entête PE est en fait une structure appelée TImageNtHeaders. Sa définition dans l'unité Windows.pas de Delphi est la suivante :
_IMAGE_NT_HEADERS = packed record
  Signature: DWORD;
  FileHeader: TImageFileHeader;
  OptionalHeader: TImageOptionalHeader;
end;

TImageNtHeaders = _IMAGE_NT_HEADERS;
Notre but est maintenant clair. Si la valeur de la signature de l'entête PE est égale à "PE" suivie de deux zéros, alors le fichier est un fichier PE valide. En réalité, à des fins de comparaison, Microsoft a défini quelques constantes nommées IMAGE_XX_SIGNATURE que l'on peut facilement utiliser :
  IMAGE_DOS_SIGNATURE                     = $5A4D;      { MZ }
  IMAGE_OS2_SIGNATURE                     = $454E;      { NE }
  IMAGE_OS2_SIGNATURE_LE                  = $454C;      { LE }
  IMAGE_VXD_SIGNATURE                     = $454C;      { LE }
  IMAGE_NT_SIGNATURE                      = $00004550;  { PE00 }
La question est maintenant : comment savoir où se trouve l'entête PE ?
La réponse est simple : l'entête DOS MZ contient l'offset dans le fichier de l'entête PE. L'entête DOS MZ est défini par la structure TImageDosHeader. Vous pouvez en consulter la composition dans l'unité Windows.pas. Le membre _lfanew de la structure TImageDosHeader contient l'offset de l'entête PE.

Les étapes sont donc les suivantes :

  1. Vérifier que le fichier a un entête DOS MZ valide en comparant le premier Word du fichier avec la valeur IMAGE_DOS_SIGNATURE.
  2. Si le fichier a un entête DOS valide, utiliser la valeur contenue dans le membre _lfanew pour trouver l'entête PE.
  3. Comparer le premier DWord de l'entête PE avec la valeur IMAGE_NT_SIGNATURE. Si les deux valeurs concordent, alors on peut considérer le fichier comme un fichier PE valide.

Exemple

La fonction suivante renvoie True si le fichier donné en paramètre est un fichier PE, False s'il n'est pas valide ou s'il y a un problème lors de la lecture du fichier :
function IsValidPE(Fichier: String): Boolean;
var
  EnteteDOS: TImageDosHeader;  //Structure pour l'entête DOS MZ
  EntetePE : TImageNtHeaders;  //Structure pour l'entête PE
  FStream  : TFileStream;      //Stream de lecture
begin

  Result := True;

  If not FileExists(Fichier) then
  begin
    Result := False;
    Exit;
  end;

  FStream := TFileStream.Create(Fichier, fmOpenRead);
  try
    try
      //Lecture de l'entête DOS MZ
      FStream.ReadBuffer(EnteteDOS, SizeOf(EnteteDOS));

      //Comparaison de la signature du fichier avec la signature DOS
      If EnteteDOS.e_magic <> IMAGE_DOS_SIGNATURE then
        Result := False
      else
      begin
        //Déplacement jusqu'à l'entête PE dont l'offset est indiqué par _lfanew
        FStream.Seek(EnteteDOS._lfanew, soFromBeginning);
        //Lecture de l'entête PE
        FStream.ReadBuffer(EntetePE, SizeOf(EntetePE));

        //Comparaison de la signature de l'entête avec la signature PE
        If EntetePE.Signature <> IMAGE_NT_SIGNATURE then
          Result := False;
      end;
    except
      //En cas de problème, on renvoie False
      On Exception do
        Result := False;
    end;
  finally
    FStream.Free;
  end;
end;

Liens

Tutoriel suivant : Entête de fichier



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 -