怎样判定一个可执行文件是否是PIE 格式的文件

/* ****************************************************    
    author: hjjdebug
    date:      2023年 10月 10日 星期二 11:03:52 CST
    description: 怎样判定可执行文件是否是PIE格式文件
*******************************************************/

PIE: Position Independent Executable, 位置无关可执行文件.

表示可以把执行文件加载到任意位置都可执行.

执行文件是PIE 需要两个条件:
1. 其文件头类型是 DYN 类型
2. 其动态节中有 DEBUG 符号名存在

随便找一个我们自己编译的可执行文件,查看其文件头(file header)
$ readelf -h multiview
ELF 头:
  Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
  类别:                              ELF64
  数据:                              2 补码,小端序 (little endian)
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI 版本:                          0
  类型:                              EXEC (可执行文件)  // 该行说明此文件不是PIE 格式文件,而是一般的EXEC文件
  系统架构:                          Advanced Micro Devices X86-64
  版本:                              0x1
  入口点地址:               0x431070
  程序头起点:          64 (bytes into file)
  Start of section headers:          20939056 (bytes into file)
  标志:             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         11
  Size of section headers:           64 (bytes)
  Number of section headers:         40
  Section header string table index: 39

找一个PIE 格式文件,例如 /bin/ls 文件,

查看其文件头: (改成英文输出了,怎样修改参考符录)
$ readelf -h /bin/ls
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)   // PIE 格式文件肯定是DYN 类型的
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x67d0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          140224 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

查看其动态节
$ readelf -d /bin/ls

Dynamic section at offset 0x21a58 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libselinux.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x4000
 0x000000000000000d (FINI)               0x17574
 0x0000000000000019 (INIT_ARRAY)         0x22010
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x22018
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x3a0
 0x0000000000000005 (STRTAB)             0x1190
 0x0000000000000006 (SYMTAB)             0x488
 0x000000000000000a (STRSZ)              1612 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0                 // PIE 格式文件动态节中包含DEBUG 符
 0x0000000000000003 (PLTGOT)             0x22c58
 0x0000000000000002 (PLTRELSZ)           2544 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x2cb8
 0x0000000000000007 (RELA)               0x1968
 0x0000000000000008 (RELASZ)             4944 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW PIE
 0x000000006ffffffe (VERNEED)            0x18f8
 0x000000006fffffff (VERNEEDNUM)         1
 0x000000006ffffff0 (VERSYM)             0x17dc
 0x000000006ffffff9 (RELACOUNT)          193
 0x0000000000000000 (NULL)               0x0

附录:  命令行下,怎样把中文输出改成英文输出?
中文有一目了然的感觉, 但不适合某些脚本操作. 所以有时候还是要换成英文.
按以下3步操作. (在ubuntu20 下操作的), 改动只需要一处.
查看locale, 修改LANGUAGE,验证输出

1. 查看locale,
$ locale
LANG=zh_CN.UTF-8
LANGUAGE=zh_CN:en
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC=zh_CN.UTF-8
LC_TIME=zh_CN.UTF-8
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY=zh_CN.UTF-8
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER=zh_CN.UTF-8
LC_NAME=zh_CN.UTF-8
LC_ADDRESS=zh_CN.UTF-8
LC_TELEPHONE=zh_CN.UTF-8
LC_MEASUREMENT=zh_CN.UTF-8
LC_IDENTIFICATION=zh_CN.UTF-8
LC_ALL=


2. 修改语言环境变量, 采用英文输出, 仅这里是需要修改的.
$ LANGUAGE=en_US

3. 重新查看执行文件信息, 已经按英文输出了,如下:
$ readelf -h multiview
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI Version:                       0
  Type:                              EXEC (Executable file)  // 指示它是可运行文件, 不是PIE 形式
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x431070
  Start of program headers:          64 (bytes into file)
  Start of section headers:          20939056 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         11
  Size of section headers:           64 (bytes)
  Number of section headers:         40
  Section header string table index: 39

你可能感兴趣的:(文件及文件系统相关,PIE)