常用的分析ELF文件的命令(readelf、objdump及od)
readelf:
-h:文件头
-S:段表
-s:符号表
-d: 查看依赖库
-p:查看某个段内容,非常重要。如:readelf -p .comment libc.so (通过-p对只读段的查看就可以替代strings命令)
objdump:
-d:反汇编(objdump我基本只用这一个)
-h:段表,同readelf -S,所以可以不用记
–s:代码段、数据段、只读数据段,各个段二进制
-a:看一个.a静态库文件中包含了哪些目标文件
od:
如:十六进制输出数据并且地址以十进制打印:od -A d -t xCc 文件
命令中各选项的含义:
- A 指定地址基数,包括:
d 十进制
o 八进制(系统默认值)
x 十六进制
n 不打印位移值
- t 指定数据的显示格式,主要的参数有:
c ASCII字符或反斜杠序列
d 有符号十进制数
f 浮点数
o 八进制(系统默认值为02)
u 无符号十进制数
x 十六进制数
以下为ELF文件各个表的描述,供以后复习
文件头:描述文件的基础信息以及找到段表
文件头查看:readef -h
1)模数
第1个字节:DEL控制符,固定的
第2、3、4个字节:ELF三个字母
第5个字节:文件位数(0:无效、1:ELF32、2:ELF64)
第6个字节:大小端(0:无效、1:小端、2:大端)
第7个字节:ELF文件的主版本号,一般为1
后面的为预留字段。
2)文件类型:REL (Relocatable file)、DYN (Shared object file)、EXEC (Executable file)
3)Machine: Intel 80386 :硬件平台,此文件适合在哪个硬件平台下运行
4)程序入口地址
Entry point address: 0x8048310
代表程序入口的虚拟地址,只有可执行文件跟共享库有入口(共享库的入口地址有什么用呢?)
5)Start of program headers: 52 (bytes into file) : (readelf -l ), 程序表头,装载时用到,因为目标文件不需要装载,所以为0。
6)Start of section headers: 2000 (bytes into file)
段表在文件中的偏移,也就是说段表从文件中的2000个字节开始的
2000是10进制,用计算器转换成16进制后就可以在那个,这个特别重要,找到段表,就代表了什么都有了
7)Size of section headers: 40 (bytes)
段表描述符的大小,猜测:会根据平台的不同,这个是固定的,因为在同一个平台下不同代码编出来的目标文件,结果是一样的
8)Number of section headers: 11
段表描述符数量,elf文件中,拥有的段的数量(所以说,一个段表描述符就是在描述一个段呗)
证明(readelf -S )
9)Size of this header: 52 (bytes)
ELF文件头本身的大小,猜测:会根据平台的不同,这个是固定的
10)Section header string table index: 8
段表字符串表所在的段在段表中的下标
总结:通过文件头找段表,之后在段表里面找到段表字符串表,段表中就能找到段表字符串标在文件中的偏移,之后就能生成整个段表。
段表:描述每个段的详细信息
段表查看:readelf –S, 如果gcc –g的话,还会有很多调试信息段
Name:在段表描述符里存了一个整形,这个整形是段名在段表字符串表(.shstrtab)中的偏移。
Type:段的类型,如下表
Addr:如果可以被加载,代表了该段在虚拟内存空间的地址,否则为0,可以看出来,段表字符串表、符号表、字符串表都不会被加载的
Off:如果该段在文件中,则代表了在文件中的偏移
Size:段长
Flags:标志
Lk跟Inf:段的链接信息
Al:段地址对齐,代表这个段是几字节对齐的
ES:项的长度:如果该段的每一项的长度是固定的,那么就代表每一项的长度,如符号表的每个符号的信息长度都是0x10个字节。对于变化的就是0。符号表里存的符号名,只是符号在字符串表中的索引,符号表里不是直接存的符号。
Flags字段:段的标志,表示该段在进程虚拟空间中的属性,可读/可写/可执行,这个标志比较重要,因为在加载的时候,会根据段的标志进行加载的,大概是只读放在一个区域,可读可写放在一个区域等
Lk跟Inf:段的链接信息,与链接、重定位相关的段,这两个信息才有意义
重要段:代码段、数据段、只读数据段、BSS段
代码段、数据段、只读数据段:objdump –s
代码段:程序指令,objdump -d反汇编
数据段:已经初始化了全局变量和局部静态变量
只读数据段:只读变量以及字符串常量
BSS段:存放了未初始化的全局变量和局部静态变量,通过符号表可以看出
字符串表:符号名等
段表字符串表:段名
注释提示段
符号表: readelf -s / nm / objdump -x
符号名:该符号在字符串表中的下标
符号值:目标文件中:非COMMON类型表示该符号在所在段中的偏移,common类型表示对齐属性;可执行文件中:代表虚拟地址(动态链接器如何用它?)
符号大小:非0代表该符号值的数据类型的大小,0代表未知或0
符号类型和绑定信息:符号类型:数据?函数?段?文件?符号绑定信息:局部符号(外部不可见)?全局符号(外部可见)?弱引用?低4位表示符号的类型,高28位表示符号的绑定信息,看下表
其他:目前没用,为0
符号所在的段:如果非0数字,代表了是在本文件中定义的符号,并且代表了对应的段,其余含义为:UND:本目标文件未定义;ABS:绝对的值,如文件名;COMMON:COMMON块类型(未初始化的全局变量)