如何测试 Linux 二进制文件是否被编译为位置无关代码?

如何测试 Linux 二进制文件是否被编译为位置无关代码?

我最近了解到(至少在 Fedora 和 Red Hat Enterprise Linux 上),编译为位置独立可执行文件(PIE)的可执行程序会获得更强的地址空间随机化(ASLR)保护。

那么:如何在 Linux 上测试特定可执行文件是否被编译为位置无关可执行文件?

答案1

您可以使用包perl中包含的脚本hardening-check在 Fedora 中可用德班(作为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

答案2

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 信息后打印的不同类型。

答案3

file5.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_PIEELF 元数据,但由于实现中的错误,它实际上破坏了一些东西,并将 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 运行可执行文件两次并查看 ASLR

您可以做的一件非常直接的事情是通过 GDB 运行可执行文件两次,看看地址是否因 ASLR 而在运行过程中发生变化。

我已在以下位置详细解释了如何执行此操作:https://stackoverflow.com/questions/2463150/what-is-the-fpie-option-for-position-independent-executables-in-gcc-and-ld/51308031#51308031

虽然这不一定是最实用的解决方案,并且如果您不信任可执行文件也是不可能的,但它很有趣,并且它执行了我们真正关心的最终检查,即 Linux 内核/动态加载器是否更改了可执行文件位置或不是。

答案4

有bash脚本Github 上的 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

相关内容