linux逆向分析之ELF文件詳解

前言

首先如果大家遇到ELF二進制文件的逆向首先考慮的可能就是通過IDA進行靜態逆向分析算法,那麼我們首先就要了解ELF(Executable
and Linking Format)的文件格式。
ELF文件格式主要分爲以下幾類:
1. 可重定位文件(Relocatable File),這類文件包含了代碼和數據,可以被用來鏈接成可執行文件或共享目標文件,靜態鏈接庫也可以歸爲這一類,如.o文件。
2. 可執行文件(Executable File),這類文件包含了直接執行的程序,如/bin/bash等。
3. 共享目標文件(Shared Object File),鏈接器可以使用這種文件跟其他的可重定位文件和共享目標文件鏈接,產生新的目標文件;動態鏈接器可以將幾個共享目標文件與可執行文件結合,作爲進程映像的一部分來運行,如glibc***.so。
4. 核心轉儲文件(Core Dump File),當進程意外終止時,系統可以將該進程的地址空間內容及終止時的一些其他信息轉儲到核心轉儲文件。
一.elf文件格式詳解

以上是elf文件格式結構示意圖
文件頭
文件頭的結構定義如下所示:
typedef struct {
unsigned char e_ident[16]; /* ELF魔數,ELF字長,字節序,ELF文件版本等 */
Elf32_Half e_type; /*ELF文件類型,REL, 可執行文件,共享目標文件等 */
Elf32_Half e_machine; /* ELF的CPU平臺屬性 */
Elf32_Word e_version; /* ELF版本號 */
Elf32_Addr e_entry; /* ELF程序的入口虛擬地址,REL一般沒有入口地址爲0 */
Elf32_Off e_phoff;
Elf32_Off e_shoff; /* 段表在文件中的偏移 */
Elf32_Word e_flags; /* 用於標識ELF文件平臺相關的屬性 */
Elf32_Half e_ehsize; /* 本文件頭的長度 */
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize; /* 段表描述符的大小 */
Elf32_Half e_shnum; /* 段表描述符的數量 */
Elf32_Half e_shstrndx; /* 段表字符串表所在的段在段表中的下標 */
} Elf32_Ehdr;
利用readelf命令可以查看elf文件的頭部信息,大家可以對照着看

結構的各個成員的含義如註釋中所解釋的。對ELF文件,有兩個視圖,一個是從裝載運行角度的,另一個是從連接角度的。從裝載運行角度,我們關注的是程序頭表,由程序頭表的指引把ELF文件加載進內存運行它。從連接的角度,我們關注節頭表,由節頭表的指引把各個節連接組裝起來。e_type的值與這兩個視圖相聯繫,由它我們可以知道能夠從哪個視圖去解讀。
如果e_type=1,表明它是重定位文件,可以從連接視圖去解讀它;
如果e_type=2,表明它是可執行文件,至少可以從裝載運行視圖去解讀它;
如果e_type=3,表明它是共享動態庫文件,同樣可以至少從裝載運行視圖去解讀它;
如果e_type=4,表明它是Coredump文件,可以從哪個視圖去解讀依賴於具體的實現。
如上圖顯示的是可執行文件那麼我就要從裝在運行視圖去解讀它

按照這兩個視圖,整個ELF文件的內容這樣來組織:
首先是ELF文件頭,也就是上面的Elf32_Ehdr結構。或者對64位的ELF文件,是Elf64_Ehdr結構。ELF文件頭位於文件開始處,無論e_type的值是什麼,它是必須有的。
其次是程序頭表,對可執行文件(e_type=2)和動態庫文件(e_type=3),它是必須有的。對重定位文件(e_type=1),程序頭表的有無是可選的。例如用gcc的-c選項生成的.o文件,就沒有程序頭表。但無論如何,e_phoff和e_phnum、e_phentsize給出了ELF文件的程序頭表信息。沒有程序頭表時它們的值爲零。
然後就是就是節頭表,對可執行文件和動態庫文件,它的有無是可選的,對重定位文件,它是必須有的。
Program header table
每個程序頭表的每個表項的結構爲:
typedefstruct
{
Elf32_Wordp_type;/*段類型*/
Elf32_Offp_offset;/*在文件中的偏移*/
Elf32_Addrp_vaddr;/*執行時的虛地址*/
Elf32_Addrp_paddr;/*執行時的物理地址*/
Elf32_Wordp_filesz;/*在文件中的字節數*/
Elf32_Wordp_memsz;/*在內存中的字節數*/
Elf32_Wordp_flags;/*標誌*/
Elf32_Wordp_align;/*字節對齊*/
}Elf32_Phdr;



