-
-
[原创] ELF文件格式解析器 原理 + 代码
-
发表于:
2020-6-2 12:25
22244
-
写在前面:
读《Linux二进制》,发现作者对 ELF文件格式部分并没有做详细介绍,为了加深对elf文件格式理解,我自己着手写了个解析器, 会和readelf 工具协同对比。
原理:
ELF文件(目标文件)格式主要三种:
1. 可重定向文件(Relocatable file):文件保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享目标文件。(目标文件或者静态库文件,即linux通常后缀为.a和.o的文件)这是由汇编器汇编生成的 .o 文件。后面的链接器(link editor)拿一个或一些 Relocatable object files 作为输入,经链接处理后,生成一个可执行的对象文件 (Executable file) 或者一个可被共享的对象文件(Shared object file),内核可加载模块 .ko 文件也是 Relocatable object file
2. 可执行文件(Executable file):文件保存着一个用来执行的程序。(例如bash,gcc等)
3. 共享目标文件:
即 .so 文件。如果拿前面的静态库来生成可执行程序,那每个生成的可执行程序中都会有一份库代码的拷贝。如果在磁盘中存储这些可执行程序,那就会占用额外的磁盘空 间;另外如果拿它们放到Linux系统上一起运行,也会浪费掉宝贵的物理内存。如果将静态库换成动态库,那么这些问题都不会出现
一般的ELF文件有三个重要的索引表
1. ELF header:在文件的开始,描述整个文件的组织。。
2. Program header table:告诉系统如何创建进程映像。用来构造进程映像的目标文件必须具有程序头部表,可重定位文件不需要这个表。
3. Section header table :包含了描述文件节区的信息,每个节区在表中都有一项,每一项给出诸如节区名称、节区大小这类信息。用于链接的目标文件必须包含节区头部表,其他目标文件可以有,也可以没有这个表。
4. sections 或者 segments:segments是从运行的角度来描述elf文件,sections是从链接的角度来描述elf文件,也就是说,在链接阶段,我们可以忽略program header table来处理此文件,在运行阶段可以忽略section header table来处理此程序(所以很多加固手段删除了section header table)。注意:segments与sections是包含的关系,一个segment包含若干个section。

(图片来自网络)
上面提到的包含关系,我们可以用表格来对比一下结构:
了解整体结构之后,我们就可以看一下具体的结构体和指针了。
代码先写了一个help函数,包含基本信息和指令结构,效果如下:

1.-h指令,查看和打印 程序header函数。
我们查看一下elf headr结构体:
这里面包括后面的code都会涉及到elf的数据格式,在这给出:

所以打印elf的头信息可以设计为:
效果展示:

readelf对比:

参考e49K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8Y4q4I4i4K6g2X3x3K6M7@1x3K6p5&6x3K6N6Q4c8e0g2Q4z5o6W2Q4z5p5c8Q4c8e0S2Q4b7V1g2Q4z5o6S2Q4c8e0g2Q4z5f1u0Q4b7V1g2Q4c8e0S2Q4b7e0N6Q4b7e0y4Q4c8f1k6Q4b7V1y4Q4z5f1p5`.

2. -S 指令 打印section信息
段表结构体:
一些成员参数解释:

代码设计:
效果展示:

readelf 对比:

3. -s 打印符号表信息
目标文件的符号表中包含用来定位、重定位程序中符号定义和引用的信息。符号表 索引是对此数组的索引。索引 0 表示表中的第一表项,同时也作为 定义符号的索引。
[培训]科锐逆向工程师培训第53期2025年7月8日开班!