linux实践之ELF文件分析

linux实践之ELF文件分析

下面开始elf文件的分析。

我们首先编写一个简单的C代码。

编译链接生成可执行文件。

首先,查看scn15elf.o文件的详细信息。

以16进制形式查看scn15elf.o文件。

查看scn15elf.o中各个段和符号表的信息。

各个段的详细信息如下。

符号表的信息如下:

使用readelf命令查看各个段的详细信息:

段表信息如下:

符号表信息如下:

下面让我们开始分析文件头吧!

由于我的虚拟机是32位的,我下面就主要以32位的系统进行分析,就不比较32位机和64位机的区别了。

32位系统elf头文件的定义。

从上图中,我们可知,elf文件头在32位系统中,占52个字节。(16+2+2+4+4+4+4+4+2+2+2+2+2+2=52)转换为16进制表示为0x34个字节。

由于该虚拟机处理器使用小端法表示数据。

分析elf文件头

第一行:

e_ident用16个字节表示为“7f45 4c46 0101 0100 0000 0000 0000 0000”,其中“7f45 4c46”表示“ELF”的ASCII码表。“0101”中前一个“01”表示是32位的机器,后一个“01”表示使用的是小端法。“0100”中的“01”表示的是版本号是01。剩下的0为默认填充。

第二行:

e_type用2个字节表示,为“0001”,表示是一个重定向文件。

e_machine用2个字节表示,为“0003”,表示Inter 80386的处理器体系结构(32位)

e_version用4个字节表示,为“0000 0001”,表示的是当前版本。

e_entry用4个字节表示,为“0000 0000 ”表示没有入口点。

e_phoff用4个字节表示,为“0000 0000”表示没有程序头表。

第三行:

e_shoff用4个字节表示,为“0000 0228”表示段表的偏移地址。

e_flags用4个字节表示,为“0000 0000”表示未知处理器特定标志。

e_ehsize用2个字节表示,为“0034”表示elf文件头大小。

e_phentsize用2个字节表示,为“0000”,因为重定位文件没有程序头表。

e_phnum用2个字节表示,为“0000”,因为重定位文件没有程序头表。

e_shentsize用2个字节表示,为“0028”,表示段头大小为“0x28”字节,即为40个字节(由此知道section header table里面每一个table的大小为40个字节)。

第四行:

e_shnum用2个字节表示,为“000d”,表示段表入口有13个,这里可以知道,段有13个。

e_shstrndx用2个字节表示,为“000a”,表示段名串表在段表中的索引,(符号表的信息在段表的索引号是10)。

自己手工分析完后,可以和“readelf”指令读出的数据进行比较。

分析段表:

首先我们根据刚刚在elf文件头中读到的段表偏移,找到段表的起始,我们可以看到偏移为“0x228”。从上图中段表的数据结构中可以看出,段表占40个字节(4*10=40字节即“0x28个字节”),这个结果和我们从elf文件头中读到的结果一致。

由于第一个段中有一部分数据没有读出来,所以我们以第二个段(偏移为0x0000268~0x00002a7)为例分析:

sh_name用4个字节表示,为“0000 001f”,该值代表section header string table中的索引。

sh_type 用4个字节表示,为“0000 0001”,表示该段的类型是“SHT_PROGBITS”。

sh_flags 用4个字节表示,为“0000 0006”,指示该section在进程执行时的特性。其中最低位如果为1 表示此节在进程执行过程中可写,次低位为1表示此节的内容加载时要读到内存中去,第三低位为1表示这个节中的数据是可执行的机器指令。这里表明该节在进程执行过程中不可写,在内容加载时要读到内存中去,该节数据是可执行的机器指令。

sh_addr 用4个字节表示,为“0000 0000”,表示该节在进程中的起始地址为“0x0000 0000”。

sh_offset用4个字节表示,为“0000 0034”表示该节在整个文件中的起始偏移量为“0x34”。

sh_size用4个字节表示,为“0000 002e”,表示该节的字节大小为2e。

sh_link用4个字节表示,为“0000 0000”,表示没有和该节相关联的节。

sh_info用4个字节表示,为“0000 0000”表示没有文件信息

sh_addralign用4个字节表示,为“0000 0001”,该值用于表示地址对齐信息,值为1时表示不用地址对齐。

sh_entsize用4个字节表示,为“0000 0000”,对特定节(动态符号)才有意义,这里没有意义。

总结:从section header table找到各个section头的信息,还是很简单的。

只要知道其序列号(第几个节)。寻找偏移“0x228+第i个节*0x28”即可。

通过从section header table中读到的信息,我们来找一找这个字段的内容。

经分析知,该节内容起始,距文件头0x34的位置,内容大小为0x2e个字节。

如图所示,该节的内容即为图中高亮的部分。我们反汇编一下scn15elf.o文件,结果为

对比发现两个结果是一致的。

