Linux及安全——ELF实践

Linux及安全——ELF实践

 一、分析ELF文件头

二、通过文件头找到section header table,理解内容

三、通过section header table 找到各section

四、理解常见.text .strtab .symtabl .rodata 等section

1.编写测试文件test.c

2.使用如下命令编译生成test.o文件

gcc -c test.c -o test.o

使用如下命令查看test.o文件的大小

ls -l test.o

得知test.o大小为7340字节

 

3.使用下面命令,用16进制数字显示test.o的内容

hexdump -x test.o

首先看ELF文件头,打开/usr/include/elf.h

32位系统和64位系统的ELF头结构基本相同,区别在于32位系统的ELF头文件大小是52字节,但是64位系统的ELF头文件是64字节。(十进制的64用十六进制表示是34,我的Ubuntu系统是32位)

4.读取ELF文件头

在 readelf 的输出中:
第 1 行,ELF Header: 指名 ELF 文件头开始。
第 2 行,Magic 魔数,用来指名该文件是一个 ELF 目标文件。第一个字节 7F 是个固定的数;后面的 3 个字节正是 E, L, F 三个字母的 ASCII 形式。
第 3 行,CLASS 表示文件类型,这里是 32位的 ELF 格式。
第 4 行,Data 表示文件中的数据是按照什么格式组织的(大端或小端),不同处理器平台数据组织格式可能就不同,如x86平台为小端存储格式。
第 5 行,当前 ELF 文件头版本号,这里版本号为 1 。
第 6 行,OS/ABI ,指出操作系统类型,ABI 是 Application Binary Interface 的缩写。
第 7 行,ABI 版本号,当前为 0 。
第 8 行,Type 表示文件类型。ELF 文件有 3 种类型,一种是如上所示的Executable可执行文件, 一种是可重定位目标文件(Relocatable file),另外一种是共享库(Shared Library) 。
第 9 行,机器平台类型。
第 10 行,当前目标文件的版本号。
第 11 行,程序的虚拟地址入口点,这里是0x8048310。
第 12 行,程序头开始处,这里是52,表示从地址偏移 0x34 处开始。
第 13 行,section头开始处,这里6100 是十进制,表示从地址偏移 0x17D4 处开始。
第 14 行,是一个与处理器相关联的标志,x86 平台上该处为 0 。
第 15 行,ELF 文件头的字节数,这里为52。
第 16 行,程序头字节数,这里为32。
第 17 行,程序头数量,这里为9个

第 18 行,sections header 的大小,这里每个 section 头大小为 40 个字节。

第 19 行,一共有多少个 section 头,这里是 31 个。

第 20 行,section 头字符串表索引号,从 Section Headers 输出部分可以看到其内容的偏移在 0x34 处,从此处开始到0x50 结束保存着各个 sections 的名字,如 .data,.text,.bss等。

 5.分析过以上之后,我们再来分析用16进制显示的本程序中的ELF头

由于intel x86使用小端法,hexdump -x test.o命令是一次性输出两个字节

第一行

(对应e_ident[EI_NIDENT]):实际表示内容为7f45 4c46 0101 0100 0000 0000 0000 0000

前四个字节7f45 4c46对应16进制ASCⅡ表是ELF,第一个字节 7F 是个固定的数;接下来的一个字节01表示是一个32位对象(64位表示成02),再接下来的一个字节01表示采用小端法表示,再接下来的一个字节01表示文件头版本,剩下的默认都设置为0.

第二行

e_type(两个字节)值为0x0002,表示是一个可执行文件。

e_machine(两个字节)值为0x0003,表示是表示386体系文件。

e_version(四个字节)值为0x00000001,和e_ident里面的EI_VERSION含义一样,表示是当前版本号。

e_entry(四个字节)值为0x08048310,表示程序入口地址0x08048310。

e_phoff(四个字节)值为 0x00000034 表示program header table(程序头表)在文件中的偏移量(0x34转化为十进制是52,与上上图吻合)

第三行

e_shoff(四个字节)值为0x000017d4,表示section header table(段表)在文件中的偏移量(0x17d4转化为十进制是6100)。

e_flags(四个字节)值为0x00000000,表示未知处理器特定标志(#define EF_SH_UNKNOWN 0x0)

e_ehsize(两个字节)值为0x0034, 表示elf header大小, 其实就是sizeof(Elf32_Ehdr)(转化为十进制为52)。

e_phentsize(两个字节)值为0x0020, 表示每个program header 的大小为0x20。

e_phnum(两个字节)的值为0x0009,表示一共有9个program header。

e_ehentsize(两个字节)值为0x0028表示每个段头大小为40个字节(由这里知道section header table里面每个header的大小)。

第四行: 

e_shnum(两个字节)值为0x001f,表示有31个section header(由这里知道段表有13个段)。

e_shstrndx(两个字节)值为0x001c,表示section string table(段名串表)在section header table(段表)中的索引值。(即第几个section描述了section string table的位置和大小),(转化为10进制是28)。

 

通过对readelf和hexdump十六进制的分析,把它们ELF格式对应了起来。

P.S.32位版本对应ELF文件格式及说明

6.段表(section table)的分析

由刚才分析的ELF头可知,段表从0x000017d4开始,每个节区大小为0x0028,共有0x001f个节区,第0x001c为段名串表的索引号。

段表大小28H*1fH=4d8(H)

0x000017d4+0x4d8=0x00001cac

第一节区(17d4-17fc)

第二节区(17fc-1824)

第三节区(1824-184c)

第四节区(184c-1874)

第五节区(1874-189c)

以此类推……

第六节区到第三十一节区(189c-1cac)

分析比较关键的段,以text段为例:

.text ssection是可执行指令的集合,查询段表可知偏移地址为0x000310,使用hexdump -x test.o命令看.text section的内容

使用命令objdump -d test.o对其进行反汇编,得到汇编代码对应的test.o的elf文件

7.符号表分析

用该指令查看各段信息

readelf test.o

 

posted @ 2016-06-12 21:03  bonjourvivi  阅读(693)  评论(0编辑  收藏  举报