精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

UNIX/LINUX平臺可執(zhí)行文件格式分析

系統(tǒng) Linux
首先是對可執(zhí)行文件格式的一個綜述,并通過描述 ELF 文件加載過程以揭示可執(zhí)行文件內(nèi)容與加載運(yùn)行操作之間的關(guān)系。

本文討論了UNIX/LINUX 平臺下三種主要的可執(zhí)行文件格式:a.out(assembler and link editor output 匯編器和鏈接編輯器的輸出)、COFF(Common Object File Format 通用對象文件格式)、ELF(Executable and Linking Format 可執(zhí)行和鏈接格式)。首先是對可執(zhí)行文件格式的一個綜述,并通過描述 ELF 文件加載過程以揭示可執(zhí)行文件內(nèi)容與加載運(yùn)行操作之間的關(guān)系。隨后依此討論了此三種文件格式,并著重討論 ELF 文件的動態(tài)連接機(jī)制,其間也穿插了對各種文件格式優(yōu)缺點(diǎn)的評價。最后對三種可執(zhí)行文件格式有一個簡單總結(jié),并提出作者對可文件格式評價的一些感想。

可執(zhí)行文件格式綜述

相對于其它文件類型,可執(zhí)行文件可能是一個操作系統(tǒng)中最重要的文件類型,因為它們是完成操作的真正執(zhí)行者??蓤?zhí)行文件的大小、運(yùn)行速度、資源占用情況以及可擴(kuò)展性、可移植性等與文件格式的定義和文件加載過程緊密相關(guān)。研究可執(zhí)行文件的格式對編寫高性能程序和一些黑客技術(shù)的運(yùn)用都是非常有意義的。

不管何種可執(zhí)行文件格式,一些基本的要素是必須的,顯而易見的,文件中應(yīng)包含代碼和數(shù)據(jù)。因為文件可能引用外部文件定義的符號(變量和函數(shù)),因此重定位信息和符號信息也是需要的。一些輔助信息是可選的,如調(diào)試信息、硬件信息等?;旧先我庖环N可執(zhí)行文件格式都是按區(qū)間保存上述信息,稱為段(Segment)或節(jié)(Section)。不同的文件格式中段和節(jié)的含義可能有細(xì)微區(qū)別,但根據(jù)上下文關(guān)系可以很清楚的理解,這不是關(guān)鍵問題。最后,可執(zhí)行文件通常都有一個文件頭部以描述本文件的總體結(jié)構(gòu)。

相對可執(zhí)行文件有三個重要的概念:編譯(compile)、連接(link,也可稱為鏈接、聯(lián)接)、加載(load)。源程序文件被編譯成目標(biāo)文件,多個目標(biāo)文件被連接成一個最終的可執(zhí)行文件,可執(zhí)行文件被加載到內(nèi)存中運(yùn)行。因為本文重點(diǎn)是討論可執(zhí)行文件格式,因此加載過程也相對重點(diǎn)討論。下面是LINUX平臺下ELF文件加載過程的一個簡單描述。

1:內(nèi)核首先讀ELF文件的頭部,然后根據(jù)頭部的數(shù)據(jù)指示分別讀入各種數(shù)據(jù)結(jié)構(gòu),找到標(biāo)記為可加載(loadable)的段,并調(diào)用函數(shù) mmap()把段內(nèi)容加載到內(nèi)存中。在加載之前,內(nèi)核把段的標(biāo)記直接傳遞給 mmap(),段的標(biāo)記指示該段在內(nèi)存中是否可讀、可寫,可執(zhí)行。顯然,文本段是只讀可執(zhí)行,而數(shù)據(jù)段是可讀可寫。這種方式是利用了現(xiàn)代操作系統(tǒng)和處理器對內(nèi)存的保護(hù)功能。著名的Shellcode(參考資料 17)的編寫技巧則是突破此保護(hù)功能的一個實際例子。

2:內(nèi)核分析出ELF文件標(biāo)記為 PT_INTERP 的段中所對應(yīng)的動態(tài)連接器名稱,并加載動態(tài)連接器?,F(xiàn)代 LINUX 系統(tǒng)的動態(tài)連接器通常是 /lib/ld-linux.so.2,相關(guān)細(xì)節(jié)在后面有詳細(xì)描述。

3:內(nèi)核在新進(jìn)程的堆棧中設(shè)置一些標(biāo)記-值對,以指示動態(tài)連接器的相關(guān)操作。

4:內(nèi)核把控制傳遞給動態(tài)連接器。

5:動態(tài)連接器檢查程序?qū)ν獠课募?共享庫)的依賴性,并在需要時對其進(jìn)行加載。

6:動態(tài)連接器對程序的外部引用進(jìn)行重定位,通俗的講,就是告訴程序其引用的外部變量/函數(shù)的地址,此地址位于共享庫被加載在內(nèi)存的區(qū)間內(nèi)。動態(tài)連接還有一個延遲(Lazy)定位的特性,即只在"真正"需要引用符號時才重定位,這對提高程序運(yùn)行效率有極大幫助。

7:動態(tài)連接器執(zhí)行在ELF文件中標(biāo)記為 .init 的節(jié)的代碼,進(jìn)行程序運(yùn)行的初始化。在早期系統(tǒng)中,初始化代碼對應(yīng)函數(shù) _init(void)(函數(shù)名強(qiáng)制固定),在現(xiàn)代系統(tǒng)中,則對應(yīng)形式為

void

__attribute((constructor))

init_function(void)

{

……

}

其中函數(shù)名為任意。

    8:動態(tài)連接器把控制傳遞給程序,從 ELF 文件頭部中定義的程序進(jìn)入點(diǎn)開始執(zhí)行。在 a.out 格式和ELF格式中,程序進(jìn)入點(diǎn)的值是顯式存在的,在 COFF 格式中則是由規(guī)范隱含定義。