那什麼是所謂 sections 呢?可以說,sections 是在ELF文件裏頭,用以裝載內容數據的最小容器。在ELF文件裏面,每一個 sections 內都裝載了性質屬性都一樣的內容,比方:

1) .text section 裏裝載了可執行代碼;

2) .data section 裏面裝載了被初始化的數據;

3) .bss section 裏面裝載了未被初始化的數據;

4) 以 .rec 打頭的 sections 裏面裝載了重定位條目;

5) .symtab 或者 .dynsym section 裏面裝載了符號信息;

6) .strtab 或者 .dynstr section 裏面裝載了字符串信息;

7) 其他還有爲滿足不同目的所設置的section,比方滿足調試的目的、滿足動態鏈接與加載的目的等等。

Section heafer table
每個節頭表的每個表項的結構爲:
typedefstruct
{
Elf32_Wordsh_name;/*節名索引*/
Elf32_Wordsh_type;/*節類型*/
Elf32_Wordsh_flags;/*加載和讀寫標誌*/
Elf32_Addrsh_addr;/*執行時的虛地址*/
Elf32_Offsh_offset;/*在文件中的偏移*/
Elf32_Wordsh_size;/*字節大小*/
Elf32_Wordsh_link;/*與其他節的關聯*/
Elf32_Wordsh_info;/*其他信息*/
Elf32_Wordsh_addralign;/*字節對齊*/
Elf32_Wordsh_entsize;/*如果由表項組成,每個表項的大小*/
}Elf32_Shdr;


這裏我們來討論一下連接視圖中section與裝載運行視圖segments之間的關係。
鏈接器在鏈接可執行文件或動態庫的過程中,它會把來自不同可重定位對象文件中的相同名稱的 section 合併起來構成同名的 section。接着,它又會把帶有相同屬性(比方都是隻讀並可加載的)的 section 都合併成所謂 segments(段)。segments 作爲鏈接器的輸出,常被稱爲輸出section。

一個單獨的 segment 通常會包含幾個不同的 sections,比方一個可被加載的、只讀的segment 通常就會包括可執行代碼section .text、只讀的數據section .rodata以及給動態鏈接器使用的符號section .dymsym等等。section 是被鏈接器使用的,但是 segments 是被加載器所使用的。加載器會將所需要的 segment 加載到內存空間中運行。和用 sections header table 來指定一個可重定位文件中到底有哪些 sections 一樣。在一個可執行文件或者動態庫中, program header table中包含有 segments。

在當我們執行命令readelf -l讀取程序表頭的時候,結果顯示,在可執行文件中,總共有8個 segments程序頭。同時,該結果也很明白顯示出了哪些 section 映射到哪一個 segment 當中去。比方在索引爲2的那個segment 中,總共有18個 sections 映射進來,其中包括我們前面提到過的 .text section。注意這個segment 有兩個標誌: R 和 E。這個表示該segment是可讀的,也可執行的。如果你看到標誌中有W,那表示該segment是可寫的。

上面類型爲PHDR的segment,用來包含程序頭表本身。類型爲INTERP的segment只包含一個 section,那就是 .interp。在這個section中,包含了動態鏈接過程中所使用的解釋器路徑和名稱。在Linux裏面,這個解釋器實際上就是 /lib/ ,這可以通過下面的 hexdump 看出來:[yihect@juliantec test_2]$ hexdump -s 0x134 -n 32 -C ./ElfCrackme2 
$ hexdump -s 0x134 -n 32 -C ./ElfCrackMe2
00000134 2f 6c 69 62 2f 6c 64 2d 6c 69 6e 75 78 2e 73 6f |/lib/ld-linux.so|
00000144 2e 32 00 00 04 00 00 00 10 00 00 00 01 00 00 00 |.2..............|
00000154
關於ELF格式的知識就說到這,想了解更多的去了解下大牛的文章點擊打開鏈接
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章