Bir Linux binary pozisyon bağımsız kod olarak derlenmiş olup olmadığını sınama nasıl?


38

Yakın zamanda öğrendim (en azından Fedora ve Red Hat Enterprise Linux'ta), Position Independent Executables (PIE) olarak derlenen çalıştırılabilir programların daha güçlü adres alanı rasgele (ASLR) koruması aldığını öğrendim.

Öyleyse: Linux'ta belirli bir yürütülebilir dosyanın Konum Bağımsız Çalıştırılabilir olarak derlenip derlenmediğini nasıl test ederim?


1
32 bit hakkında emin değilim, ancak x86_64 kodunda varsayılan olarak konum bağımsızdır . Ve tabii ki tüm sistem paketleri bu şekilde her iki kemerde de derlenir.
Michael Hampton

1
@ MichaelHampton, bunun doğru olduğunu sanmıyorum. (Yürütülebilir bir ikili dosya ile paylaşılan bir kütüphane arasındaki farka dikkat edin; ifadeniz paylaşılan kütüphaneler için doğru olabilir, ancak çalıştırılabilir dosyalar için doğru olduğunu düşünmüyorum.) X86_64'te bile, ikili dosyalar varsayılan olarak PIE görünmüyor. Sadece küçük bir test programı yazdım ve x86_64'de PIE olarak derlenmedi. -pie -fpieBir programı PIE olarak derlemek için özel derleyici bayraklarını geçmeniz gerektiğini düşünüyorum . Bu bağlantı başka ilginç bilgilere de sahipti - teşekkürler!
DW

1
Bu adamın algılama için bash betiği var: blog.fpmurphy.com/2008/06/position-independent-executables.html
CMCDragonkai

Yanıtlar:


32

Pakette bulunan ve Fedora ve Debian (as ) 'da mevcut olan perlbetiği kullanabilirsiniz . Derleme bayraklarının kontrol edildiği detaylar için bu Debian wiki sayfasını okuyun . Debian'a özgüdür, ancak teori Red Hat için de geçerlidir.hardening-checkhardening-includes

Örnek:

$ 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

Güzel cevap, Ubuntu 16.04 LTS ve muhtemelen diğer Ubuntu sürümleri için de geçerlidir. sudo apt-get install hardening-includesve sonra hardening-checkçalıştırılabilir perl betiği her zamanki PATH( /usr/bin/hardening-check); sadece bir nit: Cevaptan kaldırmak için önerin ./;-)
Dilettant

@ a25bedc5-3d09-41b8-82fb-ea6c353d75ae artık 17.10'da değil :-(
Ciro Santilli, 事件 改造 中心 法轮功 六四 事件 26:17 '

CentOS / RedHat'ta, bu paket epel deposunda mevcuttur
vikas027

@ a25bedc5-3d09-41b8-82fb-ea6c353d75ae Artık Ubuntu'da mevcut değil gibi görünüyor 18.04
Vadim Kotov

2
Bunu içeren debian paketi şimdi denir devscripts.
Tamás Szelei

15

readelf --relocsStatik veya dinamik kitaplığın x86-64'teki PIC olup olmadığını test etmek için kullanılır :

$ 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

Burada görüyoruz R_X86_64_32ve R_X86_64_32S. Bu, kodun bağımsız pozisyon olmadığı anlamına gelir. -FPIC ile bir kütüphaneyi yeniden kurduğumda şunu alıyorum:

$ 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

Bu yöntem muhtemelen çalıştırılabilirler için işe yarayabilir, ancak ben bu şekilde kullanmadım.


8
Bir astarın çıktısını nasıl yorumlayacağınızı açıklar mısınız? Paylaşılan kütüphaneyi PIC olmayan PIC olarak sınıflandırmak için kullanılacak ölçütler nelerdir?
DW

Eğer bir yürütülebilir inşa ederse -fPIE -no-pie, her zaman buna rağmen aynı adreste yüklenmiş olacaktır olabilir bir PIE çalıştırılabilir olarak bağlantılı olmuştur. Kullanın file a.outve arayın ELF executable(PIE dışı) ve ELF paylaşılan nesnesi (PIE): x86-64 Linux'ta artık 32 bit mutlak adreslere izin verilmiyor mu?
Peter Cordes

12

Sadece ikilide kullanın file:

$ 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

LSB bilgilerinden sonra yazdırılan farklı tipe dikkat edin.


1
PIE / ASLR ile derlendiğinde bu nasıl görünür?
Baruch

3
Pastadan çıktı ve pastadan çıktılar arasındaki tek fark executableve shared object. Paylaşılan nesnelerin yer değiştirebilir olması gerektiğini düşünüyorum, bu nedenle fikrimi PIE ile derledim.
Richard Braganza,

