Як перевірити, чи був компільований бінарний код Linux як незалежний від позиції код?


38

Нещодавно я дізнався, що (принаймні на Fedora та Red Hat Enterprise Linux) виконувані програми, складені як незалежні від позиції виконавчі файли (PIE), отримують більш сильний захист від рандомізації адресного простору (ASLR).

Отже: Як перевірити, чи був певний виконуваний файл складений як незалежний від позиції виконуваний файл в Linux?


1
Не впевнений у 32-розрядному, але на x86_64 код за замовчуванням не залежить від позиції . І звичайно, всі системні пакети складаються таким чином на будь-якій арці.
Майкл Хемптон

1
@MichaelHampton, я не думаю, що це правильно. (Будьте уважні до різниці між виконуваною бінарною та спільною бібліотекою; ваш вислів може бути правильним для спільних бібліотек, але я не думаю, що це підходить для виконуваних файлів.) Навіть на x86_64 бінарні файли не є PIE за замовчуванням. Я лише написав невелику тестову програму, і на x86_64 вона не була складена як PIE. Я думаю, що вам потрібно передавати -pie -fpieспеціальні прапори компілятора, щоб скласти програму як PIE. Хоча ця посилання мала й іншу цікаву інформацію - дякую!
DW

1
У цього хлопця є сценарій bash для виявлення: blog.fpmurphy.com/2008/06/position-independent-executables.html
CMCDragonkai

Відповіді:


32

Ви можете використовувати perlскрипт, що міститься в hardening-checkпакеті, доступний у Fedora та Debian (як hardening-includes). Прочитайте цю сторінку вікі Debian, щоб отримати детальну інформацію про те, які прапорці компіляції перевіряються. Це специфічно для Debian, але ця теорія стосується і Red Hat.

Приклад:

$ 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

Приємна відповідь, застосовна також до Ubuntu 16.04 LTS та, можливо, інших версій Ubuntu. sudo apt-get install hardening-includesі тоді hardening-checkвиконуваний скрипт perl доступний у звичайному PATH( /usr/bin/hardening-check); просто ніт: Запропонуйте зняти ./відповідь ;-)
Dilettant

