一般的 ELF 文件包括三個索引表:ELF header,Program header table,Section header table。
1)ELF header:在文件的開始,保存了路線圖,描述了該文件的組織情況。
2)Program header table:告訴系統如何創建進程映像。用來構造進程映像的目標文件必須具有程序頭部表,可重定位文件不需要這個表。
3)Section header table :包含了描述文件節區的信息,每個節區在表中都有一項,每一項給出諸如節區名稱、節區大小這類信息。用於鏈接的目標文件必須包含節區頭部表,其他目標文件可以有,也可以沒有這個表。
一、分析ELF文件頭
vi /usr/include/elf.h查看elf頭數據結構
用readelf –h 1(可執行文件名)讀取一個簡單可執行文件的elf頭
可見elf頭大小為52字節,用dump命令16進制讀取前52個字節進行分析
命令:hexdump –x 1 –n 52
解析:
第一行,對應e_ident[EI_NIDENT]。小端法實際表示內容為7f454c46010101000000000000000000,前四個字節為elf固定開頭7f454c46(0x45,0x4c,0x46是'e','l','f'對應的ascii編碼),表示這是一個ELF對象。接下來的一個字節01表示是一個32位對象,接下來的一個字節01表示是小端法表示,再接下來的一個字節01表示文件頭版本。剩下的默認都設置為0.
第二行,e_type值為0x0002,表示是一個可執行文件。e_machine值為0x0003,表示是intel80386處理器體系結構。e_version值為0x00000001,表示是當前版本。e_entry值為0x08048320,表示入口點。e_phoff值為0x00000034,表示程序頭表的偏移量為0x34即52個字節剛好是elf頭大小。
第三行,e_shoff值為0x0000114c,表示節頭表的偏移地址。e_flags值為0x00000000,表示未知處理器特定標志。e_ehsize值為0x0034,表示elf文件頭大小52個字節。e_phentsize表示一個程序頭表中的入口(程序頭)的長度,值為0x0020即32字節。e_phnum的值為0x0009,給出程序頭表中的入口數目。e_shentsize值為0x0028表示節頭表入口(節頭)大小為40字節。
第四行,e_shnum值為0x001e,表示節頭表入口有30個。e_shstrndx值為0x001b,表示節名串表的在節表中的索引號。
二、通過文件頭找到section header table,理解其內容
vi /usr/include/elf.h查看節頭數據結構
使用readelf -S 1讀取節頭表
使用命令hexdump 1查看16進制值
由前面分析elf頭可知節頭表的偏移地址為0x0000114c即圖示位置開始為節頭表
可見全為0,如節頭表所示為空節
接着看第一個節
三個紅框分別是節的起始地址、偏移地址和大小,可以看出與readelf的顯示結果一致
隨后的40字節是第二個段,以此類推不再贅述
第十三個節.text節為可執行指令的集合
下面用 hexdump 的方法去讀取.text這個 section 中的內容,通過看section header中.text中offset和size分別是0x00000320和0x00000192,通過16進制向10進制轉換得到offset:800和size:402。
輸入 hexdump –s 800 –n 402 –C 1
然后使用readelf -x 13 1
兩者也是一致的
使用objdump -d 1查看.text節反匯編代碼
結果也是一致的
可以用同樣的方法分析其他節
三、理解常見.text .strtab .symtab .rodata等section
- .text section是可執行指令的集合,.data和.text都是屬於PROGBITS類型的section,這是將來要運行的程序與代碼。查詢段表可知.text section的位偏移為0x0000440,size為0x0000192。
- .strtab section是屬於STRTAB類型的section,可以在文件中看到,它存着字符串,儲存着符號的名字。位偏移為0x0001f08,size為0x0000238。