從上面的描述可以看出,加載文件最重要的是完成兩件事情:加載程序段和數(shù)據(jù)段到內(nèi)存;進(jìn)行外部定義符號的重定位。重定位是程序連接中一個重要概念。我們知道,一個可執(zhí)行程序通常是由一個含有 main() 的主程序文件、若干目標(biāo)文件、若干共享庫(Shared Libraries)組成。(注:采用一些特別的技巧,也可編寫沒有 main 函數(shù)的程序,請參閱參考資料 2)一個 C 程序可能引用共享庫定義的變量或函數(shù),換句話說就是程序運(yùn)行時必須知道這些變量/函數(shù)的地址。在靜態(tài)連接中,程序所有需要使用的外部定義都完全包含在可執(zhí)行程序中,而動態(tài)連接則只在可執(zhí)行文件中設(shè)置相關(guān)外部定義的一些引用信息,真正的重定位是在程序運(yùn)行之時。靜態(tài)連接方式有兩個大問題:如果庫中變量或函數(shù)有任何變化都必須重新編譯連接程序;如果多個程序引用同樣的變量/函數(shù),則此變量/函數(shù)會在文件/內(nèi)存中出現(xiàn)多次,浪費(fèi)硬盤/內(nèi)存空間。比較兩種連接方式生成的可執(zhí)行文件的大小,可以看出有明顯的區(qū)別。

a.out 文件格式分析

a.out 格式在不同的機(jī)器平臺和不同的 UNIX 操作系統(tǒng)上有輕微的不同,例如在 MC680x0 平臺上有 6 個 section。下面我們討論的是最"標(biāo)準(zhǔn)"的格式。

a.out 文件包含 7 個 section,格式如下:

exec header(執(zhí)行頭部,也可理解為文件頭部)

text segment(文本段)

data segment(數(shù)據(jù)段)

text relocations(文本重定位段)

data relocations(數(shù)據(jù)重定位段)

symbol table(符號表)

string table(字符串表)

執(zhí)行頭部的數(shù)據(jù)結(jié)構(gòu):

struct exec {

unsigned long a_midmag; /* 魔數(shù)和其它信息 */

unsigned long a_text; /* 文本段的長度 */

unsigned long a_data; /* 數(shù)據(jù)段的長度 */

unsigned long a_bss; /* BSS段的長度 */

unsigned long a_syms; /* 符號表的長度 */

unsigned long a_entry; /* 程序進(jìn)入點(diǎn) */

unsigned long a_trsize; /* 文本重定位表的長度 */

unsigned long a_drsize; /* 數(shù)據(jù)重定位表的長度 */

};


    文件頭部主要描述了各個 section 的長度,比較重要的字段是 a_entry(程序進(jìn)入點(diǎn)),代表了系統(tǒng)在加載程序并初試化各種環(huán)境后開始執(zhí)行程序代碼的入口。這個字段在后面討論的 ELF 文件頭部中也有出現(xiàn)。由 a.out 格式和頭部數(shù)據(jù)結(jié)構(gòu)我們可以看出,a.out 的格式非常緊湊,只包含了程序運(yùn)行所必須的信息(文本、數(shù)據(jù)、BSS),而且每個 section 的順序是固定的。這種結(jié)構(gòu)缺乏擴(kuò)展性,如不能包含"現(xiàn)代"可執(zhí)行文件中常見的調(diào)試信息,最初的 UNIX 黑客對 a.out 文件調(diào)試使用的工具是 adb,而 adb 是一種機(jī)器語言調(diào)試器!


a.out 文件中包含符號表和兩個重定位表,這三個表的內(nèi)容在連接目標(biāo)文件以生成可執(zhí)行文件時起作用。在最終可執(zhí)行的 a.out 文件中,這三個表的長度都為 0。a.out 文件在連接時就把所有外部定義包含在可執(zhí)行程序中,如果從程序設(shè)計的角度來看,這是一種硬編碼方式,或者可稱為模塊之間是強(qiáng)藕和的。在后面的討論中,我們將會具體看到ELF格式和動態(tài)連接機(jī)制是如何對此進(jìn)行改進(jìn)的。

a.out 是早期UNIX系統(tǒng)使用的可執(zhí)行文件格式,由 AT&T 設(shè)計,現(xiàn)在基本上已被 ELF 文件格式代替。a.out 的設(shè)計比較簡單,但其設(shè)計思想明顯的被后續(xù)的可執(zhí)行文件格式所繼承和發(fā)揚(yáng)??梢詤㈤唴⒖假Y料 16 和閱讀參考資料 15 源代碼加深對 a.out 格式的理解。參考資料 12 討論了如何在"現(xiàn)代"的紅帽LINUX運(yùn)行 a.out 格式文件。

COFF 文件格式分析

COFF 格式比 a.out 格式要復(fù)雜一些,最重要的是包含一個節(jié)段表(section table),因此除了 .text,.data,和 .bss 區(qū)段以外,還可以包含其它的區(qū)段。另外也多了一個可選的頭部,不同的操作系統(tǒng)可一對此頭部做特定的定義。

COFF 文件格式如下:

File Header(文件頭部)

Optional Header(可選文件頭部)

Section 1 Header(節(jié)頭部)

………

Section n Header(節(jié)頭部)

Raw Data for Section 1(節(jié)數(shù)據(jù))

Raw Data for Section n(節(jié)數(shù)據(jù))

Relocation Info for Sect. 1(節(jié)重定位數(shù)據(jù))

Relocation Info for Sect. n(節(jié)重定位數(shù)據(jù))

Line Numbers for Sect. 1(節(jié)行號數(shù)據(jù))

Line Numbers for Sect. n(節(jié)行號數(shù)據(jù))

Symbol table(符號表)

String table(字符串表)

文件頭部的數(shù)據(jù)結(jié)構(gòu):

struct filehdr

