Linux課題實踐四——ELF文件格式分析

2.4   ELF文件格式分析linux

20135318 劉浩晨bash

ELF全稱Executable and Linkable Format,可執行鏈接格式,ELF格式的文件用於存儲Linux程序。ELF文件(目標文件)格式主要三種:編輯器

1)可重定向文件:文件保存着代碼和適當的數據,用來和其餘的目標文件一塊兒來建立一個可執行文件或者是一個共享目標文件。(目標文件或者靜態庫文件,即linux一般後綴爲.a和.o的文件)ide

2)可執行文件:文件保存着一個用來執行的程序。(例如bash,gcc等)工具

3)共享目標文件:共享庫。文件保存着代碼和合適的數據,用來被下鏈接編輯器和動態連接器連接。(linux下後綴爲.so的文件。)oop

目標文件既要參與程序連接又要參與程序執行:編碼

 

 

通常的 ELF 文件包括三個索引表:ELF  header,Program  header  table,Section header table。spa

1)ELF  header:在文件的開始,保存了路線圖,描述了該文件的組織狀況。orm

2)Program  header  table:告訴系統如何建立進程映像。用來構造進程映像的目標文件必須具備程序頭部表,可重定位文件不須要這個表。htm

3)Section  header  table :包含了描述文件節區的信息,每一個節區在表中都有一項,每一項給出諸如節區名稱、節區大小這類信息。用於連接的目標文件必須包含節區頭部表,其餘目標文件能夠有,也能夠沒有這個表。

一、     分析ELF文件頭(ELF  header)

進入終端輸入:cd /usr/include/elf.h,查看ELF的文件頭包含整個文件的控制結構

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

代碼項含義:

  最開頭是16個字節的e_ident, 其中包含用以表示ELF文件的字符,以及其餘一些與機器無關的信息。開頭的4個字節值固定不變,爲0x7f和ELF三個字符。

    e_type 它標識的是該文件的類型。

    e_machine 代表運行該程序須要的體系結構。

    e_version 表示文件的版本。

    e_entry 程序的入口地址。

    e_phoff 表示Program header table 在文件中的偏移量(以字節計數)。

    e_shoff 表示Section header table 在文件中的偏移量(以字節計數)。

    e_flags 對IA32而言,此項爲0。

    e_ehsize 表示ELF header大小(以字節計數)。

    e_phentsize 表示Program header table中每個條目的大小。

    e_phnum 表示Program header table中有多少個條目。

    e_shentsize 表示Section header table中的每個條目的大小。

    e_shnum 表示Section header table中有多少個條目。

    e_shstrndx 包含節名稱的字符串是第幾個節(從零開始計數)。

  •  編寫一個簡單代碼elf1.c爲例:
#include <stdio.h>
void main()
{
    int a=20135318;
    printf(「Hello %d」,a);
}

進行編譯運行,生成elf.o的目標文件:gcc –c elf1.c –o elf1.o。

ls –l elf1.o查看文件大小,爲1032字節:

 

 

 

readelf –a elf1.o獲得下面的ELF頭文件的信息,以下圖:

經過上圖信息,能夠得出Elf Header的Size爲52bytes,因此可使用hexdump工具將頭文件的16進製表打開,或使用objdump –x elf1.o來顯示.o中各個段以及符號表的相關信息:

hexdump –x elf1 –n 64查看elf文件頭的16進製表(前64bytes)對格式進行分析。

注意:因爲intel及其兼容處理器使用小端法,此處的-x命令選項是一次性輸出兩個字節,457f實際表示的是7f45,以此類推。

第一行,對應e_ident[EI_NIDENT]。實際表示內容爲7f454c46010101000000000000000000,前四個字節7f454c46(0x45,0x4c,0x46是'e','l','f'對應的ascii編碼)是一個魔數,表示這是一個ELF對象。接下來的一個字節01表示是一個32位對象(02是64位對象),接下來的一個字節01表示是小端法表示,再接下來的一個字節01表示文件頭版本。剩下的默認都設置爲0.

