日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 單片機(jī) > 程序喵大人

ELF(可執(zhí)行和鏈接格式)是 Linux 系統(tǒng)中用于可執(zhí)行文件和共享庫的文件格式。它定義了如何將一個文件加載到內(nèi)存中并執(zhí)行。ELF 文件主要包含以下幾部分:

  • ELF 頭:包含文件的基本信息,如文件類型、入口點地址等。
  • 程序頭表(Program Header Table)(PHT):描述如何將文件的各個部分加載到內(nèi)存中。
  • 節(jié)(Sections):包含代碼、數(shù)據(jù)等具體內(nèi)容。
  • 節(jié)頭表(Section Header Table)(SHT):描述各個部分的詳細(xì)信息。

ELF視圖

看這個圖:

在討論ELF文件時,通常會提到兩種視圖:鏈接視圖(Linking View)執(zhí)行視圖(Execution View)。

鏈接視圖

鏈接視圖是從鏈接器的角度來看待ELF文件的結(jié)構(gòu)。

鏈接視圖關(guān)注的是文件中的節(jié)(Section),ELF未被加載到內(nèi)存執(zhí)行前,以section 為單位組織數(shù)據(jù),這些 section 包含代碼、數(shù)據(jù)、符號表、重定位信息等。每個 section 都有特定的用途,例如.text節(jié)用于存放代碼,.data節(jié)用于存放初始化的數(shù)據(jù),.bss節(jié)用于存放未初始化的數(shù)據(jù)。

主要的section有:

  • .rodata:只讀數(shù)據(jù)
  • .text:可執(zhí)行代碼
  • .plt:程序鏈接表,用于過程調(diào)用和跳轉(zhuǎn)
  • 各種重定位表(.rel.plt, .rel.dyn等):指導(dǎo)動態(tài)鏈接
  • .dynsym:動態(tài)符號表
  • .dynstr:動態(tài)字符串表
  • .data:已初始化數(shù)據(jù)
  • .bss:未初始化數(shù)據(jù)
  • .init_array/.fini_array:程序初始化和終止時執(zhí)行的代碼
  • .got:全局偏移表
  • .symtab:符號表

執(zhí)行視圖

ELF 被加載到內(nèi)存后,也就是執(zhí)行后的視圖。執(zhí)行視圖是從操作系統(tǒng)加載器的角度來看待ELF文件的結(jié)構(gòu),執(zhí)行視圖關(guān)注的是文件中的段(Segment),這些段定義了程序在內(nèi)存中的布局和權(quán)限。執(zhí)行視圖主要用于程序的加載和執(zhí)行階段。

段是內(nèi)存映射的單位,定義了程序的代碼和數(shù)據(jù)在內(nèi)存中的布局。常見的段包括可加載段(LOAD)、動態(tài)段(DYNAMIC)、解釋器段(INTERP)等。操作系統(tǒng)根據(jù)段的信息將程序的代碼和數(shù)據(jù)映射到進(jìn)程的虛擬內(nèi)存空間。每個段有特定的權(quán)限標(biāo)志(例如,可讀、可寫、可執(zhí)行),用于保護(hù)內(nèi)存訪問。

  • 鏈接視圖關(guān)注section,用于編譯和鏈接階段。
  • 執(zhí)行視圖關(guān)注segment,用于程序的加載和執(zhí)行階段,可以這樣理解,一個segment,至少包含一個section。

也可以這樣理解:鏈接視圖是鏈接器處理文件時的視角,而執(zhí)行視圖是操作系統(tǒng)加載和運(yùn)行程序時的視角。

本項目使用的 PLT HOOK 并不是修改磁盤上的 ELF 文件,而是在運(yùn)行時修改內(nèi)存中的數(shù)據(jù),因此我們主要關(guān)心的是執(zhí)行視圖,即 ELF 被加載到內(nèi)存后,ELF 中的數(shù)據(jù)是如何組織和存放的。

linker 依據(jù) ELF 文件執(zhí)行視圖中的信息,用 mmap 將 ELF 加載到內(nèi)存中,執(zhí)行 relocation(重定位)把外部引用的絕對地址填入 GOT 表和 DATA 中,然后設(shè)置內(nèi)存頁的權(quán)限,最后調(diào)用 init_array 中的各個初始化函數(shù)。

PLT hook 執(zhí)行的時機(jī)是在 linker 完全加載完 ELF 之后,我們需要解析內(nèi)存中的 ELF 數(shù)據(jù),然后修改 relocation 的結(jié)果。