Evet, PIE çalıştırılabilir dosyaları ELF paylaşılan nesneleridir; ASLR'yi çalıştırılabilirler için uygulamanın en kolay yolu, dinamik bağlantıdaki mevcut desteği ve paylaşılan bir nesnede ELF giriş noktasını kullanmaktı. Ayrıca bkz. 32 bit mutlak adresler artık x86-64 Linux'ta izin vermiyor mu? PIE'yi kontrol eden gcc seçenekleri hakkında daha fazla bilgi için, bu gcc -fPIE -pieşimdi birçok dağıtımda varsayılandır.
Peter Cordes

Dosyanın daha yeni sürümleri açıkça belirtilir: örneğin, GNU / Linux için ELF 64-bit LSB pastası çalıştırılabilir, x86-64, sürüm 1 (SYSV), dinamik olarak bağlanmış, tercüman / lib64/ld-linux-x86-64.so.2 3.2.0, BuildID [sha1] = 9b502fd78165cb04aec34c3f046c1ba808365a96, soyuldu
Brian Minton

1
@PeterCordes, 5.36'nın fileşimdi DT_1_PIEbayraklarını temel alarak PIE'yi gerçekten tanıyabildiğini DT_FLAGS_1ve pie executablebunun yerine açıkça yazdığını söylüyor shared object.
Ciro Santilli 事件 事件 中心 事件 六四 事件

8

file 5.36 açıkça söylüyor

file5.36, çalıştırılabilir PIE ise veya yoksa, net bir şekilde yazdırır. Örneğin, bir PIE yürütülebilir dosyası aşağıdakileri gösterir:

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

ve PIE olmayan biri:

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

Bu özellik 5.33'te tanıtıldı ancak sadece basit bir chmod +xkontrol yaptı. Bundan önce shared objectPIE için basıldı .

5.34'te daha uzmanlaşmış olan DF_1_PIEELF meta verilerini kontrol etmeye başlamak gerekiyordu , ancak uygulamadaki bir hata nedeniyle gerçekte bir şeyleri kırdı ve GCC PIE çalıştırılabilirleri gösterdi shared objects.

fileHata kodunu içeren kaynak kodunu yorumladım ve tam olarak hangi ELF formatının bayt olarak kontrol ettiğini inceledim: https://stackoverflow.com/questions/34519521/why-does-gcc-create-a-shared-object -instead-of-the bir-yürütülebilir ikili-göre yapılır / 55704865 # 55704865

5.36 davranışının hızlı bir özeti:

  • Eğer Elf32_Ehdr.e_type == ET_EXEC
    • yazdırmak executable
  • aksi takdirde Elf32_Ehdr.e_type == ET_DYN
    • Eğer DT_FLAGS_1dinamik bölümü girişi mevcut olduğu
      • eğer DF_1_PIEayarlanır DT_FLAGS_1:
        • yazdırmak pie executable
      • Başka
        • yazdırmak shared object
    • Başka
      • dosya kullanıcı, grup veya başkaları tarafından yürütülebilir ise
        • yazdırmak pie executable
      • Başka
        • yazdırmak shared object

GDB çalıştırılabilir dosyayı iki kez çalıştırıyor ve ASLR'yi görüyor

Yapabileceğiniz çok doğrudan bir şey yürütülebilir dosyayı GDB aracılığıyla iki kez çalıştırmak ve adresin ASLR nedeniyle değişip değişmediğini görmek.

Bunun nasıl yapıldığını ayrıntılı olarak açıkladım: https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and-ld/51308031 # 51308031

Bu zorunlu olarak en pratik çözüm olmasa ve çalıştırılabilir dosyaya güvenmiyorsanız mümkün olmasa da eğlencelidir ve Linux çekirdeği / dinamik yükleyici çalıştırılabilir konumunu değiştiriyorsa ya da gerçekten umursadığımızı kontrol eder. değil.


1
"Çalışmalar arasındaki ana değişikliklerin adresi" - Bu saf PIE'nin etkisi değildir, PIE'dir ve ASLR'nin etkinleştirilmesidir. Evet, neredeyse her yerde etkin, ancak ASLR adresi devre dışı olan makineler için her iki seferde aynı olacaktır. ASLR genel olarak etkinleştirilebilir ancak setarch -R man7.org/linux/man-pages/man8/setarch.8.html "ile -R, --addr-no-randomize devre dışı bırakılabilir " Sanal adres alanının rastgele dağıtılmasını devre dışı bırakır ADDR_NO_RANDOMIZE. " man7.org/linux/man-pages/man2/personality.2.html " ADDR_NO_RANDOMIZE(Linux 2.6.12'den beri) Bu bayrak ayarlanmışken, adres-yer düzeni rastgele seçimini devre dışı bırakın ."
osgx

2

Yürütülebilir azaltma özelliklerini (RELRO, Yığın Kanaryası, NX bit, PIE, RPATH, RUNPATH, Fortify Source dahil) kontrol etmek için Github'da bash betiği checksec.sh vardır .

(Dosya girişi) argümanları checksecile çalıştırın -f:

$ 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.