web-dev-qa-db-fra.com

Comment tester un fichier Windows DLL afin de déterminer s'il s'agit d'un fichier 32 bits ou 64 bits?

J'aimerais écrire un script de test ou un programme qui affirme que tous les fichiers DLL d'un répertoire donné sont d'un type de construction particulier.

J'utiliserais cela comme vérification de validité à la fin du processus de génération d'un SDK pour m'assurer que la version 64 bits ne contient pas de fichiers DLL 32 bits et inversement.

Existe-t-il un moyen simple d’examiner un fichier DLL et de déterminer son type?

La solution devrait fonctionner à la fois sur xp32 et xp64.

252
morechilli

Détails Gory

Un DLL utilise le format exécutable PE et il n'est pas trop difficile de lire ces informations dans le fichier.

Voir ceci article MSDN sur le format de fichier PE pour un aperçu. Vous devez lire l'en-tête MS-DOS, puis la structure IMAGE_NT_HEADERS . Cela contient la structure IMAGE_FILE_HEADER qui contient les informations dont vous avez besoin dans le membre Machine et qui contient l'une des valeurs suivantes.

  • IMAGE_FILE_MACHINE_I386 (0x014c)
  • IMAGE_FILE_MACHINE_IA64 (0x0200)
  • IMAGE_FILE_MACHINE_AMD64 (0x8664)

Cette information devrait se trouver à un décalage fixe dans le fichier, mais je recommanderais quand même de parcourir le fichier et de vérifier la signature de l'en-tête MS-DOS et de IMAGE_NT_HEADERS pour vous assurer de faire face aux modifications futures.

Utilisez ImageHelp pour lire les en-têtes ...

Vous pouvez également utiliser ImageHelp API pour cela. Chargez le DLL avec LoadImage et vous obtiendrez un LOADED_IMAGE structure qui contiendra un pointeur sur une structure IMAGE_NT_HEADERS. Libérez LOADED_IMAGE avec ImageUnload.

... ou adaptez ce script brut en Perl

Voici un script approximatif en Perl qui fait le travail. Il vérifie que le fichier a un en-tête DOS, puis lit le décalage PE à partir des 60 octets IMAGE_DOS_HEADER dans le fichier.

Il cherche ensuite au début de la partie PE, lit la signature et la vérifie, puis extrait la valeur qui nous intéresse.

#!/usr/bin/Perl
#
# usage: petype <exefile>
#
$exe = $ARGV[0];

open(EXE, $exe) or die "can't open $exe: $!";
binmode(EXE);
if (read(EXE, $doshdr, 64)) {

   ($magic,$skip,$offset)=unpack('a2a58l', $doshdr);
   die("Not an executable") if ($magic ne 'MZ');

   seek(EXE,$offset,SEEK_SET);
   if (read(EXE, $pehdr, 6)){
       ($sig,$skip,$machine)=unpack('a2a2v', $pehdr);
       die("No a PE Executable") if ($sig ne 'PE');

       if ($machine == 0x014c){
            print "i386\n";
       }
       elsif ($machine == 0x0200){
            print "IA64\n";
       }
       elsif ($machine == 0x8664){
            print "AMD64\n";
       }
       else{
            printf("Unknown machine type 0x%lx\n", $machine);
       }
   }
}

close(EXE);
105
Paul Dixon

Une méthode grossière consiste à appeler dumpbin avec l'option d'en-têtes à partir des outils Visual Studio sur chaque DLL et à rechercher le résultat approprié:

 dumpbin/headers my32bit.dll 
 
 La signature PE a été trouvée 
 
 Type de fichier: DLL 
 
 EN-FICHIER VALEURS 
 Machine 14C (x86) 
 1 nombre de sections 
 45499E0U heure horodatage jeu. Nov. 02 03:28:10 2006 
 0 pointeur de fichier sur la table des symboles 
 0 nombre de symboles 
 E0 taille de l’en-tête facultatif 
 Caractéristiques 2102 
 Exécutable 
 Machine Word 32 bits 
 DLL 
 
 VALEURS EN-TÊTE FACULTATIVES 
 10B numéro magique (PE32) 

Vous pouvez voir quelques indices dans cette sortie qu'il s'agit d'une DLL 32 bits, y compris la valeur 14C mentionnée par Paul. Devrait être facile à rechercher dans un script.

162
Jeremy

Si Cygwin est installé (ce que je recommande vivement pour diverses raisons), vous pouvez utiliser l'utilitaire 'fichier' de la DLL.

file <filename>

ce qui donnerait une sortie comme celle-ci:

icuuc36.dll: MS-DOS executable PE  for MS Windows (DLL) (GUI) Intel 80386 32-bit
106
DevSolar

Dependency Walker dit tout (enfin presque). http://www.dependencywalker.com/

Il ne "installe" pas - il suffit de l'obtenir, de l'extraire et de lancer l'exécutif. Cela fonctionne pour n'importe quelle application de module Windows x32 ou x64.

Si je me souviens bien, il est assez simple de voir toutes les dépendances, c’est-à-dire les modules dll, et depuis l’appl. est la somme des dépendances que l’on peut vérifier s’il s’agit de x64 complet, x32 (x86) ou un peu de chacun.

Le type de CPU pour lequel le module a été créé est dans la colonne "CPU". La plupart des APS 64 bits sont encore un peu de chacun, mais des 32 bits avec tous les x86.

Beau programme pour les geeks/programmeurs et c'est gratuit ...

45
Ric

J'ai écrit un outil très simple qui fait exactement cela - il s'appelle PE Deconstructor.

Il suffit de le lancer et de charger votre fichier DLL:

enter image description here

Dans l'exemple ci-dessus, le DLL chargé est 32 bits.

Vous pouvez le télécharger ici (je n'ai que la version 64 bits de l'ATM compilé):
http://files.quickmediasolutions.com/exe/pedeconstructor_0.1_AMD64.exe

Une version 32 bits plus ancienne est disponible ici:
http://dl.dropbox.com/u/31080052/pedeconstructor.Zip

39
Nathan Osman