{

unsigned short f_magic; /* 魔數(shù) */

unsigned short f_nscns; /* 節(jié)個數(shù) */

long f_timdat; /* 文件建立時間 */

long f_symptr; /* 符號表相對文件的偏移量 */

long f_nsyms; /* 符號表條目個數(shù) */

unsigned short f_opthdr; /* 可選頭部長度 */

unsigned short f_flags; /* 標(biāo)志 */

};

    COFF 文件頭部中魔數(shù)與其它兩種格式的意義不太一樣,它是表示針對的機(jī)器類型,例如 0x014c 相對于 I386 平臺,而 0x268 相對于 Motorola 68000系列等。當(dāng) COFF 文件為可執(zhí)行文件時,字段 f_flags 的值為 F_EXEC(0X00002),同時也表示此文件沒有未解析的符號,換句話說,也就是重定位在連接時就已經(jīng)完成。由此也可以看出,原始的 COFF 格式不支持動態(tài)連接。為了解決這個問題以及增加一些新的特性,一些操作系統(tǒng)對 COFF 格式進(jìn)行了擴(kuò)展。Microsoft 設(shè)計了名為 PE(Portable Executable)的文件格式,主要擴(kuò)展是在 COFF 文件頭部之上增加了一些專用頭部,具體細(xì)節(jié)請參閱參考資料 18,某些 UNIX 系統(tǒng)也對 COFF 格式進(jìn)行了擴(kuò)展,如 XCOFF(extended common object file format)格式,支持動態(tài)連接,請參閱參考資料 5。


緊接文件頭部的是可選頭部,COFF 文件格式規(guī)范中規(guī)定可選頭部的長度可以為 0,但在 LINUX 系統(tǒng)下可選頭部是必須存在的。下面是 LINUX 下可選頭部的數(shù)據(jù)結(jié)構(gòu):

typedef struct

{

char magic[2]; /* 魔數(shù) */

char vstamp[2]; /* 版本號 */

char tsize[4]; /* 文本段長度 */

char dsize[4]; /* 已初始化數(shù)據(jù)段長度 */

char bsize[4]; /* 未初始化數(shù)據(jù)段長度 */

char entry[4]; /* 程序進(jìn)入點(diǎn) */

char text_start[4]; /* 文本段基地址 */

char data_start[4]; /* 數(shù)據(jù)段基地址 */

}

COFF_AOUTHDR;

字段 magic 為 0413 時表示 COFF 文件是可執(zhí)行的,注意到可選頭部中顯式定義了程序進(jìn)入點(diǎn),標(biāo)準(zhǔn)的 COFF 文件沒有明確的定義程序進(jìn)入點(diǎn)的值,通常是從 .text 節(jié)開始執(zhí)行,但這種設(shè)計并不好。

前面我們提到,COFF 格式比 a.out 格式多了一個節(jié)段表,一個節(jié)頭條目描述一個節(jié)數(shù)據(jù)的細(xì)節(jié),因此 COFF 格式能包含更多的節(jié),或者說可以根據(jù)實際需要,增加特定的節(jié),具體表現(xiàn)在 COFF 格式本身的定義以及稍早提及的 COFF 格式擴(kuò)展。我個人認(rèn)為,節(jié)段表的出現(xiàn)可能是 COFF 格式相對 a.out 格式最大的進(jìn)步。下面我們將簡單描述 COFF 文件中節(jié)的數(shù)據(jù)結(jié)構(gòu),因為節(jié)的意義更多體現(xiàn)在程序的編譯和連接上,所以本文不對其做更多的描述。此外,ELF 格式和 COFF格式對節(jié)的定義非常相似,在隨后的 ELF 格式分析中,我們將省略相關(guān)討論。

struct COFF_scnhdr

{

char s_name[8]; /* 節(jié)名稱 */

char s_paddr[4]; /* 物理地址 */

char s_vaddr[4]; /* 虛擬地址 */

char s_size[4]; /* 節(jié)長度 */

char s_scnptr[4]; /* 節(jié)數(shù)據(jù)相對文件的偏移量 */

char s_relptr[4]; /* 節(jié)重定位信息偏移量 */

char s_lnnoptr[4]; /* 節(jié)行信息偏移量 */

char s_nreloc[2]; /* 節(jié)重定位條目數(shù) */

char s_nlnno[2]; /* 節(jié)行信息條目數(shù) */

char s_flags[4]; /* 段標(biāo)記 */

};

有一點(diǎn)需要注意:LINUX系統(tǒng)中頭文件coff.h中對字段s_paddr的注釋是"physical address",但似乎應(yīng)該理解為"節(jié)被加載到內(nèi)存中所占用的空間長度"。字段s_flags標(biāo)記該節(jié)的類型,如文本段、數(shù)據(jù)段、BSS段等。在 COFF的節(jié)中也出現(xiàn)了行信息,行信息描述了二進(jìn)制代碼與源代碼的行號之間的對映關(guān)系,在調(diào)試時很有用。

    ELF文件格式分析


ELF 文件有三種類型:可重定位文件:也就是通常稱的目標(biāo)文件,后綴為.o。共享文件:也就是通常稱的庫文件,后綴為.so??蓤?zhí)行文件:本文主要討論的文件格式,總的來說,可執(zhí)行文件的格式與上述兩種文件的格式之間的區(qū)別主要在于觀察的角度不同:一種稱為連接視圖(Linking View),一種稱為執(zhí)行視圖(Execution View)。

首先看看ELF文件的總體布局:

ELF header(ELF頭部)

Program header table(程序頭表)

Segment1(段1)

Segment2(段2)

………

Sengmentn(段n)

Setion header table(節(jié)頭表,可選)

段由若干個節(jié)(Section)構(gòu)成,節(jié)頭表對每一個節(jié)的信息有相關(guān)描述。對可執(zhí)行程序而言,節(jié)頭表是可選的。參考資料 1中作者談到把節(jié)頭表的所有數(shù)據(jù)全部設(shè)置為0,程序也能正確運(yùn)行!ELF頭部是一個關(guān)于本文件的路線圖(road map),從總體上描述文件的結(jié)構(gòu)。下面是ELF頭部的數(shù)據(jù)結(jié)構(gòu):

typedef struct

