ELF文件的作用详解
1. 通过ELF文件可以做什么?
(1)获取编译选项和编译参数
ELF文件中不会直接存储完整的编译命令(如gcc -O2 -I/usr/include demo.c),但可以通过以下方式间接获取部分信息:
-  查看编译器版本和基础选项: 
 ELF文件的.comment节可能包含编译器版本信息。
 示例:readelf -p .comment demo # 查看编译器和链接器版本输出可能类似: GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
-  通过调试信息推测编译选项(需编译时添加 -g选项):
 调试信息中可能包含优化级别(如-O2)或宏定义(如-DDEBUG)。
 示例:objdump -g demo | grep "DW_AT_producer" # 查看编译器参数片段输出可能包含: DW_AT_producer : "GNU C17 9.3.0 -O2 -mtune=generic"
(2)查找ELF文件中的字符串
ELF的.rodata(只读数据)或.data节中可能包含硬编码的字符串(如日志信息、密钥)。
 工具:
-  使用 strings命令:strings demo | grep "error" # 查找包含"error"的字符串输出示例: error: invalid input!
-  直接查看 .rodata节:objdump -s -j .rodata demo # 显示.rodata节内容
(3)其他实用功能
3.1 查看符号表(函数和全局变量)
readelf -s demo  # 列出所有符号
输出示例:
   Num:    Value          Size Type    Bind   Vis      Ndx Name55: 0000000000401126    42 FUNC    GLOBAL DEFAULT   14 main56: 0000000000601040     4 OBJECT  GLOBAL DEFAULT   23 global_var
3.2 反汇编代码(查看机器码对应的汇编指令)
objdump -d demo  # 反汇编.text节(代码段)
输出示例:
0000000000401126 <main>:401126:       55                      push   %rbp401127:       48 89 e5                mov    %rsp,%rbp40112a:       b8 00 00 00 00          mov    $0x0,%eax
3.3 查看动态链接库依赖
ldd demo  # 列出依赖的共享库
输出示例:
linux-vdso.so.1 (0x00007ffd45df0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1a2d200000)
3.4 调试程序崩溃问题(结合核心转储文件)
gdb demo core  # 分析崩溃时的堆栈和变量
GDB会直接显示崩溃位置(需编译时加-g选项):
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401126 in main () at demo.c:20
20        printf("%s\n", (char*)0x0);  # 尝试打印空指针
3.5 修改ELF文件(谨慎操作!)
- 替换字符串:
 使用二进制编辑器(如hexedit)修改.rodata节中的字符串。
 示例:将"Hello World"改为"Hello Hacker":hexedit demo # 搜索并修改二进制内容
2. 实际案例演示
案例1:从ELF文件中提取版本信息
strings demo | grep "Version"  # 查找版本字符串
输出示例:
Version: 1.0.0
Build Date: 2023-10-01
案例2:检查是否启用了栈保护(编译选项-fstack-protector)
 
readelf -s demo | grep "__stack_chk_fail"  # 如果存在该符号,说明启用了栈保护
输出示例:
0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@GLIBC_2.4 (3)
案例3:查看文件是否被Strip过(是否删除符号表)
file demo  # 如果显示"stripped",则符号表已被删除
输出示例:
demo: ELF 64-bit LSB executable, x86-64, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, **stripped**
总结
| 功能 | 工具/命令 | 示例 | 
|---|---|---|
| 获取编译器版本 | readelf -p .comment | 查看GCC版本 | 
| 查找字符串 | strings+grep | 提取硬编码的错误信息 | 
| 反汇编代码 | objdump -d | 分析函数逻辑 | 
| 查看动态库依赖 | ldd | 检查缺失的 .so文件 | 
| 调试崩溃问题 | gdb+ 核心转储文件 | 定位空指针崩溃位置 | 
| 检查编译优化选项 | objdump -g+DW_AT_producer | 确认是否启用 -O2优化 | 
如果有更多具体场景,欢迎进一步提问! 😊
