elf文件結構解讀以及plt節got節的理解


前言:

  熟悉elf文件結構是一件很不錯的事,因為安卓中的so加固以及修復都是需要這些知識的,包括pwn里面的rop之類的,也都是

和got節,plt節息息相關的,個人建議是在搞懂elf文件結構后,自己實現一個解析器,把注釋寫好,方便忘了再進一步重溫,寫的不好

見諒。

一. elf文件概述

elf文件包括了可執行文件,共享文件,目標文件這三類,其中安卓中涉及到的就是so文件,這個其實就是一個共享文件,類似

windows上的dll文件,目標文件是匯編文件,后綴為.o的文件,與可執行文件不同的是,並沒有段頭表,因為段是由相同功能的

節組合成的,而目標文件只是一個模塊,並沒有和其他模塊進行鏈接,也就是節也沒有合並,所以不存在段這個概念,程序的入口點

地址也是為空的,可執行文件和共享文件的話,大體結構和目標文件相同,多了段的概念,然后提供了兩種視圖(鏈接視圖和裝載視圖)

二.elf文件結構

 

看起來其實不復雜,文件頭,程序頭表,節頭表,節,段(其實就是相同功能節的組合體),接下來單獨說說各個部分

三.elf文件頭

這里搬出來010editor來看,這里是我導入之前做的crackme的so文件

 

 好像名字奇奇怪怪的,我直接搬上,elf結構體定義

typedef struct
 
{
 
    unsigned char e_ident[EI_NIDENT];  /* Magic number and other info */
 
    Elf32_Half   e_type;         /* Object file type */
 
    Elf32_Half   e_machine;       /* Architecture */
 
    Elf32_Word   e_version;       /* Object file version */
 
    Elf32_Addr   e_entry;    /* Entry point virtual address */
 
    Elf32_Off   e_phoff;    /* Program header table file offset */
 
    Elf32_Off   e_shoff;    /* Section header table file offset */
 
    Elf32_Word   e_flags;    /* Processor-specific flags */
 
    Elf32_Half   e_ehsize;       /* ELF header size in bytes */
 
    Elf32_Half   e_phentsize;     /* Program header table entry size */
 
    Elf32_Half   e_phnum;    /* Program header table entry count */
 
    Elf32_Half   e_shentsize;     /* Section header table entry size */
 
    Elf32_Half   e_shnum;    /* Section header table entry count */
 
    Elf32_Half   e_shstrndx;      /* Section header string table index */
 
} Elf32_Ehdr;

重點說說幾個字段,沒說的說明比較簡單易懂

1. e_ident:魔數,標識是哪個文件

2. e_phoff:程序頭表在文件中的偏移

3. e_shoff: 程序節表在文件中的編譯

4.e_phentsize: elf頭占多少字節,32位的so,一般為52個字節

5. e_phnum: 程序頭表中有關程序頭的結構體個數,類似一個int數組,中int的個數

6. e_shnum:  和e_phnum差不多,把主語換成節頭表

7. e_shstrndx: .strtab節在節頭表的下標,因為里面存着所有節的名字

四.節頭表解析

typedef struct
{
  Elf32_Word    sh_name;        /* Section name (string tbl index) */
  Elf32_Word    sh_type;        /* Section type */
  Elf32_Word    sh_flags;        /* Section flags */
  Elf32_Addr    sh_addr;        /* Section virtual addr at execution */
  Elf32_Off    sh_offset;        /* Section file offset */
  Elf32_Word    sh_size;        /* Section size in bytes */
  Elf32_Word    sh_link;        /* Link to another section */
  Elf32_Word    sh_info;        /* Additional section information */
  Elf32_Word    sh_addralign;        /* Section alignment */
  Elf32_Word    sh_entsize;        /* Entry size if section holds table */
} Elf32_Shdr;

節頭表的結構如上圖,實際上節頭表就是上圖結構體的數組,里面的數量是上面elf文件頭中的e_shnum決定的,但是注意這個結構體並不是我們所想的節

也只是一個中間過渡的東西,只是定義了每個節在文件的哪個位置,名字叫什么,大小,類型是什么,具體的內容,還要根據其中定義好的偏移和大小再

去查找,接下來說說每個字段的含義

1.sh_name  是字符串節的下表,通常是先根據文件頭中的strndx字段找到字符串節,然后再根據這個sh_name,找到節的名字

2. sh_type  表明這個節的類型是什么,內容比較多,直接上圖

 

 3.sh_flag 表明這個節是否可讀可寫可執行,記憶性的東西,直接上圖

 

 

4.sh_addr  將會映射到虛擬內存空間中的地址

5.sh_size 和sh_off: 前一個是節的大小,后一個是節在文件中的偏移

在linux上也可以通過readelf -S xxx(文件名)進行查看

 

 五. 特殊的節

五.1  .symtab

符號表的節,一般的so文件都會被抹去,怕被反編譯,直接還原出符號名,也是一個結構體數組

 

 st_name: 在字符串表中的下標

st_value :真正的值

st_size: 大小

st_info: 符號類別

 

 畢竟符號分為局部符號,全局符號,還得標記是不是動態鏈接的

st_stndx: 符號屬於哪個段,那個段在節頭表的下標

挑了個so文件,發現里面的符號表已經被抹去了,-s只能查看.dynsym這個動態鏈接的節了

 

 2..dynsym和.dynstr

動態鏈接符號表,里面主要存放着動態鏈接的符號,.dynstr里面主要存放動態鏈接符號的字符串名,

3. .rel.節名

重定位的表,很重要,因為這個表需要告訴linker哪個符號需要重定位

4. .plt節和.got節

出現.plt節的原因是有延遲綁定機制,因為動態鏈接中,符號很多,而且有些符號還沒用到

那么重定位的負擔就很重,所以就出現了延遲綁定,只有用到了該符號再進行綁定(這里的綁定主要說的是got表中填入符號的地址)

所以匯編代碼大概是這樣的:

 

jmp 后面的地址,是got表中的內容,但是如果沒用過這個符號,里面填寫的是push n的地址,也就是跳轉到下一條指令了,

然后在把got表的下標和模塊的id入棧,調用符號綁定的函數,實現延遲綁定,所以.plt節實際上就是一個got表的跳板,

六.程序頭表(segment)
elf可分為兩種視圖,一種是鏈接視圖,還有一種是裝載視圖

 

 實際上不需要想的很復雜,段實際上就是相同功能的節的集合,本質上還是節,不過裝載過程中所需的信息只和段有關,這也是為什么so加固中,可以去動節的一些信息,為我們解殼提供便利

typedef struct

{
   Elf32_Word    p_type;             / *  Segment  type  * /
   Elf32_Off    p_offset;           / *  Segment  file  offset  * /
   Elf32_Addr    p_vaddr;         / *  Segment virtual address  * /
   Elf32_Addr    p_paddr;         / *  Segment physical address  * /
   Elf32_Word    p_filesz;         / *  Segment size  in  file  * /
   Elf32_Word    p_memsz;         / *  Segment size  in  memory  * /
   Elf32_Word    p_flags;         / *  Segment flags  * /
   Elf32_Word    p_align;         / *  Segment alignment  * /
} Elf32_Phdr;

 也是一個結構體數組,注釋也寫得很清楚了。略

 

總結: 重心還是在節那塊,參考了程序員自我修養,和看雪的幾篇文章,但是看雪文章明顯不如書有精華了,建議還是看看書


免責聲明!

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



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