{

unsigned char e_ident[EI_NIDENT]; /* 魔數(shù)和相關(guān)信息 */

Elf32_Half e_type; /* 目標(biāo)文件類型 */

Elf32_Half e_machine; /* 硬件體系 */

Elf32_Word e_version; /* 目標(biāo)文件版本 */

Elf32_Addr e_entry; /* 程序進(jìn)入點(diǎn) */

Elf32_Off e_phoff; /* 程序頭部偏移量 */

Elf32_Off e_shoff; /* 節(jié)頭部偏移量 */

Elf32_Word e_flags; /* 處理器特定標(biāo)志 */

Elf32_Half e_ehsize; /* ELF頭部長度 */

Elf32_Half e_phentsize; /* 程序頭部中一個條目的長度 */

Elf32_Half e_phnum; /* 程序頭部條目個數(shù) */

Elf32_Half e_shentsize; /* 節(jié)頭部中一個條目的長度 */

Elf32_Half e_shnum; /* 節(jié)頭部條目個數(shù) */

Elf32_Half e_shstrndx; /* 節(jié)頭部字符表索引 */

} Elf32_Ehdr;

   e_ident [0]-e_ident[3]包含了ELF文件的魔數(shù),依次是0x7f、'E'、'L'、'F'。注意,任何一個ELF 文件必須包含此魔數(shù)。參考資料 3中討論了利用程序、工具、/Proc文件系統(tǒng)等多種查看ELF魔數(shù)的方法。e_ident[4]表示硬件系統(tǒng)的位數(shù),1代表32位,2代表64位。 e_ident[5] 表示數(shù)據(jù)編碼方式,1代表小印第安排序(最大有意義的字節(jié)占有最低的地址),2代表大印第安排序(最大有意義的字節(jié)占有最高的地址)。e_ident [6]指定ELF頭部的版本,當(dāng)前必須為1。e_ident[7]到e_ident[14]是填充符,通常是0。ELF格式規(guī)范中定義這幾個字節(jié)是被忽略的,但實際上是這幾個字節(jié)完全可以可被利用。如病毒Lin/Glaurung.676/666(參考資料 1)設(shè)置 e_ident[7]為0x21,表示本文件已被感染;或者存放可執(zhí)行代碼(參考資料 2)。ELF頭部中大多數(shù)字段都是對子頭部數(shù)據(jù)的描述,其意義相對比較簡單。值得注意的是某些病毒可能修改字段e_entry(程序進(jìn)入點(diǎn))的值,以指向病毒代碼,例如上面提到的病毒Lin/Glaurung.676/666。


#p#一個實際可執(zhí)行文件的文件頭部形式如下:(利用命令readelf)

ELF Header:

Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00

Class: ELF32

Data: 2's complement, little endian

Version: 1 (current)

OS/ABI: UNIX - System V

ABI Version: 0

Type: EXEC (Executable file)

Machine: Intel 80386

Version: 0x1

Entry point address: 0x80483cc

Start of program headers: 52 (bytes into file)

Start of section headers: 14936 (bytes into file)

Flags: 0x0

Size of this header: 52 (bytes)

Size of program headers: 32 (bytes)

Number of program headers: 6

Size of section headers: 40 (bytes)

Number of section headers: 34

Section header string table index: 31

緊接ELF頭部的是程序頭表,它是一個結(jié)構(gòu)數(shù)組,包含了ELF頭表中字段e_phnum定義的條目,結(jié)構(gòu)描述一個段或其他系統(tǒng)準(zhǔn)備執(zhí)行該程序所需要的信息。

typedef struct {

Elf32_Word p_type; /* 段類型 */

Elf32_Off p_offset; /* 段位置相對于文件開始處的偏移量 */

Elf32_Addr p_vaddr; /* 段在內(nèi)存中的地址 */

Elf32_Addr p_paddr; /* 段的物理地址 */

Elf32_Word p_filesz; /* 段在文件中的長度 */

Elf32_Word p_memsz; /* 段在內(nèi)存中的長度 */

Elf32_Word p_flags; /* 段的標(biāo)記 */

Elf32_Word p_align; /* 段在內(nèi)存中對齊標(biāo)記 */

} Elf32_Phdr;

    在詳細(xì)討論可執(zhí)行文件程序頭表之前,首先查看一個實際文件的輸出:


Program Headers:

Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align

PHDR 0x000034 0x08048034 0x08048034 0x000c0 0x000c0 R E 0x4

INTERP 0x0000f4 0x080480f4 0x080480f4 0x00013 0x00013 R 0x1

[Requesting program interpreter: /lib/ld-linux.so.2]

LOAD 0x000000 0x08048000 0x08048000 0x00684 0x00684 R E 0x1000

LOAD 0x000684 0x08049684 0x08049684 0x00118 0x00130 RW 0x1000

DYNAMIC 0x000690 0x08049690 0x08049690 0x000c8 0x000c8 RW 0x4

NOTE 0x000108 0x08048108 0x08048108 0x00020 0x00020 R 0x4

Section to Segment mapping:

Segment Sections...

00

01 .interp

02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame

03 .data .dynamic .ctors .dtors .jcr .got .bss

04 .dynamic

05 .note.ABI-tag

Section Headers:

[Nr] Name Type Addr Off Size ES Flg Lk Inf Al

[ 0] NULL 00000000 000000 000000 00 0 0 0

[ 1] .interp PROGBITS 080480f4 0000f4 000013 00 A 0 0 1

[ 2] .note.ABI-tag NOTE 08048108 000108 000020 00 A 0 0 4

[ 3] .hash HASH 08048128 000128 000040 04 A 4 0 4

[ 4] .dynsym DYNSYM 08048168 000168 0000b0 10 A 5 1 4

[ 5] .dynstr STRTAB 08048218 000218 00007b 00 A 0 0 1

[ 6] .gnu.version VERSYM 08048294 000294 000016 02 A 4 0 2

[ 7] .gnu.version_r VERNEED 080482ac 0002ac 000030 00 A 5 1 4

[ 8] .rel.dyn REL 080482dc 0002dc 000008 08 A 4 0 4

[ 9] .rel.plt REL 080482e4 0002e4 000040 08 A 4 b 4

