J'ai récemment appris que (au moins sur Fedora et Red Hat Enterprise Linux), les programmes exécutables qui sont compilés en tant que PIE (Position Independent Executables) bénéficient d'une meilleure protection contre la randomisation de l'espace d'adressage (ASLR).
Donc: comment tester si un exécutable particulier a été compilé en tant qu'exécutable indépendant de position, sous Linux?
Vous pouvez utiliser le script Perl
contenu dans le hardening-check
package, disponible dans Fedora et Debian (comme hardening-includes
). Lisez ceci page wiki Debian pour plus de détails sur les drapeaux de compilation qui sont vérifiés. C'est spécifique à Debian, mais la théorie s'applique également à Red Hat.
Exemple:
$ 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
J'ai utilisé readelf --relocs
pour tester si la bibliothèque statique ou dynamique est PIC sur x86-64 de la manière suivante:
$ 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
On voit ici R_X86_64_32
et R_X86_64_32S
. Cela signifie que le code n'est pas indépendant de la position. Lorsque je reconstruis une bibliothèque avec -fPIC, j'obtiens:
$ 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
Cette méthode peut probablement fonctionner pour les exécutables, mais je ne l'ai pas utilisée de cette façon.
Utilisez simplement file
sur le binaire:
$ 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
Notez les différents types imprimés après les informations LSB.
file
5.36 le dit clairement
file
5.36 l'affiche clairement si l'exécutable est PIE ou non. Par exemple, un exécutable PIE s'affiche comme suit:
main.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, not stripped
et un non-TARTE comme:
main.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
La fonctionnalité a été introduite dans la version 5.33, mais elle a simplement fait chmod +x
vérifier. Avant cela, il vient d'imprimer shared object
pour PIE.
En 5.34, il était censé commencer à vérifier le _ plus spécialisé DF_1_PIE
Métadonnées ELF, mais en raison d'un bogue dans l'implémentation, elles ont en fait cassé les choses et montré les exécutables GCC PIE comme shared objects
.
J'ai interprété le code source de file
, y compris le bogue, et exactement les octets du format ELF qu'il vérifie en détails atroces sur: https://stackoverflow.com/questions/34519521/why-does -gcc-créer-un-objet-partagé-au-lieu-d'un-exécutable-binaire-selon/55704865 # 55704865
Voici un bref résumé du comportement du fichier 5.36:
Elf32_Ehdr.e_type == ET_EXEC
executable
Elf32_Ehdr.e_type == ET_DYN
DT_FLAGS_1
l'entrée de section dynamique est présente DF_1_PIE
est défini dans DT_FLAGS_1
: pie executable
shared object
pie executable
shared object
GDB exécute l'exécutable deux fois et voit ASLR
Une chose très directe que vous pouvez faire est d'exécuter l'exécutable deux fois via GDB et de voir si l'adresse change à travers les exécutions en raison de ASLR.
J'ai expliqué comment le faire en détail sur: https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and -ld/51308031 # 51308031
Bien que ce ne soit pas nécessairement la solution la plus pratique et impossible si vous ne faites pas confiance à l'exécutable, c'est amusant et il fait la vérification ultime qui nous tient vraiment à cœur, à savoir si le noyau Linux/chargeur dynamique change l'emplacement de l'exécutable ou ne pas.
Il y a un script bash checksec.sh sur Github pour vérifier les propriétés d'atténuation des exécutables (y compris RELRO, Stack Canary, bit NX, PIE, RPATH, RUNPATH, Fortify Source).
Exécutez checksec
avec -f
(entrée de fichier) arguments:
$ 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