私は最近(少なくともFedoraとRed Hat Enterprise Linuxでは)、位置独立実行可能ファイル(PIE)としてコンパイルされた実行可能プログラムが、より強力なアドレス空間ランダム化(ASLR)保護を受け取ることを学びました。
それで、Linuxで特定の実行可能ファイルが位置独立実行可能ファイルとしてコンパイルされたかどうかをテストするにはどうすればよいですか?
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
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
この方法はおそらく実行可能ファイルに対して機能する可能性がありますが、私はそのように使用していません。
バイナリで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情報の後に印刷されている別のタイプに注意してください。
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の動作の概要は次のとおりです。
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は実行可能ファイルを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