[10] .init PROGBITS 08048324 000324 000017 00 AX 0 0 4

[11] .plt PROGBITS 0804833c 00033c 000090 04 AX 0 0 4

[12] .text PROGBITS 080483cc 0003cc 0001f8 00 AX 0 0 4

[13] .fini PROGBITS 080485c4 0005c4 00001b 00 AX 0 0 4

[14] .rodata PROGBITS 080485e0 0005e0 00009f 00 A 0 0 32

[15] .eh_frame PROGBITS 08048680 000680 000004 00 A 0 0 4

[16] .data PROGBITS 08049684 000684 00000c 00 WA 0 0 4

[17] .dynamic DYNAMIC 08049690 000690 0000c8 08 WA 5 0 4

[18] .ctors PROGBITS 08049758 000758 000008 00 WA 0 0 4

[19] .dtors PROGBITS 08049760 000760 000008 00 WA 0 0 4

[20] .jcr PROGBITS 08049768 000768 000004 00 WA 0 0 4

[21] .got PROGBITS 0804976c 00076c 000030 04 WA 0 0 4

[22] .bss NOBITS 0804979c 00079c 000018 00 WA 0 0 4

[23] .comment PROGBITS 00000000 00079c 000132 00 0 0 1

[24] .debug_aranges PROGBITS 00000000 0008d0 000098 00 0 0 8

[25] .debug_pubnames PROGBITS 00000000 000968 000040 00 0 0 1

[26] .debug_info PROGBITS 00000000 0009a8 001cc6 00 0 0 1

[27] .debug_abbrev PROGBITS 00000000 00266e 0002cc 00 0 0 1

[28] .debug_line PROGBITS 00000000 00293a 0003dc 00 0 0 1

[29] .debug_frame PROGBITS 00000000 002d18 000048 00 0 0 4

[30] .debug_str PROGBITS 00000000 002d60 000bcd 01 MS 0 0 1

[31] .shstrtab STRTAB 00000000 00392d 00012b 00 0 0 1

[32] .symtab SYMTAB 00000000 003fa8 000740 10 33 56 4

[33] .strtab STRTAB 00000000 0046e8 000467 00 0 0 1

    對一個ELF可執(zhí)行程序而言,一個基本的段是標(biāo)記p_type為PT_INTERP的段,它表明了運(yùn)行此程序所需要的程序解釋器(/lib/ld- linux.so.2),實際上也就是動態(tài)連接器(dynamic linker)。最重要的段是標(biāo)記p_type為PT_LOAD的段,它表明了為運(yùn)行程序而需要加載到內(nèi)存的數(shù)據(jù)。查看上面實際輸入,可以看見有兩個可 LOAD段,第一個為只讀可執(zhí)行(FLg為R E),第二個為可讀可寫(Flg為RW)。段1包含了文本節(jié).text,注意到ELF文件頭部中程序進(jìn)入點(diǎn)的值為0x80483cc,正好是指向節(jié). text在內(nèi)存中的地址。段二包含了數(shù)據(jù)節(jié).data,此數(shù)據(jù)節(jié)中數(shù)據(jù)是可讀可寫的,相對的只讀數(shù)據(jù)節(jié).rodata包含在段1中。ELF格式可以比 COFF格式包含更多的調(diào)試信息,如上面所列出的形式為.debug_xxx的節(jié)。在I386平臺LINUX系統(tǒng)下,用命令file查看一個ELF可執(zhí)行程序的可能輸出是:a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped。


ELF文件中包含了動態(tài)連接器的全路徑,內(nèi)核定位"正確"的動態(tài)連接器在內(nèi)存中的地址是"正確"運(yùn)行可執(zhí)行文件的保證,參考資料 13討論了如何通過查找動態(tài)連接器在內(nèi)存中的地址以達(dá)到顛覆(Subversiver)動態(tài)連接機(jī)制的方法。

最后我們討論ELF文件的動態(tài)連接機(jī)制。每一個外部定義的符號在全局偏移表(Global Offset Table GOT)中有相應(yīng)的條目,如果符號是函數(shù)則在過程連接表(Procedure Linkage Table PLT)中也有相應(yīng)的條目,且一個PLT條目對應(yīng)一個GOT條目。對外部定義函數(shù)解析可能是整個ELF文件規(guī)范中最復(fù)雜的,下面是函數(shù)符號解析過程的一個描述。

1:代碼中調(diào)用外部函數(shù)func,語句形式為call 0xaabbccdd,地址0xaabbccdd實際上就是符號func在PLT表中對應(yīng)的條目地址(假設(shè)地址為標(biāo)號.PLT2)。

2:PLT表的形式如下

.PLT0: pushl 4(%ebx) /* GOT表的地址保存在寄存器ebx中 */

jmp *8(%ebx)

nop; nop

nop; nop

.PLT1: jmp *name1@GOT(%ebx)

pushl $offset

jmp .PLT0@PC

.PLT2: jmp *func@GOT(%ebx)

pushl $offset

jmp .PLT0@PC

3:查看標(biāo)號.PLT2的語句,實際上是跳轉(zhuǎn)到符號func在GOT表中對應(yīng)的條目。

4:在符號沒有重定位前,GOT表中此符號對應(yīng)的地址為標(biāo)號.PLT2的下一條語句,即是pushl $offset,其中$offset是符號func的重定位偏移量。注意到這是一個二次跳轉(zhuǎn)。

5:在符號func的重定位偏移量壓棧后,控制跳到PLT表的第一條目,把GOT[1]的內(nèi)容壓棧,并跳轉(zhuǎn)到GOT[2]對應(yīng)的地址。

6:GOT[2]對應(yīng)的實際上是動態(tài)符號解析函數(shù)的代碼,在對符號func的地址解析后,會把func在內(nèi)存中的地址設(shè)置到GOT表中此符號對應(yīng)的條目中。

