天天看点

ELF文件格式ELF文件格式

ELF文件格式

0x00 准备

ELF全称Executable and Linking Format,ELF文件主要有3种,在文件内部有2个byte用来指明该ELF文件的类型(后文详述)。为了分析ELF文件的结构,准备好一个简单的c语言“hello world”程序,编译该文件得到ELF文件。

hw.c

#include <stdio.h>                                                                                                                              

int main(){
    printf("hello world!\n");
    return ;
}
           

命令:gcc -c hw.c

得到文件hw.o

命令:gcc hw.c -o hw

得到文件hw

在分析的过程中会:

  • 使用hexdump命令查看ELF文件的二进制数据
  • 使用readelf命令查看ELF文件的结构分析
  • 使用objdump命令查看ELF文件的信息

命令:hexdump -C hw

得到ELF文件hw的二进制显示:

f  c                |.ELF............|
    e                |..>.....@.@.....|
           c8         |@...............|
               e  b   |....@...@.....|
                    |........@.......|
                    |@.@.....@.@.....|
  f8         f8         |................|
                    |................|
                    |......@.....|
           c         |@.............|
a0  c                  |................|
b0                    |................|
c0                    |..@.......@.....|
d0  c         c         |................|
                    |.. .............|
f0   e         e        |..........`.....|
........
           

0x01 ELF文件头(ELF Header):前64字节

ELF文件的前64个字节(这里指的是64位系统下,32位系统下稍有不同,是52个字节)描述了ELF文件的基本信息,被称为ELF头

先分析前16个byte(0-15)

(0-3)byte:7f 45 4c 46

这个是ELF文件的魔数,每一种文件一般都有魔数,用来表明该文件的类型,例如java的class文件的魔数就是前4个byte :CAFEBABE

(4)byte : 02

这个字节标识此ELF文件的平台类型,有3个可选值

0x00 :无效文件

0x01 :32bit平台目标文件(ELF文件)

0x02 :64bit平台目标文件

这里是值为0x02表明是在64位系统下编译的

(5)byte:01

这个字节标识二进制文件的编码类型,有3个可选值

0x00:无效编码

0x01:小印第安排序(最大有意义的字节占有最低的地址)

0x02:大印第安排序(最大有意义的字节占有最高的地址)

这里的值为0x01表明此ELF文件使用的是小印第安排序

(6)byte:01

这个字节指明ELF文件格式的版本,当前必须为0x01

(7)byte :00 00 00 00 00 00 00 00 00

OS/ABI

(8)byte : 00

ABI version

(9-15)byte : 00 00 00 00 00 00 00

当前没有意义,但是在将来可能有意义,规定必须每个byte都设置为0x00 ,但是其实不设置为0x00也可以,例如病毒程序就可以用这些byte来表明改ELF文件是否已经被感染,或者是处于其他什么状态

再分析后48个byte(16-63)

(16-17)byte 02 00

这2个字节表明文章开头所说的ELF文件的类型,(5)byte表明ELF文件是小印第安排序,因此这2个字节的值为0x0002 ,说明这是一个可执行文件。这2个字节的可选值如下:

0x0000 : 未知

0x0001 : 重定位文件

0x0002 : 可执行文件

0x0003 : 共享库文件

0x0004 : 核心文件

0xff00 - 0xffff : 处理器相关

(18-19)byte 3e 00

这2个字节表明机器架构,0x003e说明是x86_64机器

这个值的部分可选值有:

0x00 : No Manchine

0x02 : SPARC

0x03 : Intel 80386

0x12 : Sun SPARC 32+

0x2b : SPARC V9

0x3e : ADM 64

(20-23)byte 01 00 00 00

这4个字节说明此目标文件的版本,当前的版本均为1

(24-31)byte 40 04 40 00 00 00 00 00

这8个字节是程序入口点地址,也就是main函数的逻辑地址,在64位系统下用8个字节表示,32为系统下只有4个字节,这个值说明main函数的逻辑地址为:0x0000000000040440c8 19 00 00 00 00 00 00

(32-39)byte 40 00 00 00 00 00 00 00

这8个字节是程序头表(program header table)在目标文件中的偏移地址,这里的值为0x40,即64,说明程序头表从第64字节开始,也就是紧接着ELF Header之后。如果没有程序头表,这个值为0

(40-47)byte c8 19 00 00 00 00 00 00

这8个字节是节头表(section header table)在目标文件中的偏移地址,这里的值为0x19c8 ,说明节头表在目标文件的6600字节。如果没有节头表这个值为0

(48-51)byte 00 00 00 00

这4个字节就是一个与处理器相关的标识(flag)

(52-53)byte 40 00

这2个字节说明ELF Header本身的大小,64位系统的下是64字节,所以是0x0040

(54-55)byte 38 00

这2个字节标识在程序头表中每个程序头的大小(以字节为单位,每个程序头的大小都是一样的),此ELF文件中每个程序头的大小为0x38个字节

(56-57)byte 09 00

这2个字节说明程序头表中程序头的个数, 没有的话就是0,此ELF文件有9个程序头

(58-59)byte 40 00

这2个字节标识在节头表中每个节头的大小(以字节为单位,每个节头的大小都是一样的),此ELF文件每个节头的大小是0x40,即64个字节

(60-61)byte 1e 00

这2个字节标识节头表中节头的个数,没有的话就是0,0x1e说明ELF文件有30个节头

(62-63)byte 1b 00

这2个字节表示的值是一个节头表的索引值(因此这个值0x1b必然小于总数0x1e),通过这个索引值,可以在节头表中找到一个特殊的节头,在这个节头中有每个节头的字符串名字信息。没有这样一个特殊的节头的话这个值就是0

待续…

继续阅读