1. 程式人生 > 其它 >ELF檔案格式第三講,節頭(section header)

ELF檔案格式第三講,節頭(section header)

目錄

ELF檔案格式第三講,節頭(section header)

一丶節頭

1.1 概念簡介

​ 段(segment) 和 節(section)是有區別的。 節不是段。 段是程式執行的必要組成部分。 在每個段中會有程式碼或者資料被劃分為不同的節。 而 節頭表 則是對這些節的位置和大小的描述,主要是用於連結和除錯。

因為節頭表沒有對程式的記憶體佈局進行描述,對程式記憶體佈局的描述的是 程式頭表(第二講)的任務。 所以

節頭表就是對程式頭的補充。所以我們將“節頭表”都填充為無用的值的話程式還是可以正常啟動的。 雖然可以修改,但是隨著版本的升級,保不準以後會使用。 就跟window平臺上的最小PE一樣,在xp下可以是100kb以下。win7下則對各個表的限制更嚴格了。所以需要100kb以上。 win10同理。 所以節頭表以後可能會使用。

readelf -l 顯示一個段對應有那些節。 很直觀的可以看到節和段的關係。
readelf -S 
......
Section to Segment mapping:
段節...
00
01     .interp
02     .interp .note.gnu.build-id .note.gnu.property .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt
03     .init .plt .text .fini
04     .rodata .eh_frame_hdr .eh_frame
05     .init_array .fini_array .dynamic .got .got.plt .data .bss
06     .dynamic
07     .note.gnu.build-id .note.gnu.property .note.ABI-tag
08     .note.gnu.property
09     .eh_frame_hdr
10
11     .init_array .fini_array .dynamic .got

1.2 節頭和節

​ 如果二進位制檔案中缺少了 節頭 ,並不意味著節是不存在的。只是沒有辦法通過節頭來引用節了,對於偵錯程式或者反編譯(IDA)程式來說,參考的資訊就變少了。

​ 每一個節都儲存了某種型別的程式碼和資料。 資料可以是程式中的全域性變數,也可以是聯結器所需要的動態連結的資訊。 這點跟windows平臺的 windowsPE檔案格式設計很像。 節頭可以被抹除,預設的ELF檔案是有節頭的。

如果節頭被抹除,那麼 objcopy objdump gdb IDA 等工具就可能無法使用。

而節頭表中的 .dynsym這樣的節(記錄了函式名和偏移地址,匯入匯出等符號)就無法分析。進而就增大了逆向的難度。

1.3 節頭 結構

  • 結構
/* Section Header */
typedef struct {
    Elf32_Word    sh_name;    /* name - index into section header
                       string table section */
    Elf32_Word    sh_type;    /* type */
    Elf32_Word    sh_flags;    /* flags */
    Elf32_Addr    sh_addr;    /* address */
    Elf32_Off    sh_offset;    /* file offset */
    Elf32_Word    sh_size;    /* section size */
    Elf32_Word    sh_link;    /* section header table index link */
    Elf32_Word    sh_info;    /* extra information */
    Elf32_Word    sh_addralign;    /* address alignment */
    Elf32_Word    sh_entsize;    /* section entry size */
} Elf32_Shdr;

typedef struct {
    Elf64_Half    sh_name;    /* section name */
    Elf64_Half    sh_type;    /* section type */
    Elf64_Xword    sh_flags;    /* section flags */
    Elf64_Addr    sh_addr;    /* virtual address */
    Elf64_Off    sh_offset;    /* file offset */
    Elf64_Xword    sh_size;    /* section size */
    Elf64_Half    sh_link;    /* link to another */
    Elf64_Half    sh_info;    /* misc info */
    Elf64_Xword    sh_addralign;    /* memory alignment */
    Elf64_Xword    sh_entsize;    /* table entry size */
} Elf64_Shdr;
  • 欄位含義如下

索引為0的表是 (SHN_UNDEF) 儘管這個表的意義是未定義的節區應用。

這個節區固定的值為如下:

010Edit中的取值為如下:

  • 欄位型別

    型別定義結果如下

  • sh_flag欄位

    此欄位定義了一個節區中包含的內容是否可以修改,是否可以執行的資訊。 如果一個標誌位被設定,則該位取值為1. 定義的各位都設定為0

SHF_EXECINSTR: 節區包含可執行的機器指令。

SHF_MASKPROC: 所有包含於刺眼嗎中的四位都用於處理器專用的語義

在32 or 64下欄位還增加了

typedef enum <Elf32_Xword> {
    SF32_None               = 0x0,     無
    SF32_Exec               = 0x1,     執行
    SF32_Alloc              = 0x2,     此節區執行過程中佔用記憶體。某些控制接續並不會出現於目標檔案的記憶體映像中,對於那些節區此值為0
    SF32_Alloc_Exec         = 0x3,
    SF32_Write              = 0x4,      寫
    SF32_Write_Exec         = 0x5,      寫執行
    SF32_Write_Alloc        = 0x6,      寫記憶體
    SF32_Write_Alloc_Exec   = 0x7
} s_flags32_e;

typedef enum <Elf64_Xword> {
    SF64_None               = 0x0,
    SF64_Exec               = 0x1,
    SF64_Alloc              = 0x2,
    SF64_Alloc_Exec         = 0x3,
    SF64_Write              = 0x4,
    SF64_Write_Exec         = 0x5,
    SF64_Write_Alloc        = 0x6,
    SF64_Write_Alloc_Exec   = 0x7
} s_flags64_e;
  • 節區型別於欄位

    根據節區型別的不同,那麼s_link s_info也是不同的。

    如下表

1.4特殊節區

下圖是系統中使用的節區以及他們的型別和屬性。 簡單概括圖。