Si vous souhaitez vous limiter à la détection ELF, vous pouvez lire l'en- tête ELF de /proc/$PID/exevous - même. C'est assez banal: si le 5ème octet du fichier est 1, c'est un binaire 32 bits. Si c'est 2, c'est 64 bits. Pour une vérification supplémentaire de la santé mentale:
- Si les 5 premiers octets sont
0x7f, "ELF", 1: c'est un binaire ELF 32 bits.
- Si les 5 premiers octets sont
0x7f, "ELF", 2: c'est un binaire ELF 64 bits.
- Sinon: ce n'est pas concluant.
Vous pouvez également utiliser objdump, mais cela supprime votre libmagicdépendance et la remplace par une libelfautre.
Une autre façon : vous pouvez également analyser le /proc/$PID/auxvfichier. Selon proc(5):
Il contient le contenu des informations d'interpréteur ELF transmises au processus au moment de l'exécution. Le format est un ID long non signé plus une valeur longue non signée pour chaque entrée. La dernière entrée contient deux zéros.
Les significations des unsigned longtouches sont là /usr/include/linux/auxvec.h. Vous voulez AT_PLATFORM, ce qui est 0x00000f. Ne me citez pas à ce sujet, mais il semble que la valeur devrait être interprétée comme un char *pour obtenir la description de la chaîne de la plate-forme.
Vous pouvez trouver cette question StackOverflow utile.
Encore une autre façon : vous pouvez demander au linker dynamique ( man ld) de vider les informations sur l'exécutable. Il imprime sur la sortie standard la structure AUXV décodée. Attention: c'est un hack, mais ça marche.
LD_SHOW_AUXV=1 ldd /proc/$SOME_PID/exe | grep AT_PLATFORM | tail -1
Cela montrera quelque chose comme:
AT_PLATFORM: x86_64
Je l'ai essayé sur un binaire 32 bits et l'ai obtenu à la i686place.
Comment cela fonctionne: LD_SHOW_AUXV=1demande au Dynamic Linker de vider la structure AUXV décodée avant d'exécuter l'exécutable. À moins que vous n'aimiez vraiment rendre votre vie intéressante, vous voulez éviter d' exécuter réellement ledit exécutable. Une façon de le charger et de le lier dynamiquement sans réellement appeler sa main()fonction est de l'exécuter ldd(1). L'inconvénient: LD_SHOW_AUXVest activé par le shell, vous obtiendrez donc des vidages des structures AUXV pour: le sous-shell ldd, et votre binaire cible. Nous avons donc greppour AT_PLATFORM, mais ne gardons que la dernière ligne.
Analyse Auxv : si vous analysez la auxvstructure vous-même (sans compter sur le chargeur dynamique), il y a un peu d'énigme: la auxvstructure suit la règle du processus qu'elle décrit, elle sizeof(unsigned long)sera donc 4 pour les processus 32 bits et 8 pour 64 processus de bits. Nous pouvons faire en sorte que cela fonctionne pour nous. Pour que cela fonctionne sur les systèmes 32 bits, tous les codes clés doivent être 0xffffffffou moins. Sur un système 64 bits, les 32 bits les plus significatifs seront nuls. Les machines Intel sont peu endians, donc ces 32 bits suivent les moins significatifs en mémoire.
À ce titre, il vous suffit de:
1. Read 16 bytes from the `auxv` file.
2. Is this the end of the file?
3. Then it's a 64-bit process.
4. Done.
5. Is buf[4], buf[5], buf[6] or buf[7] non-zero?
6. Then it's a 32-bit process.
7. Done.
8. Go to 1.
Analyser le fichier de cartes : cela a été suggéré par Gilles, mais n'a pas vraiment fonctionné. Voici une version modifiée qui le fait. Il repose sur la lecture du /proc/$PID/mapsfichier. Si le fichier répertorie les adresses 64 bits, le processus est de 64 bits. Sinon, c'est 32 bits. Le problème réside dans le fait que le noyau simplifiera la sortie en supprimant les zéros de tête des adresses hexadécimales en groupes de 4, de sorte que le hack de longueur ne peut pas tout à fait fonctionner. awkà la rescousse:
if ! [ -e /proc/$pid/maps ]; then
echo "No such process"
else
case $(awk </proc/$pid/maps -- 'END { print substr($1, 0, 9); }') in
*-) echo "32 bit process";;
*[0-9A-Fa-f]) echo "64 bit process";;
*) echo "Insufficient permissions.";;
esac
fi
Cela fonctionne en vérifiant l'adresse de départ de la dernière carte mémoire du processus. Ils sont listés comme 12345678-deadbeef. Donc, si le processus est de 32 bits, cette adresse comportera huit chiffres hexadécimaux et le neuvième sera un tiret. S'il s'agit d'un 64 bits, l'adresse la plus élevée sera plus longue que cela. Le neuvième caractère sera un chiffre hexadécimal.
Attention: toutes les méthodes sauf la première et la dernière ont besoin du noyau Linux 2.6.0 ou plus récent, car le auxvfichier n'était pas là auparavant.
/proc/[pid]/auxv: "les informations d'interpréteur ELF transmises au processus au moment de l'exécution. Le format est un ID long non signé plus une valeur longue non signée pour chaque entrée" (man proc).