Wie kann man testen, ob eine Linux-Binärdatei als positionsunabhängiger Code kompiliert wurde?


38

Ich habe kürzlich erfahren, dass (zumindest unter Fedora und Red Hat Enterprise Linux) ausführbare Programme, die als Position Independent Executables (PIE) kompiliert wurden, einen stärkeren Schutz durch Adressraum-Randomisierung (ASLR) erhalten.

Also: Wie teste ich, ob eine bestimmte ausführbare Datei unter Linux als positionsunabhängige ausführbare Datei kompiliert wurde?


1
Ich bin mir nicht sicher, ob 32-Bit- Code auf x86_64 standardmäßig positionsunabhängig ist . Und natürlich werden alle Systempakete auf beiden Archiven auf diese Weise kompiliert.
Michael Hampton

1
@ MichaelHampton, ich glaube nicht, dass das stimmt. (Seien Sie vorsichtig mit dem Unterschied zwischen einer ausführbaren Binärdatei und einer gemeinsam genutzten Bibliothek. Ihre Aussage ist möglicherweise für gemeinsam genutzte Bibliotheken richtig, aber ich denke nicht, dass sie für ausführbare Dateien richtig ist.) Sogar auf x86_64 scheinen Binärdateien nicht standardmäßig PIE zu sein. Ich habe gerade ein kleines Testprogramm geschrieben und auf x86_64 wurde es nicht als PIE kompiliert. Ich denke, Sie müssen die -pie -fpiespeziellen Compiler-Flags übergeben, um ein Programm als PIE zu kompilieren. Dieser Link enthielt jedoch noch weitere interessante Informationen - danke!
DW

1
Dieser Typ hat ein Bash-Skript zur Erkennung: blog.fpmurphy.com/2008/06/position-independent-executables.html
CMCDragonkai

Antworten:


32

Sie können das perlim hardening-checkPaket enthaltene Skript verwenden , das in Fedora und Debian (als hardening-includes) verfügbar ist . Lesen Sie diese Debian-Wiki-Seite, um zu erfahren, welche Compile-Flags überprüft werden. Es ist Debian-spezifisch, aber die Theorie gilt auch für Red Hat.

Beispiel:

$ hardening-check $(which sshd)
/usr/sbin/sshd:
 Position Independent Executable: yes
 Stack protected: yes
 Fortify Source functions: yes (some protected functions found)
 Read-only relocations: yes
 Immediate binding: yes

Schöne Antwort, auch für Ubuntu 16.04 LTS und möglicherweise andere Ubuntu-Versionen. sudo apt-get install hardening-includesund dann ist das hardening-checkausführbare Perl-Skript auf dem usual PATH( /usr/bin/hardening-check) verfügbar ; nur nit: Schlagen Sie die entfernen , ./aus der Antwort ;-)
Dilettant