ELF 結(jié)構(gòu)

看這個Header(https://github.com/bminor/glibc/blob/master/elf/elf.h#L97):

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

ELF Header是整個文件的起始部分,它包含以下關(guān)鍵字段:

  • e_ident: 標(biāo)識信息,包括魔數(shù)(0x7F 'E' 'L' 'F')等。
  • e_type: 文件類型(例如,ET_EXEC表示可執(zhí)行文件,ET_DYN表示共享庫)。
  • e_machine: 目標(biāo)機(jī)器架構(gòu)(例如,EM_X86_64表示x86_64架構(gòu))。
  • e_version: ELF版本。
  • e_entry: 程序入口點地址。
  • e_phoff: Program Header Table的偏移。
  • e_shoff: Section Header Table的偏移。
  • e_flags: 與架構(gòu)相關(guān)的標(biāo)志。
  • e_ehsize: ELF Header的大小。
  • e_phentsize: Program Header Table中每個條目的大小。(執(zhí)行視圖)
  • e_phnum: Program Header Table中的條目數(shù)。
  • e_shentsize: Section Header Table中每個條目的大小。(鏈接視圖)
  • e_shnum: Section Header Table中的條目數(shù)。
  • e_shstrndx: 包含節(jié)名稱字符串表的節(jié)索引。

Program Header Table

看代碼(https://github.com/bminor/glibc/blob/master/elf/elf.h#L707):

typedef struct {  Elf64_Word        p_type;                  /* Segment type */  Elf64_Word        p_flags;                /* Segment flags */  Elf64_Off        p_offset;                /* Segment file offset */  Elf64_Addr        p_vaddr;                /* Segment virtual address */  Elf64_Addr        p_paddr;                /* Segment physical address */  Elf64_Xword        p_filesz;                /* Segment size in file */  Elf64_Xword        p_memsz;                /* Segment size in memory */  Elf64_Xword        p_align;                /* Segment alignment */ } Elf64_Phdr; 

Program Header Table用于描述段的信息,每個條目包含:

  • p_type: 段類型(例如,PT_LOAD表示可加載段),具體詳見(https://github.com/bminor/glibc/blob/master/elf/elf.h#L717):
#define PT_NULL   0 /* Program header table entry unused */ #define PT_LOAD   1 /* Loadable program segment */ #define PT_DYNAMIC  2 /* Dynamic linking information */ #define PT_INTERP 3 /* Program interpreter */ #define PT_NOTE   4 /* Auxiliary information */ #define PT_SHLIB  5 /* Reserved */ #define PT_PHDR   6 /* Entry for header table itself */ #define PT_TLS    7 /* Thread-local storage segment */ #define PT_NUM    8 /* Number of defined types */ #define PT_LOOS   0x60000000 /* Start of OS-specific */ #define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ #define PT_GNU_STACK  0x6474e551 /* Indicates stack executability */ #define PT_GNU_RELRO  0x6474e552 /* Read-only after relocation */ #define PT_GNU_PROPERTY 0x6474e553 /* GNU property */ #define PT_GNU_SFRAME 0x6474e554 /* SFrame segment.  */ #define PT_LOSUNW 0x6ffffffa #define PT_SUNWBSS  0x6ffffffa /* Sun Specific segment */ #define PT_SUNWSTACK  0x6ffffffb /* Stack segment */ #define PT_HISUNW 0x6fffffff #define PT_HIOS   0x6fffffff /* End of OS-specific */ #define PT_LOPROC 0x70000000 /* Start of processor-specific */ #define PT_HIPROC 0x7fffffff /* End of processor-specific */ 
  • p_offset: 段在文件中的偏移。
  • p_vaddr: 段在內(nèi)存中的虛擬地址。
  • p_paddr: 段在內(nèi)存中的物理地址(通常未使用)。
  • p_filesz: 段在文件中的大小。
  • p_memsz: 段在內(nèi)存中的大小。
  • p_flags: 段的權(quán)限標(biāo)志(例如,可讀、可寫、可執(zhí)行)。
  • p_align: 段的對齊要求。

Section Header Table

看代碼(https://github.com/bminor/glibc/blob/master/elf/elf.h#L409):

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

Section Header Table用于描述節(jié)的信息,每個條目包含:

  • sh_name: section 名稱字符串表中的索引。
  • sh_type: section 類型(例如,SHT_PROGBITS表示程序代碼或數(shù)據(jù)),具體詳見(https://github.com/bminor/glibc/blob/master/elf/elf.h#L430):
/* Legal values for sh_type (section type).  */  #define SHT_NULL    0 /* Section header table entry unused */ #define SHT_PROGBITS    1 /* Program data */ #define SHT_SYMTAB    2 /* Symbol table */ #define SHT_STRTAB    3 /* String table */ #define SHT_RELA    4 /* Relocation entries with addends */ #define SHT_HASH    5 /* Symbol hash table */ #define SHT_DYNAMIC   6 /* Dynamic linking information */ #define SHT_NOTE    7 /* Notes */ #define SHT_NOBITS    8 /* Program space with no data (bss) */ #define SHT_REL     9 /* Relocation entries, no addends */ #define SHT_SHLIB   10 /* Reserved */ #define SHT_DYNSYM    11 /* Dynamic linker symbol table */ #define SHT_INIT_ARRAY    14 /* Array of constructors */ #define SHT_FINI_ARRAY    15 /* Array of destructors */ #define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ #define SHT_GROUP   17 /* Section group */ #define SHT_SYMTAB_SHNDX  18 /* Extended section indices */ #define SHT_RELR    19 /* RELR relative relocations */ #define SHT_NUM     20 /* Number of defined types.  */ #define SHT_LOOS    0x60000000 /* Start OS-specific.  */ #define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes.  */ #define SHT_GNU_HASH    0x6ffffff6 /* GNU-style hash table.  */ #define SHT_GNU_LIBLIST   0x6ffffff7 /* Prelink library list */ #define SHT_CHECKSUM    0x6ffffff8 /* Checksum for DSO content.  */ #define SHT_LOSUNW    0x6ffffffa /* Sun-specific low bound.  */ #define SHT_SUNW_move   0x6ffffffa #define SHT_SUNW_COMDAT   0x6ffffffb #define SHT_SUNW_syminfo  0x6ffffffc #define SHT_GNU_verdef    0x6ffffffd /* Version definition section.  */ #define SHT_GNU_verneed   0x6ffffffe /* Version needs section.  */ #define SHT_GNU_versym    0x6fffffff /* Version symbol table.  */ #define SHT_HISUNW    0x6fffffff /* Sun-specific high bound.  */ #define SHT_HIOS    0x6fffffff /* End OS-specific type */ #define SHT_LOPROC    0x70000000 /* Start of processor-specific */ #define SHT_HIPROC    0x7fffffff /* End of processor-specific */ #define SHT_LOUSER    0x80000000 /* Start of application-specific */ #define SHT_HIUSER    0x8fffffff /* End of application-specific */ 
  • sh_flags: section 標(biāo)志(例如,可寫、可分配、可執(zhí)行)。
  • sh_addr: section 在內(nèi)存中的地址。
  • sh_offset: section 節(jié)在文件中的偏移。
  • sh_size: section 的大小。
  • sh_link: 與section 相關(guān)的鏈接信息。
  • sh_info: 附加信息。
  • sh_addralign: section 的對齊要求。
  • sh_entsize: 如果section 包含固定大小的條目,則為每個條目的大小。

常見的Section

  • .text: 包含程序的可執(zhí)行代碼。
  • .data: 包含初始化的全局和靜態(tài)變量。
  • .bss: 包含未初始化的全局和靜態(tài)變量,實際在文件中不占空間。
  • .rodata: 包含只讀數(shù)據(jù),例如字符串常量。
  • .symtab: 包含符號表,用于鏈接。
  • .strtab: 包含字符串表,通常用于符號表中的符號名稱。
  • .rel.text: 包含與.text節(jié)相關(guān)的重定位信息。
  • .debug: 包含調(diào)試信息。

Segment

Segment是程序運(yùn)行時的內(nèi)存映射單位,常見的段包括:

  • LOAD段: 包含可加載的代碼和數(shù)據(jù),映射到進(jìn)程的虛擬內(nèi)存空間。
  • DYNAMIC段: 包含動態(tài)鏈接信息。
  • INTERP段: 指定程序運(yùn)行時使用的解釋器(例如,動態(tài)鏈接器)。
  • NOTE段: 包含附加信息,如版本信息。

ELF文件結(jié)構(gòu)通過Header、Segment和Section的組合,提供了一個靈活的機(jī)制來描述程序的代碼和數(shù)據(jù)布局。

本項目的PLTHOOK主要關(guān)注的就是DYNAMIC段。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