Wenn Sie sich auf die ELF-Erkennung beschränken möchten, können Sie den ELF-Header von sich /proc/$PID/exe
selbst lesen . Es ist ziemlich trivial: Wenn das 5. Byte in der Datei 1 ist, ist es eine 32-Bit-Binärdatei. Wenn es 2 ist, ist es 64-Bit. Für zusätzliche Überprüfung der geistigen Gesundheit:
- Wenn die ersten 5 Bytes sind
0x7f, "ELF", 1
: Es ist eine 32-Bit-ELF-Binärdatei.
- Wenn die ersten 5 Bytes sind
0x7f, "ELF", 2
: Es ist eine 64-Bit-ELF-Binärdatei.
- Ansonsten: es ist nicht schlüssig.
Sie könnten auch verwenden objdump
, aber das nimmt Ihre libmagic
Abhängigkeit und ersetzt sie durch eine libelf
Eins.
Eine andere Möglichkeit : Sie können die /proc/$PID/auxv
Datei auch analysieren . Nach proc(5)
:
Dies enthält den Inhalt der ELF-Interpreterinformationen, die zur Ausführungszeit an den Prozess übergeben werden. Das Format besteht aus einer vorzeichenlosen langen ID und einem vorzeichenlosen langen Wert für jeden Eintrag. Der letzte Eintrag enthält zwei Nullen.
Die Bedeutungen der unsigned long
Schlüssel sind in /usr/include/linux/auxvec.h
. Du willst AT_PLATFORM
, was ist 0x00000f
. Zitieren Sie mich nicht, aber es scheint, dass der Wert als interpretiert werden sollte char *
, um die Zeichenfolgenbeschreibung der Plattform zu erhalten.
Diese StackOverflow-Frage ist möglicherweise hilfreich.
Noch eine andere Möglichkeit : Sie können den dynamischen Linker ( man ld
) anweisen , Informationen über die ausführbare Datei zu sichern. Es druckt die dekodierte AUXV-Struktur als Standardausgabe aus. Warnung: Dies ist ein Hack, aber es funktioniert.
LD_SHOW_AUXV=1 ldd /proc/$SOME_PID/exe | grep AT_PLATFORM | tail -1
Dies zeigt etwas wie:
AT_PLATFORM: x86_64
Ich habe es mit einer 32-Bit-Binärdatei versucht und i686
stattdessen bekommen.
So funktioniert es: LD_SHOW_AUXV=1
Weist den Dynamic Linker an, die dekodierte AUXV-Struktur zu sichern, bevor die ausführbare Datei ausgeführt wird. Wenn Sie Ihr Leben nicht wirklich interessant machen möchten, möchten Sie vermeiden, dass die genannte ausführbare Datei tatsächlich ausgeführt wird . Eine Möglichkeit, es zu laden und dynamisch zu verknüpfen, ohne seine main()
Funktion aufzurufen , besteht darin, es auszuführen ldd(1)
. Der Nachteil: LD_SHOW_AUXV
Wird von der Shell aktiviert, sodass Sie Speicherauszüge der AUXV-Strukturen erhalten für: die Subshell ldd
und Ihre Zielbinärdatei . Also wir grep
für AT_PLATFORM, aber nur die letzte Zeile behalten.
Parsing auxv : Wenn Sie die auxv
Struktur selbst analysieren (ohne auf den dynamischen Loader angewiesen zu sein), gibt es ein kleines Rätsel: Die auxv
Struktur folgt der Regel des beschriebenen Prozesses, also sizeof(unsigned long)
4 für 32-Bit-Prozesse und 8 für 64 -Bit-Prozesse. Wir können diese Arbeit für uns erledigen. Damit dies auf 32-Bit-Systemen funktioniert, müssen alle Schlüsselcodes 0xffffffff
kleiner oder gleich sein. Auf einem 64-Bit-System sind die höchstwertigen 32 Bit Null. Intel-Maschinen sind kleine Endianer, daher folgen diese 32 Bit den niedrigstwertigen im Speicher.
Alles, was Sie tun müssen, ist:
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.
Analysieren der Kartendatei : Dies wurde von Gilles vorgeschlagen, funktionierte aber nicht ganz. Hier ist eine modifizierte Version, die dies tut. Es beruht auf dem Lesen der /proc/$PID/maps
Datei. Wenn in der Datei 64-Bit-Adressen aufgeführt sind, werden 64-Bit-Adressen verarbeitet. Ansonsten sind es 32 Bits. Das Problem liegt darin, dass der Kernel die Ausgabe vereinfacht, indem führende Nullen von Hexadezimaladressen in 4er-Gruppen entfernt werden, sodass der Längen-Hack nicht ganz funktionieren kann. awk
zur Rettung:
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
Dies funktioniert, indem die Startadresse der letzten Speicherzuordnung des Prozesses überprüft wird. Sie sind wie aufgeführt 12345678-deadbeef
. Wenn es sich also um einen 32-Bit-Prozess handelt, besteht diese Adresse aus acht Hexadezimalziffern und der neunte aus einem Bindestrich. Wenn es sich um eine 64-Bit-Adresse handelt, ist die höchste Adresse länger. Das neunte Zeichen ist eine hexadezimale Ziffer.
Beachten Sie: Alle außer der ersten und der letzten Methode benötigen den Linux-Kernel 2.6.0 oder neuer, da die auxv
Datei vorher nicht vorhanden war.
/proc/[pid]/auxv
: "Die zum Ausführungszeitpunkt an den Prozess übergebenen ELF-Interpreterinformationen. Das Format besteht aus einer vorzeichenlosen langen ID und einem vorzeichenlosen langen Wert für jeden Eintrag" (man proc
).