IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

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

Dans cette partie, nous verrons comment vérifier qu'un fichier donné respecte le format PE.
Article original : Tutorial 2: Detecting a Valid PE File

Retour à la liste des tutoriels

Tutoriel précédent : Aperçu du format PE
Tutoriel suivant : Entête de fichier

Article lu   fois.

Les deux auteur et traducteur

Site personnel

Traducteur : Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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 passer à 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 :

 
Sélectionnez
_IMAGE_NT_HEADERS = packed record
  Signature: DWORD;
  FileHeader: TImageFileHeader;
  OptionalHeader: TImageOptionalHeader;
end;

TImageNtHeaders = _IMAGE_NT_HEADERS;
  • Signature est un DWord contenant la valeur $50, $45, $00, $00. Pour être plus clair, il contient le texte "PE" suivi de deux zéros terminaux. Ce membre est la signature PE, nous l'utiliserons donc dans le processus de vérification.
  • FileHeader est une structure qui contient des informations à propos de l'organisation physique du fichier PE, comme le nombre de sections, la machine pour laquelle le fichier est destiné etc.
  • OptionalHeader est une structure qui contient des informations supplémentaires sur l'organisation du fichier PE. Malgré le terme "Optional" figurant dans son nom, il est toujours présent.

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 :

 
Sélectionnez
  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 :

 
Sélectionnez
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

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Copyright © 2005 Olivier Lance. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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.