web-dev-qa-db-ja.com

Linuxバイナリが位置独立コードとしてコンパイルされたかどうかをテストするにはどうすればよいですか?

私は最近(少なくともFedoraとRed Hat Enterprise Linuxでは)、位置独立実行可能ファイル(PIE)としてコンパイルされた実行可能プログラムが、より強力なアドレス空間ランダム化(ASLR)保護を受け取ることを学びました。

それで、Linuxで特定の実行可能ファイルが位置独立実行可能ファイルとしてコンパイルされたかどうかをテストするにはどうすればよいですか?

42
D.W.

hardening-checkパッケージに含まれるPerlスクリプト、 Fedoraで使用可能 および Debian を使用できます(hardening-includesとして)。チェックされるコンパイルフラグの詳細については、この Debian wikiページ をお読みください。これは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
33
dawud

readelf --relocs静的ライブラリまたは動的ライブラリがx86-64上のPICかどうかを次の方法でテストします。

$ 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

この方法はおそらく実行可能ファイルに対して機能する可能性がありますが、私はそのように使用していません。

15
user2387

バイナリで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情報の後に印刷されている別のタイプに注意してください。

15
p5yx

file 5.36はそれをはっきり言っています

file 5.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チェックのみを行いました。その前に、PIEのshared objectを出力しました。

5.34では、より専門的なDF_1_PIE ELFメタデータのチェックを開始するためのものでしたが、実装のバグにより、実際に問題が発生し、GCC PIE実行可能ファイルがshared objectsとして表示されました。

バグを含むfileソースコードを解釈し、ELF形式のどのバイトを詳細にチェックするか https://stackoverflow.com/questions/34519521/why-does -gcc-create-a-shared-object-instead-of-an-executable-binary-according-to/55704865#55704865

ファイル5.36の動作の概要は次のとおりです。

  • if Elf32_Ehdr.e_type == ET_EXEC
    • 印刷executable
  • それ以外の場合はElf32_Ehdr.e_type == ET_DYN
    • DT_FLAGS_1動的セクションエントリが存在する場合
      • DF_1_PIEDT_FLAGS_1に設定されている場合:
        • 印刷pie executable
      • そうしないと
        • 印刷shared object
    • そうしないと
      • ファイルがユーザー、グループ、その他によって実行可能である場合
        • 印刷pie executable
      • そうしないと
        • 印刷shared object

GDBは実行可能ファイルを2回実行し、ASLRを表示します

実行できる非常に直接的なことの1つは、実行可能ファイルをGDBで2回実行し、ASLRが原因で実行全体でアドレスが変化するかどうかを確認することです。

その方法を詳しく説明しました: https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and -ld/51308031#51308031

これは必ずしも最も実用的な解決策ではなく、実行可能ファイルを信頼できない場合は不可能ですが、それは楽しいものであり、Linuxカーネル/ダイナミックローダーが実行可能ファイルの場所を変更するかどうかなど、私たちが本当に気にかけている最終的なチェックを行いますない。

実行可能ファイルの軽減プロパティ(RELRO、スタックカナリー、NXビット、PIE、RPATH、RUNPATH、Fortifyソースなど)をチェックするbashスクリプト Githubのchecksec.sh があります。

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
3
Sourc7