Làm cách nào để kiểm tra xem tệp nhị phân Linux có được biên dịch thành mã độc lập vị trí không?


38

Gần đây tôi đã biết rằng (ít nhất là trên Fedora và Red Hat Enterprise Linux), các chương trình thực thi được biên dịch dưới dạng Thực thi độc lập vị trí (PIE) nhận được sự bảo vệ ngẫu nhiên không gian địa chỉ (ASLR) mạnh hơn.

Vậy: Làm cách nào để kiểm tra xem một tệp thực thi cụ thể có được biên dịch dưới dạng Thực thi độc lập vị trí trên Linux không?


1
Không chắc chắn về 32-bit, nhưng trên mã x86_64 là vị trí độc lập theo mặc định . Và tất nhiên tất cả các gói hệ thống được biên dịch theo cách này trên một trong hai vòm.
Michael Hampton

1
@MichaelHampton, tôi không nghĩ điều đó đúng. (Hãy cẩn thận về sự khác biệt giữa thư viện nhị phân thực thi và thư viện dùng chung; câu lệnh của bạn có thể phù hợp với thư viện dùng chung, nhưng tôi không nghĩ nó phù hợp với tệp thực thi.) Tôi vừa viết một chương trình thử nghiệm nhỏ, và trên x86_64, nó không được biên dịch thành PIE. Tôi nghĩ bạn phải vượt qua các -pie -fpiecờ biên dịch đặc biệt để biên dịch chương trình dưới dạng PIE. Liên kết đó có thông tin thú vị khác, mặc dù - cảm ơn bạn!
DW

1
Anh chàng này có một tập lệnh bash để phát hiện: blog.fpmurphy.com/2008/06/poseition-indeperee-executables.html
CMCDragonkai

Câu trả lời:


32

Bạn có thể sử dụng perltập lệnh có trong hardening-checkgói, có sẵn trong FedoraDebian (dưới dạng hardening-includes). Đọc trang wiki Debian này để biết chi tiết về những cờ biên dịch nào được kiểm tra. Đó là Debian cụ thể, nhưng lý thuyết cũng áp dụng cho Red Hat.

Thí dụ:

$ 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

Câu trả lời hay, cũng có thể áp dụng cho Ubuntu 16.04 LTS và có thể các phiên bản Ubuntu khác. sudo apt-get install hardening-includesvà sau đó hardening-checktập lệnh perl thực thi có sẵn trên thông thường PATH( /usr/bin/hardening-check); chỉ là một nit: Đề nghị xóa ./câu trả lời ;-)
Dilettant