@ a25bedc5-3d09-41b8-82fb-ea6c353d75ae вже не о 17.10 :-(
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

У CentOS / RedHat цей пакет доступний у сховищі epel
vikas027,

@ a25bedc5-3d09-41b8-82fb-ea6c353d75ae Схоже, він більше не доступний в Ubuntu 18.04
Вадим Котов

2
Тепер пакет debian, який містить це, називається devscripts.
Tamás Szelei

15

Я використовував readelf --relocsдля перевірки того, чи є статична або динамічна бібліотека PIC на x86-64 наступним чином:

$ 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

Ми бачимо тут R_X86_64_32і R_X86_64_32S. Це означає, що код не залежить від позиції. Коли я відновлюю бібліотеку з -fPIC, я отримую:

$ 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

Цей метод, можливо, може працювати для виконуваних файлів, але я не використовував його таким чином.


8
Чи не хотіли б ви пояснити, як інтерпретувати вихід цього одноклапника? Які критерії використовувати для класифікації спільної бібліотеки як PIC та non-PIC?
DW

Якщо ви створили виконуваний файл -fPIE -no-pie, він завжди буде завантажений за тією самою адресою, хоча він міг би бути пов'язаний як виконуваний файл PIE. Використовуйте file a.outта шукайте ELF executable(не-PIE) та ELF-спільний об’єкт` (PIE): 32-бітні абсолютні адреси більше не дозволені в x86-64 Linux?
Пітер Кордес

12

Просто використовуйте 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.


1
Як це відображається, якщо складено з PIE / ASLR?
Барух

3
Єдиною різницею між виходами від pie-off та pie.on є executableі shared object. Я припускаю, що спільні об'єкти потрібно пересувати, отже, на мій погляд, було складено з PIE.
Річард Браганса

Так, виконувані файли PIE - це спільні об'єкти ELF; найпростішим способом реалізації ASLR для виконуваних файлів було використання наявної підтримки в динамічному лінкері для та точки входу ELF у спільний об'єкт. Дивіться також 32-бітні абсолютні адреси, більше не дозволені в Linux x86-64? Докладніше про параметри gcc, які керують PIE, і gcc -fPIE -pieце тепер за замовчуванням у багатьох дистрибутивах.
Пітер Кордес

Новіші версії файлу явно згадують пиріг: наприклад, 64-розрядний керований пиріг LF ELF, x86-64, версія 1 (SYSV), динамічно пов'язаний, інтерпретатор /lib64/ld-linux-x86-64.so.2, для GNU / Linux 3.2.0, BuildID [sha1] = 9b502fd78165cb04aec34c3f046c1ba808365a96, позбавлений
Брайан Мінтон

1
@PeterCordes відзначають, що file5.36 тепер може фактично розпізнати PIE-ность на основі DT_1_PIEпрапора DT_FLAGS_1, і чітко говорить pie executableзамість shared object.
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

8

file 5.36 це чітко сказано

file5.36 насправді чітко друкується, чи виконується файл PIE чи ні. Наприклад, виконуваний файл PIE показує:

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

а не PIE як:

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

Ця функція була введена в 5.33, але вона зробила лише просту chmod +xперевірку. До цього його просто надрукували shared objectдля PIE.

У 5.34, передбачалося почати перевірку більш спеціалізованих DF_1_PIEметаданих ELF, але через помилку у впровадженні вони фактично зламали речі та показали виконувані файли GCC PIE як shared objects.

Я інтерпретував fileвихідний код, включаючи помилку, а також саме, які байти формату ELF він перевіряє з неприємними деталями за посиланням: https://stackoverflow.com/questions/34519521/why-does-gcc-create-a-shared-object -intead-of-an-исполняемого-бінарного-згідно / 55704865 # 55704865

Короткий підсумок поведінки файлу 5.36:

  • якщо Elf32_Ehdr.e_type == ET_EXEC
    • друк executable
  • інше якщо Elf32_Ehdr.e_type == ET_DYN
    • якщо DT_FLAGS_1присутній запис динамічного розділу
      • якщо DF_1_PIEвстановлено DT_FLAGS_1:
        • друк pie executable
      • ще
        • друк shared object
    • ще
      • якщо файл виконується користувачем, групою чи іншими
        • друк pie executable
      • ще
        • друк shared object

GDB запустіть виконуваний файл двічі і перегляньте ASLR

Одне дуже пряме, що ви можете зробити, це запустити виконуваний файл двічі через GDB і побачити, чи змінюється адреса через прогони через ASLR.

Я детально пояснив, як це зробити на веб- сайті: https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and-ld/51308031 # 51308031

Хоча це не обов'язково є найбільш практичним рішенням і неможливо, якщо ви не довіряєте виконуваному файлу, це цікаво, і це остаточно перевіряє, що нас дійсно цікавить, а це якщо ядро ​​Linux / динамічний завантажувач змінить місце виконання файлів або ні.


1
"адреса основних змін між прогонами" - це не ефект чистого PIE, це PIE та включений ASLR. Так, це майже будь-де ввімкнено, але для машин з вимкненою ASLR адресою буде однаково обидва рази. ASLR може бути включений у всьому світі, але відключений за допомогою setarch -R man7.org/linux/man-pages/man8/setarch.8.html " -R, --addr-no-randomize Вимикає рандомізацію віртуального адресного простору. Вмикається ADDR_NO_RANDOMIZE." man7.org/linux/man-pages/man2/personality.2.html " ADDR_NO_RANDOMIZE(з Linux 2.6.12) За допомогою цього набору прапор вимкніть рандомізацію макетів адресного простору."
osgx

2

У Github є bash script checksec.sh для перевірки властивостей пом'якшення виконуваних файлів (включаючи RELRO, Stack Canary, NX біт, PIE, RPATH, RUNPATH, Fortify Source).

Запустити checksecз -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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.