第二行,e_type(兩字節)值爲0x0001,表示是一個重定位文件。

           e_machine(兩字節)值爲0x0003,表示是Intel 80386處理器體系結構。

           e_version(四字節)值爲0x00000001,表示是當前版本。

           e_entry(四字節)值爲0x00000000,表示沒有入口點。

           e_phoff(四字節)值爲0x00000000,表示程序頭表。

第三行,e_shoff(四字節)值爲0x00000124,表示段表的偏移地址。

           e_flags(四字節)值爲0x00000000,表示未知處理器特定標誌(#define EF_SH_UNKNOWN 0x0)。

           e_ehsize(兩字節)值爲0x0034,表示elf文件頭大小爲0x34H(正好是52個字節)。

           e_phentsize(兩字節)值爲0x0000,表示一個program header大小爲0。

           e_phnum(兩字節)的值爲0x0000,給出program header表中的入口數目。

           e_shentsize(兩字節)值爲0x0028表示段頭大小爲40字節。

第四行,e_shnum(兩字節)值爲0x000d,表示段表入口有13個。

           e_shstrndx(兩字節)值爲0x000a,表示段名串表的在段表中的索引號(由此知.shstrtab段(符號表)的信息在段表的索引號是10)。


2、經過文件頭找到section header table,理解其內容

剛纔已經使用objdump –x elf1.o來顯示.o中各個段以及符號表的相關信息,如今能夠輸入:readelf –a elf1來查看各個段信息:

段表Section header table

 

符號表 Symbol table

再用readelf –s elf1.o查看:

3、經過section header table找到各section

  在一個ELF文件中有一個section header table,經過它咱們能夠定位到全部的 section,而 ELF header 中的e_shoff 變量就是保存 section header table 入口對文件頭的偏移量。而每一個 section 都會對應一個 section  header ,因此只要在 section  header  table 中找到每一個 section header,就能夠經過 section header 找到你想要的 section。

  ELF header獲得了e_shoff變量的值爲0X00000124,也就是table入口的偏移量,經過看e_shnum值爲0x000d,表示段表入口有13個。

  因此從0x00000124開始有13個段,每一個段佔40個字節大小,輸入 hexdump elf1查看:

第一個段,其中內容所有爲0,因此不表示任何段。

 

第二個段,爲.text段,段偏移sh_offset爲0X0034,段大小sh_size爲0X0027。

 

第三個段,爲.rel.text段,段偏移sh_offset爲0X03f0,段大小sh_size爲0X0010。

 

.......

下面用readelf –S elf1.o命令先去看看elf1的section table中存放的全部的 section header。

 

首先,咱們能夠用readelf 命令去查看.text這個 section 中的內容,輸入readelf –x 1 elf1.o,對1索引號的.text的section的內容進行查看;

其次,也用 hexdump 的方法去讀取.text這個 section 中的內容,經過看section header中.text中offset和size分別是0x000034和0x000027,經過16進制向10進制轉換獲得offset:52和size:39。輸入 hexdump –s 52–n 39 –C elf1。獲得了和上面的readelf獲得的相同。

最後再用使用下面命令對elf1的文本段(.text)進行反彙編,objdump –d elf1  獲得以下圖:

 

 

能夠看出,使用反彙編的16進制數據和前面查找到的是相同的。

4、理解常見.text .strtab .symtab .rodata等section

①.text section是可執行指令的集合,.data和.text都是屬於PROGBITS類型的section,這是未來要運行的程序與代碼。查詢段表可知.text section的位偏移爲0x0000440,size爲0x0000192。

②.strtab section是屬於STRTAB類型的section,能夠在文件中看到,它存着字符串,儲存着符號的名字。位偏移爲0x0001f08,size爲0x0000238。

③.symtab section存放全部section中定義的符號名字,好比「data_items」,「start_loop」。 .symtab section是屬於SYMTAB類型的section,它描述了.strtab中的符號在「內存」中對應的「內存地址」。 位偏移爲0x00018f0,size爲0x0000618。

④.rodata section,ro表明read only,即只讀數據(const)。位偏移爲0x00005e0,size爲0x000000c。

相關文章
相關標籤/搜索