为何readelf将ET_EXEC可执行文件识别为ET_DYN共享库?
嘿,这个问题其实挺普遍的——你遇到的情况不是编译器出问题了,而是现代Linux系统里的一个默认安全特性在起作用!
核心原因:默认生成PIE(位置独立可执行文件)
现在几乎所有主流Linux发行版的GCC/Clang编译器,都会默认生成**PIE(Position-Independent Executable)**格式的可执行文件。这类文件的ELF类型就是ET_DYN(和共享库一样),因为它和共享库采用了相同的位置独立代码技术,能被加载到内存的任意地址上。
这么做的目的是为了启用ASLR(地址空间布局随机化),这是一种重要的安全机制:通过随机化程序在内存中的加载地址,大幅降低缓冲区溢出、代码注入等攻击的成功率。
验证它确实是可执行文件
你可以用file命令来确认文件类型,比如运行:
file your_program
输出会明确标注它是pie executable,比如:
ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=xxxx, for GNU/Linux 3.2.0, not stripped
如何生成传统的ET_EXEC可执行文件
如果确实需要生成传统的、ELF类型为EXEC的可执行文件,只需要在编译时加上-no-pie参数即可:
gcc your_code.c -o your_program -no-pie
再用readelf -h查看,就能看到Type字段变成EXEC (Executable file)了。
为什么/bin目录下的工具也是ET_DYN?
现在大部分系统的系统级二进制文件(比如/bin/ls、/bin/cat)也都采用了PIE格式,因为安全性是当前系统的优先考虑项,所以它们的ELF类型同样是ET_DYN,但丝毫不影响它们作为可执行文件的功能。
内容的提问来源于stack exchange,提问作者Trey