@ a25bedc5-3d09-41b8-82fb-ea6c353d75ae không còn trong 17.10 nữa :-(
Ciro Santilli 改造

Trong CentOS / RedHat, gói này có sẵn trong EPEL kho
vikas027

@ a25bedc5-3d09-41b8-82fb-ea6c353d75ae Hình như nó không còn có sẵn trong Ubuntu 18.04
Vadim Kotov

2
Gói debian chứa cái này bây giờ được gọi devscripts.
Tamás Szelei

15

Tôi đã sử dụng readelf --relocsđể kiểm tra xem thư viện tĩnh hay động là PIC trên x86-64 theo cách sau:

$ 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

Chúng tôi thấy ở đây R_X86_64_32R_X86_64_32S. Điều này có nghĩa là mã không độc lập với vị trí. Khi tôi xây dựng lại một thư viện với -fPIC, tôi nhận được:

$ 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

Phương pháp này có thể hoạt động cho các tệp thực thi, nhưng tôi chưa sử dụng theo cách đó.


8
Bạn có quan tâm để giải thích làm thế nào để giải thích đầu ra của một-liner? Các tiêu chí để sử dụng để phân loại thư viện chia sẻ là PIC và không phải PIC là gì?
DW

Nếu bạn đã xây dựng một tệp thực thi với -fPIE -no-pie, nó sẽ luôn được tải tại cùng một địa chỉ mặc dù nó có thể được liên kết dưới dạng thực thi PIE. Sử dụng file a.outvà tìm kiếm ELF executable(không phải PIE) so với đối tượng chia sẻ ELF` (PIE): Địa chỉ tuyệt đối 32 bit không còn được phép trong x86-64 Linux?
Peter Cordes

12

Chỉ cần sử dụng filetrên nhị phân:

$ 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

Lưu ý các loại khác nhau được in sau thông tin LSB.


1
Làm thế nào điều này hiển thị nếu được biên dịch với PIE / ASLR?
Baruch

3
Sự khác biệt duy nhất giữa các đầu ra từ pie-off và pie.on là executableshared object. Tôi cho rằng các đối tượng được chia sẻ cần phải được định vị lại do đó trong tâm trí tôi đã được biên dịch bằng PIE.
Richard Braganza

Yup, PIE thực thi là các đối tượng chia sẻ ELF; cách dễ nhất để thực hiện ASLR cho các tệp thực thi là sử dụng hỗ trợ hiện có trong trình liên kết động cho và điểm nhập ELF trong một đối tượng được chia sẻ. Xem thêm địa chỉ tuyệt đối 32 bit không còn được phép trong x86-64 Linux? để biết thêm về các tùy chọn gcc kiểm soát PIE và gcc -fPIE -piehiện tại đó là mặc định trên nhiều bản phát hành.
Peter Cordes

Các phiên bản mới hơn của tệp đề cập rõ ràng đến chiếc bánh: ví dụ ELF 64-bit LSB có thể thực thi, x86-64, phiên bản 1 (SYSV), được liên kết động, trình thông dịch /lib64/ld-linux-x86-64.so.2, cho GNU / Linux 3.2.0, BuildID [sha1] = 9b502fd78165cb04aec34c3f046c1ba808365a96, bị tước
Brian Minton

1
@PeterCordes lưu ý rằng file5.36 bây giờ thực sự có thể nhận ra PIE-ness dựa trên DT_1_PIEcờ của DT_FLAGS_1và nói rõ ràng pie executablethay vì shared object.
Ciro Santilli 心 心

8

file 5,36 nói rõ ràng

file5.36 thực sự in nó rõ ràng nếu thực thi là PIE hay không. Ví dụ, một tệp thực thi PIE hiển thị như:

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

và một người không PIE như:

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

Tính năng này được giới thiệu vào 5.33 nhưng nó chỉ là một chmod +xkiểm tra đơn giản . Trước đó nó chỉ in shared objectcho PIE.

Trong 5.34, nó có nghĩa là bắt đầu kiểm tra DF_1_PIEsiêu dữ liệu ELF chuyên dụng hơn , nhưng do lỗi trong quá trình triển khai, nó thực sự đã phá vỡ mọi thứ và hiển thị các tệp thực thi GCC PIE như shared objects.

Tôi đã giải thích filemã nguồn, bao gồm cả lỗi và chính xác các byte của định dạng ELF mà nó kiểm tra chi tiết rõ ràng tại: https://stackoverflow.com/questions/34519521/why-does-gcc-create-a- Shared-object -instead-of-an-execable-binary-theo / 55704865 # 55704865

Tóm tắt nhanh về hành vi của tệp 5.36 là:

  • nếu Elf32_Ehdr.e_type == ET_EXEC
    • in executable
  • khác nếu Elf32_Ehdr.e_type == ET_DYN
    • nếu DT_FLAGS_1mục động phần là hiện tại
      • nếu DF_1_PIEđược đặt trong DT_FLAGS_1:
        • in pie executable
      • khác
        • in shared object
    • khác
      • nếu tập tin được thực thi bởi người dùng, nhóm hoặc người khác
        • in pie executable
      • khác
        • in shared object

GDB chạy thực thi hai lần và xem ASLR

Một điều rất trực tiếp mà bạn có thể làm là chạy hai lần thực thi thông qua GDB và xem liệu địa chỉ có thay đổi trong các lần chạy do ASLR không.

Tôi đã giải thích cách thực hiện điều đó một cách chi tiết tại: https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-poseition-indeperee-executables-in-gcc-and-ld/51308031 # 51308031

Mặc dù đây không nhất thiết là giải pháp thiết thực nhất và không thể thực hiện được nếu bạn không tin tưởng vào khả năng thực thi, nhưng thật thú vị và đó là kiểm tra cuối cùng mà chúng tôi thực sự quan tâm, đó là nếu hạt nhân / trình tải động của Linux thay đổi vị trí thực thi hay không phải.


1
"Địa chỉ của những thay đổi chính giữa các lần chạy" - đây không phải là hiệu ứng của PIE thuần túy, đó là PIE và kích hoạt ASLR. Có, hầu như mọi nơi đều được bật, nhưng đối với các máy có địa chỉ ASLR bị vô hiệu hóa sẽ giống nhau cả hai lần. ASLR có thể được bật trên toàn cầu nhưng bị vô hiệu hóa với setarch -R man7.org/linux/man-pages/man8/setarch.8.html " -R, --addr-no-randomize Vô hiệu hóa ngẫu nhiên không gian địa chỉ ảo. Bật ADDR_NO_RANDOMIZE." man7.org/linux/man-pages/man2/personality.2.html " ADDR_NO_RANDOMIZE(kể từ Linux 2.6.12) Với bộ cờ này, vô hiệu hóa ngẫu nhiên bố cục không gian địa chỉ."
osgx

2

Có bash script testsec.sh trên Github để kiểm tra các thuộc tính giảm thiểu thực thi (bao gồm cả RELRO, Stack Canary, NX bit, PIE, RPATH, RUNPATH, Fortify Source).

Chạy checksecvới các -fđối số (nhập tệp):

$ 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.