@ a25bedc5-3d09-41b8-82fb-ea6c353d75ae nicht mehr in 17.10 :-(
Ciro Santilli 新疆 新疆 法轮功 六四 六四 事件

In CentOS / RedHat ist dieses Paket im Epel- Repository verfügbar
vikas027

@ a25bedc5-3d09-41b8-82fb-ea6c353d75ae Es sieht so aus, als wäre es in Ubuntu 18.04
Vadim Kotov am

2
Das Debian-Paket, das dies enthält, heißt jetzt devscripts.
Tamás Szelei

15

Ich habe readelf --relocsauf folgende Weise getestet, ob es sich bei der statischen oder dynamischen Bibliothek um PIC auf x86-64 handelt:

$ readelf --relocs /usr/lib/gcc/x86_64-linux-gnu/4.6/libstdc++.a |\
      awk '$3~/^R_/ && $5!~/^\.debug/{print $3}' |sort -u
R_X86_64_32
R_X86_64_32S
R_X86_64_64
R_X86_64_DTPOFF32
R_X86_64_GOTPCREL
R_X86_64_PC32
R_X86_64_PLT32
R_X86_64_TLSLD
R_X86_64_TPOFF32

Wir sehen hier R_X86_64_32und R_X86_64_32S. Dies bedeutet, dass der Code nicht positionsunabhängig ist. Wenn ich eine Bibliothek mit -fPIC neu aufbaue, erhalte ich:

$ readelf --relocs libstdc++.a |\
      awk '$3~/^R_/ && $5!~/^\.debug/{print $3}' |sort -u
R_X86_64_64
R_X86_64_DTPOFF32
R_X86_64_GOTPCREL
R_X86_64_PC32
R_X86_64_PLT32
R_X86_64_TLSGD
R_X86_64_TLSLD

Diese Methode funktioniert möglicherweise für ausführbare Dateien, aber ich habe sie nicht so verwendet.


8
Möchten Sie erklären, wie die Ausgabe dieses Einzeilers zu interpretieren ist? Nach welchen Kriterien wird die gemeinsam genutzte Bibliothek als PIC gegenüber Nicht-PIC klassifiziert?
DW

Wenn Sie eine ausführbare Datei mit eingebauter -fPIE -no-pie, wäre es immer an der gleichen Adresse geladen werden , obwohl es könnte als PIE ausführbaren verknüpft wurde. Verwenden file a.outund suchen Sie nach ELF executable(Nicht-PIE) vs. ELF Shared Object (PIE): 32-Bit-Absolutadressen sind unter x86-64 Linux nicht mehr zulässig?
Peter Cordes

12

Verwenden Sie einfach fileauf der Binärdatei:

$ file ./pie-off
./pie-off: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=0dc3858e9f0334060bfebcbe3e854909191d8bdc, not stripped
$ file ./pie-on
./pie-on: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=962235df5bd188e1ec48c151ff61b6435d395f89, not stripped

Beachten Sie den anderen Typ, der nach den LSB-Informationen gedruckt wird.


1
Wie zeigt sich dies, wenn es mit PIE / ASLR kompiliert wurde?
Baruch

3
Der einzige Unterschied zwischen den Ausgängen von pie-off und pie.on sind executableund shared object. Ich gehe davon aus, dass freigegebene Objekte verlagerbar sein müssen, daher wurden sie meines Erachtens mit PIE kompiliert.
Richard Braganza

Ja, ausführbare PIE-Dateien sind gemeinsam genutzte ELF-Objekte. Die einfachste Möglichkeit, ASLR für ausführbare Dateien zu implementieren, bestand darin, die vorhandene Unterstützung im dynamischen Linker für einen ELF-Einstiegspunkt in einem gemeinsam genutzten Objekt zu verwenden. Siehe auch 32-Bit-Absolutadressen, die unter x86-64 Linux nicht mehr zulässig sind? Weitere gcc -fPIE -pieInformationen zu gcc-Optionen, die PIE steuern, sind in vielen Distributionen standardmäßig enthalten.
Peter Cordes

Neuere Versionen der Datei erwähnen ausdrücklich pie: zB ELF 64-Bit-LSB-pie-Programm, x86-64, Version 1 (SYSV), dynamisch verknüpft, Interpreter /lib64/ld-linux-x86-64.so.2 für GNU / Linux 3.2.0, BuildID [sha1] = 9b502fd78165cb04aec34c3f046c1ba808365a96, gestrippt
Brian Minton

1
@PeterCordes stellt fest, dass 5.36 filenun tatsächlich TORTE anhand der DT_1_PIEFlagge von erkennt DT_FLAGS_1und pie executablestattdessen deutlich sagt shared object.
Ciro Santilli am

8

file 5.36 sagt es deutlich

file5.36 gibt tatsächlich deutlich aus, ob es sich bei der ausführbaren Datei um PIE handelt oder nicht. Beispielsweise zeigt eine ausführbare PIE-Datei Folgendes:

main.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, not stripped

und eine Nicht-TORTE als:

main.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

Die Funktion wurde in 5.33 eingeführt, aber es wurde nur eine einfache chmod +xÜberprüfung durchgeführt. Davor wurde es nur shared objectfür PIE gedruckt .

In 5.34 sollte damit begonnen werden, die spezialisierteren DF_1_PIEELF-Metadaten zu überprüfen. Aufgrund eines Fehlers in der Implementierung wurden jedoch tatsächlich Fehler aufgetreten, und die ausführbaren Dateien von GCC PIE wurden als angezeigt shared objects.

Ich habe den fileQuellcode einschließlich des Fehlers und genau die Bytes des ELF-Formats interpretiert , die es in qualvollen Details überprüft: https://stackoverflow.com/questions/34519521/why-does-gcc-create-a-shared-object statt einer ausführbaren Binärdatei gemäß / 55704865 # 55704865

Eine kurze Zusammenfassung des Verhaltens von Datei 5.36 lautet:

  • ob Elf32_Ehdr.e_type == ET_EXEC
    • drucken executable
  • sonst wenn Elf32_Ehdr.e_type == ET_DYN
    • wenn ein DT_FLAGS_1dynamischer Abschnittseintrag vorhanden ist
      • wenn DF_1_PIEeingestellt ist in DT_FLAGS_1:
        • drucken pie executable
      • sonst
        • drucken shared object
    • sonst
      • Wenn die Datei von Benutzer, Gruppe oder anderen ausführbar ist
        • drucken pie executable
      • sonst
        • drucken shared object

GDB führt die ausführbare Datei zweimal aus und zeigt ASLR an

Eine sehr direkte Sache, die Sie tun können, ist, die ausführbare Datei zweimal über GDB auszuführen und zu prüfen, ob sich die Adresse aufgrund von ASLR zwischen den Ausführungen ändert.

Wie das geht, habe ich ausführlich erklärt unter: https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and-ld/51308031 # 51308031

Dies ist zwar nicht unbedingt die praktischste Lösung und nicht möglich, wenn Sie der ausführbaren Datei nicht vertrauen, aber es macht Spaß und führt die ultimative Überprüfung durch, die uns wirklich am Herzen liegt nicht.


1
"Adresse der Hauptänderungen zwischen den Läufen" - dies ist keine Auswirkung von reinem PIE, sondern von PIE und aktiviertem ASLR. Ja, es ist fast überall aktiviert, aber für Computer mit deaktivierter ASLR-Adresse ist die Adresse beide Male gleich. ASLR kann global aktiviert, aber mit setarch -R man7.org/linux/man-pages/man8/setarch.8.html deaktiviert werden. " -R, --addr-no-randomize Deaktiviert die Randomisierung des virtuellen Adressraums. Wird aktiviert ADDR_NO_RANDOMIZE." man7.org/linux/man-pages/man2/personality.2.html " ADDR_NO_RANDOMIZE(seit Linux 2.6.12) Deaktivieren Sie bei gesetztem Flag die Adressraum-Layout-Randomisierung."
Oslo

2

Es gibt ein Bash-Skript checksec.sh auf Github , um die Eigenschaften der ausführbaren Dateien zu überprüfen (einschließlich RELRO, Stack Canary, NX-Bit, PIE, RPATH, RUNPATH, Fortify Source).

Führen Sie checksecmit -f(Input - Datei) Argumente:

$ checksec -f /usr/bin/bash

RELRO           STACK CANARY      NX            PIE             RPATH     RUNPATH      FORTIFY Fortified Fortifiable
Full RELRO      Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH    YES      13        33
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.