7:當(dāng)?shù)诙握{(diào)用此符號時,GOT表中對應(yīng)的條目已經(jīng)包含了此符號的地址,就可直接調(diào)用而不需要利用PLT表進(jìn)行跳轉(zhuǎn)。

動態(tài)連接是比較復(fù)雜的,但為了獲得靈活性的代價通常就是復(fù)雜性。其最終目的是把GOT表中條目的值修改為符號的真實地址,這也可解釋節(jié).got包含在可讀可寫段中。

動態(tài)連接是一個非常重要的進(jìn)步,這意味著庫文件可以被升級、移動到其他目錄等等而不需要重新編譯程序(當(dāng)然,這不意味庫可以任意修改,如函數(shù)入?yún)⒌膫€數(shù)、數(shù)據(jù)類型應(yīng)保持兼容性)。從很大程度上說,動態(tài)連接機(jī)制是ELF格式代替a.out格式的決定性原因。如果說面對對象的編程本質(zhì)是面對接口(interface)的編程,那么動態(tài)連接機(jī)制則是這種思想的地一個非常典型的應(yīng)用,具體的講,動態(tài)連接機(jī)制與設(shè)計模式中的橋接(BRIDGE)方法比較類似,而它的LAZY特性則與代理(PROXY)方法非常相似。動態(tài)連接操作的細(xì)節(jié)描述請參閱參考資料 8,9,10,11。通過閱讀命令readelf、objdump 的源代碼以及參考資料 14中所提及的相關(guān)軟件源代碼,可以對ELF文件的格式有更徹底的了解。

總結(jié)

不同時期的可執(zhí)行文件格式深刻的反映了技術(shù)進(jìn)步的過程,技術(shù)進(jìn)步通常是針對解決存在的問題和適應(yīng)新的環(huán)境。早期的UNIX系統(tǒng)使用a.out格式,隨著操作系統(tǒng)和硬件系統(tǒng)的進(jìn)步,a.out格式的局限性越來越明顯。新的可執(zhí)行文件格式COFF在UNIX System VR3中出現(xiàn),COFF格式相對a.out格式最大變化是多了一個節(jié)頭表(section head table),能夠在包含基礎(chǔ)的文本段、數(shù)據(jù)段、BSS段之外包含更多的段,但是COFF對動態(tài)連接和C++程序的支持仍然比較困難。為了解決上述問題, UNIX系統(tǒng)實驗室(UNIX SYSTEM Laboratories USL) 開發(fā)出ELF文件格式,它被作為應(yīng)用程序二進(jìn)制接口(Application binary Interface ABI)的一部分,其目的是替代傳統(tǒng)的a.out格式。例如,ELF文件格式中引入初始化段.init和結(jié)束段.fini(分別對應(yīng)構(gòu)造函數(shù)和析構(gòu)函數(shù))則主要是為了支持C++程序。1994年6月ELF格式出現(xiàn)在LINUX系統(tǒng)上,現(xiàn)在ELF格式作為UNIX/LINUX最主要的可執(zhí)行文件格式。當(dāng)然我們完全有理由相信,在將來還會有新的可執(zhí)行文件格式出現(xiàn)。

上述三種可執(zhí)行文件格式都很好的體現(xiàn)了設(shè)計思想中分層的概念,由一個總的頭部刻畫了文件的基本要素,再由若干子頭部/條目刻畫了文件的若干細(xì)節(jié)。比較一下可執(zhí)行文件格式和以太數(shù)據(jù)包中以太頭、IP頭、TCP頭的設(shè)計,我想我們能很好的感受分層這一重要的設(shè)計思想。參考資料 21從全局的角度討論了各種文件的格式,并提出一個比較夸張的結(jié)論:Everything Is Byte!

最后的題外話:大多數(shù)資料中對a.out格式的評價較低,常見的詞語有黑暗年代(dark ages)、丑陋(ugly)等等,當(dāng)然,從現(xiàn)代的觀點(diǎn)來看,的確是比較簡單,但是如果沒有曾經(jīng)的簡單何來今天的精巧?正如我們今天可以評價石器時代的技術(shù)是ugly,那么將來的人們也可以嘲諷今天的技術(shù)是非常ugly。我想我們也許應(yīng)該用更平和的心態(tài)來對曾經(jīng)的技術(shù)有一個公正的評價。

 

【編輯推薦】

  1. Linux下查看用戶登陸后的操作記錄
  2. 專家指導(dǎo):Linux操作系統(tǒng)密碼恢復(fù)方法
  3. Linux系統(tǒng)下手動分析病毒樣本技巧
責(zé)任編輯:趙寧寧 來源: 中國IT實驗室
相關(guān)推薦

2015-02-02 11:03:12

2012-01-05 10:37:40

Java

2010-02-22 18:04:27

CentOS mpla

2017-02-07 10:22:53

2022-05-11 14:50:34

Python解包執(zhí)行文件

2021-01-12 10:10:41

shell腳本Linux命令

2021-01-08 08:06:19

腳本Shell文件

2011-08-09 10:24:19

可執(zhí)行文件病毒病毒

2023-03-31 23:31:06

.go文本文件

2024-05-06 00:00:00

Go文件瘦身代碼

2021-01-14 22:17:09

PythonLinux工具

2024-08-12 16:42:50

二進(jìn)制工具系統(tǒng)

2021-01-06 05:29:57

虛擬內(nèi)存文件

2024-05-21 12:01:39

.NET 6開發(fā)

2009-04-16 10:37:17

Javaexejar

2023-09-04 07:14:36

2023-12-25 16:10:34

Linuxdconfig命令

2022-05-20 08:55:02

py文件exepython

2023-12-18 09:21:22

開發(fā)靜態(tài)編譯Linux

2016-12-01 14:47:20

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