分析各个section。(.text .strtab .symtab .rodata

.text

分析见上一步的例子,已经分析完了。

.strtab

.strtab中存放的是符号的名字(符号表示一个固定的内存地址)。

计算该节的偏移=0x228+12*0x28=0x408。

sh_name用4个字节表示,为“0000 0009”,该值代表section header string table中的索引。即.strtab节。

sh_type 用4个字节表示,为“0000 0003”,表示该段的类型是“SHT_STRTAB”。

sh_flags 用4个字节表示,为“0000 0000”,指示该section在进程执行时的特性。表明该节在进程执行过程中不可写,在内容加载时不需要读到内存中去,该节数据不是可执行的机器指令。

sh_addr 用4个字节表示,为“0000 0000”,表示该节在进程中的起始地址为“0x0000 0000”。

sh_offset用4个字节表示,为“0000 00198”表示该节在整个文件中的起始偏移量为“0x198”。

sh_size用4个字节表示,为“0000 0016”,表示该节的字节大小为16。

sh_link用4个字节表示,为“0000 0000”,表示没有和该节相关联的节。

sh_info用4个字节表示,为“0000 0000”表示没有文件信息

sh_addralign用4个字节表示,为“0000 0001”,该值用于表示地址对齐信息,值为1时表示不用地址对齐。

sh_entsize用4个字节表示,为“0000 0000”,对特定节(动态符号)才有意义,这里没有意义。

总结上面的分析是,该节距离文件头偏移为0x198,内容大小为0x16。

.symtab

该节中存放着所有section中定义的符号名字。描述了.strtab中的符号在“内存”中对应的“内存地址”。这里的“内存地址”指的是偏移量,不是真的内存地址。

计算该节的偏移=0x228+11*0x28=0x3E0。

sh_name用4个字节表示,为“0000 0001”,该值代表section header string table中的索引。即.symtab节。

sh_type 用4个字节表示,为“0000 0002”,表示该段的类型是“SHT_STRTAB”。

sh_flags 用4个字节表示,为“0000 0000”,指示该section在进程执行时的特性。表明该节在进程执行过程中不可写,在内容加载时不需要读到内存中去,该节数据不是可执行的机器指令。

sh_addr 用4个字节表示,为“0000 0000”,表示该节在进程中的起始地址为“0x0000 0000”。

sh_offset用4个字节表示,为“0000 00e8”表示该节在整个文件中的起始偏移量为“0xe8”。

sh_size用4个字节表示,为“0000 00b0”,表示该节的字节大小为16。

sh_link用4个字节表示,为“0000 000c”,表示没有和该节相关联的节。

sh_info用4个字节表示,为“0000 0009”表示没有文件信息

sh_addralign用4个字节表示,为“0000 0004”,该值用于表示地址对齐信息,值为4时表示需要地址对齐。

sh_entsize用4个字节表示,为“0000 0010”,表示字节大小。

总结上面的分析是,该节距离文件头偏移为0xe8,内容大小为0xb0。

对比符号表里的内容。

.rodata

rodata的意义同样明显,ro代表read only,即只读数据(const)。关于rodata类型的数据,要注意以下几点:
1、常量不一定就放在rodata里,有的立即数直接编码在指令里,存放在代码段(.text)中。
对于字符串常量,编译器会自动去掉重复的字符串,保证一个字符串在一个可执行文件(EXE/SO)中只存在一份拷贝。
2、rodata是在多个进程间是共享的,这可以提高空间利用率。
3、有的嵌入式系统中,rodata放在ROM(如norflash)里,运行时直接读取ROM内存,无需要加载到RAM内存中。
4、在嵌入式linux系统中,通过一种叫作XIP(就地执行)的技术,也可以直接读取,而无需要加载到RAM内存中。

计算该节的偏移=0x228+5*0x28=0x2F0。

sh_name用4个字节表示,为“0000 030”,该值代表section header string table中的索引。即.rodata节。

sh_type 用4个字节表示,为“0000 0001”,表示该段的类型是“SHT_STRTAB”。

sh_flags 用4个字节表示,为“0000 0002”,指示该section在进程执行时的特性。表明该节在进程执行过程中不可写,在内容加载时不需要读到内存中去,该节数据不是可执行的机器指令。

sh_addr 用4个字节表示,为“0000 0000”,表示该节在进程中的起始地址为“0x0000 0000”。

sh_offset用4个字节表示,为“0000 0062”表示该节在整个文件中的起始偏移量为“0x62”。

sh_size用4个字节表示,为“0000 0013”,表示该节的字节大小为13。

sh_link用4个字节表示,为“0000 0000”,表示没有和该节相关联的节。

sh_info用4个字节表示,为“0000 0000”表示没有文件信息

sh_addralign用4个字节表示,为“0000 0001”,该值用于表示地址对齐信息,值为1时表示不用地址对齐。

sh_entsize用4个字节表示,为“0000 0000”,对特定节(动态符号)才有意义,这里没有意义。

总结上面的分析是,该节距离文件头偏移为0x62,内容大小为0x13。

参考资料

1、 浅谈Linux的可执行文件格式ELF

http://blog.chinaunix.net/uid-9068997-id-2010376.html

时间: 05-30

linux实践之ELF文件分析的相关文章

Linux及安全实践四——ELF文件格式分析

Linux及安全实践四——ELF文件格式分析 一.ELF文件格式概述 1. ELF:是一种对象文件的格式,用于定义不同类型的对象文件中都放了什么东西.以及都以什么样的格式去放这些东西. 二.分析一个ELF文件 以一个最简单的helloworld程序为例 1. ELF文件头 使用工具查看ELF文件头:readelf -h obj 在/usr/include/elf.h中可以找到文件头结构定义: 大小总共为64字节,换算成十六进制为0x40.在十六进制代码中找到前0x40字节,即为文件头信息部分(阅

linux c lseek (空洞文件) 分析和处理

首先测试标准输入是否可以进行lseek操作 [[email protected] 03]# cat ex03-lseek-01.c /*文件ex03-lseek-01.c, 使用lseek函数测试标准输入是否可以进行seek操作*/ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main(void) { off_t offset =

linux下的ELF格式分析

ELF格式文档详解 一,ELF格式综述 ELF(Executable and Linkable Format)是Linux下的一种格式标准,Linux中的ELF格式文件一共有四种: ●可重定位文件(Relocatable File):这类文件包含了代码和数据,可被用来链接成可执行文件或者共享目录文件,扩展名为.o ●可执行文件(Executable File):这类文件包含了可以直接执行的程序,一般没有扩展名 ●共享目录文件(Shared Object File):这类文件包含了代码和数据,扩展

ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三)

日期 内核版本 架构 作者 GitHub CSDN 2016-06-04 Linux-4.6 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度-之-进程的描述 加载和动态链接 从编译/链接和运行的角度看,应用程序和库程序的连接有两种方式. 一种是固定的.静态的连接,就是把需要用到的库函数的目标代码(二进制)代码从程序库中抽取出来,链接进应用软件的目标映像中: 另一种是动态链接,是指库函数的代码并不进入应用软件的目标映像,应用软件在编译/链接阶段并

Linux之ELF文件初探

对比windowsPE文件与概述 在windows中可执行文件是pe文件格式,Linux中可执行文件是ELF文件,其文件格式是ELF文件格式,在Linux下的ELF文件除了可执行文件(Excutable File),可重定位目标文件(RellocatableObject File).共享目标文件(SharedObjectFile).核心转储文件(Core DumpFile)也都是ELF格式文件. 一个典型的ELF文件大致的结构如下 文件头(ELF Header) 程序头表(Program Hea

【实践报告】Linux实践四

Linux内核分析 实践四——ELF文件格式分析 一.概述 1.ELF全称Executable and Linkable Format,可执行连接格式,ELF格式的文件用于存储Linux程序.ELF文件(目标文件)格式主要三种: 可重定向文件:文件保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享目标文件.(目标文件或者静态库文件,即linux通常后缀为.a和.o的文件) 可执行文件:文件保存着一个用来执行的程序.(例如bash,gcc等) 共享目标文件:共享库.

浅谈linux 中的目标文件 即.o后缀名的文件

实际上 目标文件从结构上讲,已经非常接近可执行文件,只是没有经过链接的过程,所以其中有些符号或者地址还没有被调整. 实际上上在linux下 都是可以称之为ELF文件. 看一下这个图,a.out 就是我们的hello.c的执行文件.hello.o 就是目标文件 所以实际上他们2 几乎是一样的. 一般目标文件有很多属性,比如符号表啊,字符串之类的,然后目标文件 把这些属性 按照 segment的形式存储,也叫段.就是大家经常遇到的段错误 里的那个段. 一般来说程序代码被编译以后 主要分为程序指令和程

Linux共享库.so文件的命名和动态链接

Linux中的.so文件 是动态链接的产物 共享库理解为提供各种功能函数的集合,对外提供标准的接口 Linux中命名系统中共享库的规则 主版本号:不同的版本号之间不兼容 次版本号:增量升级 向后兼容 发行版本号:对应次版本的错误修正和性能提升,不影响兼容性 Linux中的共享库并不都是这样的格式 比如GLibc的共享库命名为:libc-x.y.z.so 动态链接器也是GLibc的一部分,使用ld-x.y.z.so命名 libm(数学库)等 SO-NAME机制 系统和程序中要链接的共享库的格式一般

动态链接库的ELF头分析

ELF(Executable and Linking Format)用于存储Linux程序. ELF文件分三种类型: 1.目标文件(通常是.o); 2.可执行文件(我们的运行文件)   3.动态库(.so) ELF头的各个字段: typedef struct { unsigned char e_ident[EI_NIDENT]; /* File identification. */ Elf32_Half e_type; /* File type. */ Elf32_Half e_machine;