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
).hd
eine herausgegeben und es fehlte die magische Zahl. Es mag einige relevante Informationen geben, aber ich denke, dass diese häufiger geändert werden als der ELF-Header. Es wurde auch in 2.6.0 eingeführt, ist also nicht ganz so allgegenwärtig wie/proc/PID/exe
. Aber es hat die Architekturinformationen. Ich werde meine Antwort aktualisieren.sizeof(unsigned long)
8 auf 64-Bit oder 4 auf 32-Bit, was bedeutet, dass Sie, um es direkt richtig zu interpretieren, wissen müssen, ob der Prozess 64-Bit oder 32-Bit ist!auxv
Schlüsselcodes für eine 32-Bit-Version passenunsigned long
, sodass die höchstwertigen 32-Bit-Versionen auf einer 64-Bit-Box Null sind.Schau rein
/proc/$pid/maps
. Die Adressbereiche sind über 32-Bit-Adressen (8 Hexadezimalstellen) oder 64-Bit-Adressen (16 Hexadezimalstellen). Dies funktioniert für jede Art von ausführbarer Datei, egal in welchem Format. Sie können nur Informationen zu Prozessen abrufen, die als derselbe Benutzer ausgeführt werden (es sei denn, Sie sind root).Wenn Sie keine Berechtigung zum Zugriff auf diese Datei haben, besteht meiner Meinung nach die einzige Möglichkeit darin, die ausführbare Datei zu analysieren. (Sie können zwar immer lesen
/proc/$pid/stat
, aber keines der Felder, die für Prozesse angezeigt werden, die als unterschiedliche Benutzer ausgeführt werden, zeigt die Bitgröße des Prozesses an.) Sie können die Ausführbarkeit des Prozesses mit genau erratenps -o comm=
und imPATH
nachschlagen, aber achten Sie darauf, dass der Prozess ausgeführt wird wurde möglicherweise mit einer anderenPATH
Version gestartet oder hat diese möglicherweise umgeschriebenargv[0]
. Anschließend können Sie die ausführbare Datei analysieren. Wenn Sie bereit sind, ELF anzunehmen, sehen Sie sich das 5. Byte an .quelle
vsyscall
Karte immer die höchste ist, könnten Sie mit nur Ändern weghead
zutail
- was leider nicht funktionieren , weil proc nicht implementiertseek(2)
, so wird es etwas hässlicher sein, wieawk /proc/self/maps -- 'END { print substr($1, 0, 9); }'