日韩av影视大全| 欧洲亚洲一区二区三区四区五区| 日韩视频中文字幕在线观看| 视频成人永久免费视频| 亚洲3atv精品一区二区三区| 精品一区二区视频| 探花国产精品一区二区| 91精品国产乱码久久久久久久| 欧美一级xxx| 亚洲熟妇国产熟妇肥婆| 98在线视频| 国产伦精品一区二区三区在线观看| 欧美黑人性猛交| 国产熟妇搡bbbb搡bbbb| 24小时成人在线视频| 亚洲影院理伦片| 秋霞久久久久久一区二区| 国产日韩一级片| 在线视频免费在线观看一区二区| 最新日韩中文字幕| 精产国品一区二区三区| 精品网站在线| 亚洲高清在线视频| 一本色道久久综合亚洲精品婷婷| 色婷婷中文字幕| 久久99精品久久久久| 欧美在线视频免费观看| 亚洲熟女www一区二区三区| 欧美美女在线观看| 亚洲第一中文字幕| 中文av一区二区三区| 色是在线视频| 亚洲国产aⅴ成人精品无吗| 一区二区日本伦理| 国产区av在线| 99久久伊人精品| 91久久精品一区二区别| 在线视频你懂得| 日韩影院免费视频| 欧美一级高清免费| 日韩成人高清视频| 国产伊人精品| 欧美高清视频免费观看| 国产少妇在线观看| 91国语精品自产拍| 日韩三级成人av网| 九九热久久免费视频| 红桃成人av在线播放| 亚洲欧美精品一区二区| 少妇激情一区二区三区视频| 91精品国产自产在线丝袜啪| 欧美一区二区精品在线| 色婷婷综合在线观看| 开心久久婷婷综合中文字幕| 欧美性猛交xxxx黑人交| 无码精品国产一区二区三区免费| 成人福利影视| 亚洲第一激情av| 精品国产av无码一区二区三区| 欧美日韩xx| 国产精品进线69影院| 亚洲色图自拍| 免费黄色网页在线观看| 亚洲丝袜另类动漫二区| 国产高清免费在线| 香蕉成人app免费看片| 樱花草国产18久久久久| 亚洲色欲久久久综合网东京热| 国产传媒在线播放| 一区二区三区精品| www.99热这里只有精品| 色资源二区在线视频| 欧洲中文字幕精品| 男女污污视频网站| 凹凸av导航大全精品| 亚洲精品国产精品自产a区红杏吧 亚洲精品国产精品乱码不99按摩 亚洲精品国产精品久久清纯直播 亚洲精品国产精品国自产在线 | 久久久久亚洲av成人网人人软件| 日本一区影院| 亚洲精品美女久久| 日本人亚洲人jjzzjjz| 欧美国产一级| 国产综合在线视频| 国产精品熟女视频| 激情综合色综合久久| 999精品在线观看| 亚洲欧美丝袜中文综合| 国产女人18水真多18精品一级做| 四虎影院一区二区| 神马久久午夜| 欧美精品乱码久久久久久按摩| 一级黄色大片免费看| 亚洲人成精品久久久| 日韩最新av在线| 日韩毛片在线播放| 裸体在线国模精品偷拍| 国产精品亚洲一区| 午夜视频在线看| 亚洲第一搞黄网站| 中文字幕天天干| 99re8这里有精品热视频8在线 | 成年人视频在线看| 夜夜夜精品看看| 精品国产成人av在线免| 欧美激情精品| 亚洲人成电影网站色…| 欧美日韩激情在线观看| 久久久久久婷| 国产高清自拍一区| 91福利在线视频| 精品久久久视频| 欧美精品色视频| 中文字幕精品影院| 九九九久久久久久| 中文字幕日韩三级| 99r国产精品| 日本一道在线观看| 欧美网站免费| 精品性高朝久久久久久久| 在线免费日韩av| 奇米一区二区三区av| 国产日韩精品推荐| 成人在线播放免费观看| 欧美在线观看一区二区| 黄色短视频在线观看| 欧美96在线丨欧| 国产精品综合网站| 美国一级片在线免费观看视频 | 日本高清不卡码| 高清国产一区二区| 成人午夜免费剧场| 亚洲午夜国产成人| 中国人与牲禽动交精品| 福利网址在线观看| 91视频.com| 国产精品无码人妻一区二区在线 | 日韩一级二级三级| 伊人久久久久久久久久久久久久| 日本欧美大码aⅴ在线播放| 免费在线国产精品| 欧美久久天堂| 日韩电影中文字幕| 影音先锋亚洲天堂| 99re这里都是精品| 阿v天堂2017| 任你躁在线精品免费| 992tv成人免费视频| 日批视频在线播放| 婷婷一区二区三区| 国产精品无码网站| 国产日韩一区| 欧美一区二区影视| 免费电影日韩网站| 一区二区三区国产视频| 自拍偷拍校园春色| 国产精品午夜在线观看| 久久久久久三级| 欧美三级美国一级| 成人精品一区二区三区电影免费 | 综合久久国产九一剧情麻豆| 午夜激情影院在线观看| 先锋资源久久| 99re视频在线| 黄视频网站在线观看| 亚洲精品网站在线播放gif| 天堂а√在线中文在线新版| 久久久www免费人成精品| 日韩免费高清在线| 国产精品传媒精东影业在线| 91中文字精品一区二区| av手机免费在线观看| 亚洲精品福利视频| 波多野结衣视频在线看| 中文字幕一区日韩精品欧美| 免费欧美一级片| 亚洲国内欧美| 日本精品二区| av国产精品| 国外成人在线直播| 户外极限露出调教在线视频| 欧美日韩在线不卡| 免费网站看av| 91丨porny丨首页| 污片在线免费看| 国产精品激情| 欧美一区二区三区在线播放 | 午夜激情视频在线播放| 成人性生交大片免费| 欧美一级片中文字幕| 91tv精品福利国产在线观看| 久久精彩视频| 亚洲精品aa| 欧美在线视频一区| 久草中文在线观看| 日韩第一页在线| 国产精品久久久久久久久久久久久久久久久久 | 国严精品久久久久久亚洲影视| 偷拍精品精品一区二区三区| 美日韩精品免费视频| 免费在线视频一级不卡| 欧美一区二区三区性视频| 久久久久久91亚洲精品中文字幕| 国产精品美女一区二区| 中国极品少妇videossexhd| 美女诱惑一区二区| 无码播放一区二区三区| 综合日韩在线| 亚洲不卡1区| 久久久91麻豆精品国产一区| 国产国语刺激对白av不卡| 青青青草视频在线| 日韩中文字幕视频在线| 青青草视频在线观看| 日韩欧美国产小视频| 一区二区视频免费| 欧美午夜精品伦理| 久久久一二三区| 中文字幕日本乱码精品影院| 日本激情小视频| www.欧美.com| 性高潮免费视频| 精品一区精品二区高清| 成人3d动漫一区二区三区| 亚洲大片av| 日本a在线天堂| 999精品在线| 一级做a爰片久久| 欧美精品一区二区三区中文字幕| 国严精品久久久久久亚洲影视| 日韩高清一区| 成人有码在线视频| **日韩最新| 成人免费午夜电影| 欧美综合影院| 国产在线拍偷自揄拍精品| 成人午夜亚洲| 国产精品久久久久久久久久久久久| 日本а中文在线天堂| 91国产视频在线播放| 国产精品—色呦呦| 欧美精品videos另类日本| av毛片在线播放| 久久av中文字幕| 最新国产露脸在线观看| 久久精品男人天堂| 成人在线免费看片| 欧美成人午夜视频| 欧美v亚洲v| 高清一区二区三区四区五区| 久久99亚洲网美利坚合众国| 欧美激情在线视频二区| 免费男女羞羞的视频网站在线观看| 欧美日韩国产成人| 福利成人导航| 91av在线视频观看| 欧美性猛交xxx高清大费中文| 欧洲成人免费视频| 日韩成人影音| 国产美女久久精品| 秋霞午夜一区二区三区视频| 99国产超薄丝袜足j在线观看 | 亚洲高清av在线| 亚洲色图欧美视频| 亚洲欧美制服综合另类| av电影在线网| 插插插亚洲综合网| 2001个疯子在线观看| 日产精品99久久久久久| 黄色精品视频网站| 91在线精品观看| 亚洲裸色大胆大尺寸艺术写真| 久久综合九色综合网站| 热久久天天拍国产| 中文字幕在线中文| 一区二区日本视频| 久久这里只精品| 国产精品18久久久久久vr| 无码一区二区精品| 欧美韩国日本不卡| 青青草原国产视频| 一本久道中文字幕精品亚洲嫩| 在线观看免费黄色小视频| 日韩一级片网站| 国产一二三在线观看| 久久久精品在线| 亚洲精品一区| 成人精品aaaa网站| 偷拍自拍亚洲色图| 中文字幕欧美人与畜| 日韩一级欧洲| 污污动漫在线观看| jlzzjlzz亚洲日本少妇| 69xxx免费| 亚洲成a人片综合在线| 国内av在线播放| 亚洲国产精彩中文乱码av在线播放 | 中文字幕欧美人与畜| 亚洲欧美日韩专区| 中文字幕一区二区在线观看视频| www.欧美色图| 9999热视频| 91久久精品一区二区三区| 91久久久久久久久久久久| 亚洲精品在线观看网站| 日本在线播放| 国产成人精品免费久久久久| 中文字幕视频精品一区二区三区| 日本在线观看一区| 亚洲电影在线| 欧美一级小视频| 国产亚洲短视频| 国内免费精品视频| 欧美一级二级在线观看| av男人的天堂在线| 日韩免费观看在线观看| a看欧美黄色女同性恋| 一本一生久久a久久精品综合蜜| 91久久视频| 又色又爽又黄18网站| 国产精品麻豆网站| 亚洲综合图片网| 日韩精品在线免费观看| 黄页网站在线观看免费| 91精品综合久久久久久五月天| 神马久久一区二区三区| 免费av观看网址| av在线综合网| 久草视频精品在线| 精品国产一区二区三区四区四| 免费大片黄在线| 国产日韩中文字幕在线| 日本女优一区| 婷婷丁香激情网| 久久久精品黄色| 亚洲精品男人的天堂| 亚洲精品456在线播放狼人| 丁香影院在线| 国产伦精品一区二区三区高清版 | 国产不卡av在线播放| 日韩综合视频在线观看| 久久电影天堂| 一本色道久久综合亚洲精品婷婷| 欧美aⅴ一区二区三区视频| 亚洲欧美va天堂人熟伦| 日本道在线观看一区二区| 黄色视屏网站在线免费观看| 日本精品va在线观看| 亚洲电影一级片| 青青在线视频观看| 国产亚洲婷婷免费| 中文字幕人妻精品一区| 日韩中文在线不卡| 亚洲精品第一| 中文字幕色呦呦| 成人午夜在线免费| 日本中文字幕在线免费观看| 亚洲精品国产精品乱码不99按摩| 蜜桃视频在线观看播放| 久久精品一二三区| 久久精品一本| 你懂得视频在线观看| 欧美精品1区2区| 欧美性受ⅹ╳╳╳黑人a性爽| 国产精品视频入口| 中文日韩在线| 舐め犯し波多野结衣在线观看| 欧美色图一区二区三区| 麻豆免费在线视频| 国产高清在线一区| 老司机免费视频久久| 老司机深夜福利网站| 欧美xxxxxxxx| 欧美三级网址| 一区二区视频在线免费| 成人午夜碰碰视频| 九九精品免费视频| 波霸ol色综合久久| 欧美xxxx在线| 色国产在线视频| 亚洲一区视频在线观看视频| 欧美18xxxxx| 川上优av一区二区线观看| 99精品视频免费| 性爱在线免费视频| 精品国产污网站| 91久久久久久白丝白浆欲热蜜臀| 亚洲最新免费视频| 99免费精品视频| 国产精品视频a| 97超级碰在线看视频免费在线看| 欧美军人男男激情gay| 熟妇无码乱子成人精品| 精品久久中文字幕| 老司机在线永久免费观看| 国产精品免费一区二区| 免费观看30秒视频久久| 国产一级大片在线观看| 最新91在线视频| 天天久久夜夜| 粗大的内捧猛烈进出视频| 日本高清不卡aⅴ免费网站|