/* ****************************************************
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