Linux及安全實踐四——ELF文件格式分析


Linux及安全實踐四——ELF文件格式分析

一、ELF文件格式概述

1. ELF:是一種對象文件的格式,用於定義不同類型的對象文件中都放了什么東西、以及都以什么樣的格式去放這些東西。

二、分析一個ELF文件

以一個最簡單的helloworld程序為例

1. ELF文件頭

使用工具查看ELF文件頭:readelf -h obj

 

在/usr/include/elf.h中可以找到文件頭結構定義:

 

大小總共為64字節,換算成十六進制為0x40。在十六進制代碼中找到前0x40字節,即為文件頭信息部分(閱讀時注意反序問題):

 

(1)identification

 

第一部分:占四個字節。7f 45 4c 46,對應ASCII碼.ELF,表示這是一個ELF對象。

第二部分:占一個字節。02表示是一個64位對象。

第三部分:占一個字節。01表示是小端表示法。

第四部分:占一個字節。01表示文件頭版本。

其余默認為0。

(2)information

 

e_type:兩個字節,01 00表示是一個重定位文件。

e_machine:兩個字節,3e 00表示是intel80386處理器體系結構。

e_version:四個字節,01 00 00 00表示是當前版本。

e_entry:八個字節,00 00 00 00 00 00 00 00表示當前程序沒有入口點。

e_phoff:八個字節,00 00 00 00 00 00 00 00表示沒有程序頭表。

e_shoff:八個字節,90 02 00 00 00 00 00 00表示段表的偏移地址在00 00 00 00 00 00 02 90處。

e_flags:四個字節,00 00 00 00表示未知處理器特定標志#define EF_SH_UNKNOWN 0x0。

e_ehsize:兩個字節,40 00表示elf文件頭大小為00 40(64個字節)。

e_phentsize:兩個字節,00 00表示重定位文件沒有程序頭表。

e_phnum:兩個字節,00 00表示重定位文件沒有程序頭表。

e_ehentsize:兩個字節,40 00 表示段頭大小為00 40(64字節),section header table中每個header的大小。

e_shnum:兩個字節,0d 00表示段表入口有13個,即段表有13段。

e_shstrndx:兩個字節,0a 00 表示段表字符串在段表中的索引號,.shstrab段的段表索引號為00 0a,即10。

2. 通過文件頭找到各個節

使用工具查看段表信息:readelf -S obj

(1)找到段表

在文件頭中e_shoff可以找到段表偏移地址00 00 00 00 00 00 02 90,從這個地址去查找段表。

段表長度由e_ehentsize為00 40(64字節)。

段表個數由e_shnum可知有13個。

/usr/include/elf.h中可以找到段表結構:

 

(2)分析一個段表

第一個段:全為零,不表示任何段。

 

第二個段:

 

sh_name:四個字節,20 00 00 00表示該段名稱在.shstrtab中偏移量,為.test節。

sh_type:四個字節,01 00 00 00表示這個段擁有程序所定義的信息,其格式和含義完全由該程序確定,這里表示PROGBITS。

sh_flags:八個字節,06 00 00 00 00 00 00 00表示alloc和execute。

sh_addr:八個字節,00 00 00 00 00 00 00 00表示是section在內存中的虛擬地址,.o文件不需要執行,這里都是0。

sh_offset:八個字節,40 00 00 00 00 00 00 00表示是section與文件頭之間的偏移。

sh_size:八個字節,11 00 00 00 00 00 00 00表示文件里面section占用的大小。

sh_link:四個字節,00 00 00 00表示沒有鏈接信息。

sh_info:四個字節,00 00 00 00表示沒有輔助信息。

sh_addralign:八個字節,01 00 00 00 00 00 00 00表示字節對齊長度。

sh_entsize:八個字節,00 00 00 00 00 00 00 00表示沒有入口。(3)所有段表

第三個段:

 

段名:.rel.text

類型:RELA

標志:info

相對文件頭偏移:0x1e0

占用大小:0x30

第四個段:

 

段名:.data

類型:PROGBITS

標志:write、alloc

相對文件頭偏移:0x51

占用大小:0

第五個段:

 

段名:.bss

類型:NOBITS

標志:write、alloc

相對文件頭偏移:0x51

占用大小:0

第六個段:

 

段名:.rodata

類型:PROGBITS

標志:alloc

相對文件頭偏移:0x51

占用大小:0x0b

第七個段:

 

段名:.comment

類型:PROGBITS

標志:merge、strings

相對文件頭偏移:0x5c

占用大小:0x26

第八個段:

 

段名:.note.GNU-stack

類型:PROGBITS

標志:無

相對文件頭偏移:0x82

占用大小:0

第九個段:

 

段名:.eh_frame

類型:PROGBITS

標志:alloc

相對文件頭偏移:0x88

占用大小:0x38

第十個段:

 

段名:.rela.eh_frame

類型:RELA

標志:info

相對文件頭偏移:0x210

占用大小:0x18

第十一段:

 

段名:.shstrtab

類型:STRTAB

標志:無

相對文件頭偏移:0x228

占用大小:0x61

第十二段:

 

段名:.symtab

類型:STRTAB

標志:無

相對文件頭偏移:0xc0

占用大小:0x0108

第十三段:

 

段名:.strtab

類型:STRTAB

標志:無

相對文件頭偏移:0x1c8

占用大小:0x11

三、理解常見節

1. .text節:本節中是可執行指令的集合

通過剛才的信息,我們可以從文件中偏移0x40處找到大小為0x11的 .text節:

 

可以通過反匯編該程序來查看:

 

2. .rodata:本節是只讀數據,ro代表read only

從偏移0x51處找到大小為0x0b的 .rodata節:

 

使用ASCII碼對照表翻譯數據為hello 5309,即.c文件中的字符串:

 

2. .comment:本節用來存放編譯器版本信息

從偏移0x5c處找到大小為0x26的 .comment節:

 

3. .symtab:本節存放所有section中定義的符號名字,一般是變量、函數shstrtab及symtab經常引用strtab中的字符串

從偏移0xc0處找到大小為0x0108的 .symtab節:

 

4. .strtab:本節是段表的字符串表

從偏移0x1c8處找到大小為0x11的 .strtab節:

 

數據用“0”分隔出了三部分,用ASCII碼翻譯:

65 6c 66 2e 63:elf.c

6d 61 69 6e:main

70 75 74 73:puts

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM