青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

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

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

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

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

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

  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)和處理器對(duì)內(nèi)存的保護(hù)功能。著名的Shellcode(參考資料 17)的編寫技巧則是突破此保護(hù)功能的一個(gè)實(shí)際例子。

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

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

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

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

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

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

  void

  __attribute((constructor))

  init_function(void)

  {

  ……

  }

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


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

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

a.out 文件格式分析

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

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

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

  text segment(文本段)

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

  text relocations(文本重定位段)

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

  symbol table(符號(hào)表)

  string table(字符串表)

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

  struct exec {

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

  unsigned long a_text; /* 文本段的長(zhǎng)度 */

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

  unsigned long a_bss; /* BSS段的長(zhǎng)度 */

  unsigned long a_syms; /* 符號(hào)表的長(zhǎng)度 */

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

  unsigned long a_trsize; /* 文本重定位表的長(zhǎng)度 */

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

  };


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

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

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

COFF 文件格式分析

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

  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é)行號(hào)數(shù)據(jù))

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

  Symbol table(符號(hào)表)

  String table(字符串表)

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

  struct filehdr

  {

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

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

  long f_timdat; /* 文件建立時(shí)間 */

  long f_symptr; /* 符號(hào)表相對(duì)文件的偏移量 */

  long f_nsyms; /* 符號(hào)表?xiàng)l目個(gè)數(shù) */

  unsigned short f_opthdr; /* 可選頭部長(zhǎng)度 */

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

  };

 


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

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

typedef struct

  {

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

  char vstamp[2]; /* 版本號(hào) */

  char tsize[4]; /* 文本段長(zhǎng)度 */

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

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

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

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

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

  }

  COFF_AOUTHDR;

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

  前面我們提到,COFF 格式比 a.out 格式多了一個(gè)節(jié)段表,一個(gè)節(jié)頭條目描述一個(gè)節(jié)數(shù)據(jù)的細(xì)節(jié),因此 COFF 格式能包含更多的節(jié),或者說可以根據(jù)實(shí)際需要,增加特定的節(jié),具體表現(xiàn)在 COFF 格式本身的定義以及稍早提及的 COFF 格式擴(kuò)展。我個(gè)人認(rèn)為,節(jié)段表的出現(xiàn)可能是 COFF 格式相對(duì) a.out 格式最大的進(jìn)步。下面我們將簡(jiǎn)單描述 COFF 文件中節(jié)的數(shù)據(jù)結(jié)構(gòu),因?yàn)楣?jié)的意義更多體現(xiàn)在程序的編譯和連接上,所以本文不對(duì)其做更多的描述。此外,ELF 格式和 COFF格式對(duì)節(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é)長(zhǎng)度 */

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

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

ELF文件格式分析

  ELF 文件有三種類型:可重定位文件:也就是通常稱的目標(biāo)文件,后綴為.o。共享文件:也就是通常稱的庫(kù)文件,后綴為.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é)頭表,可選)

  段由若干個(gè)節(jié)(Section)構(gòu)成,節(jié)頭表對(duì)每一個(gè)節(jié)的信息有相關(guān)描述。對(duì)可執(zhí)行程序而言,節(jié)頭表是可選的。參考資料 1中作者談到把節(jié)頭表的所有數(shù)據(jù)全部設(shè)置為0,程序也能正確運(yùn)行!ELF頭部是一個(gè)關(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頭部長(zhǎng)度 */

  Elf32_Half e_phentsize; /* 程序頭部中一個(gè)條目的長(zhǎng)度 */

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

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

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

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

  } Elf32_Ehdr;

 


e_ident [0]-e_ident[3]包含了ELF文件的魔數(shù),依次是0x7f、'E'、'L'、'F'。注意,任何一個(gè)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ī)范中定義這幾個(gè)字節(jié)是被忽略的,但實(shí)際上是這幾個(gè)字節(jié)完全可以可被利用。如病毒Lin/Glaurung.676/666(參考資料 1)設(shè)置 e_ident[7]為0x21,表示本文件已被感染;或者存放可執(zhí)行代碼(參考資料 2)。ELF頭部中大多數(shù)字段都是對(duì)子頭部數(shù)據(jù)的描述,其意義相對(duì)比較簡(jiǎn)單。值得注意的是某些病毒可能修改字段e_entry(程序進(jìn)入點(diǎn))的值,以指向病毒代碼,例如上面提到的病毒Lin/Glaurung.676/666。

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

  typedef struct {

  Elf32_Word p_type; /* 段類型 */

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

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

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

  Elf32_Word p_filesz; /* 段在文件中的長(zhǎng)度 */

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

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

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

  } Elf32_Phdr;

 


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

  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

 


對(duì)一個(gè)ELF可執(zhí)行程序而言,一個(gè)基本的段是標(biāo)記p_type為PT_INTERP的段,它表明了運(yùn)行此程序所需要的程序解釋器(/lib/ld- linux.so.2),實(shí)際上也就是動(dòng)態(tài)連接器(dynamic linker)。最重要的段是標(biāo)記p_type為PT_LOAD的段,它表明了為運(yùn)行程序而需要加載到內(nèi)存的數(shù)據(jù)。查看上面實(shí)際輸入,可以看見有兩個(gè)可 LOAD段,第一個(gè)為只讀可執(zhí)行(FLg為R E),第二個(gè)為可讀可寫(Flg為RW)。段1包含了文本節(jié).text,注意到ELF文件頭部中程序進(jìn)入點(diǎn)的值為0x80483cc,正好是指向節(jié). text在內(nèi)存中的地址。段二包含了數(shù)據(jù)節(jié).data,此數(shù)據(jù)節(jié)中數(shù)據(jù)是可讀可寫的,相對(duì)的只讀數(shù)據(jù)節(jié).rodata包含在段1中。ELF格式可以比 COFF格式包含更多的調(diào)試信息,如上面所列出的形式為.debug_xxx的節(jié)。在I386平臺(tái)LINUX系統(tǒng)下,用命令file查看一個(gè)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文件中包含了動(dòng)態(tài)連接器的全路徑,內(nèi)核定位"正確"的動(dòng)態(tài)連接器在內(nèi)存中的地址是"正確"運(yùn)行可執(zhí)行文件的保證,參考資料 13討論了如何通過查找動(dòng)態(tài)連接器在內(nèi)存中的地址以達(dá)到顛覆(Subversiver)動(dòng)態(tài)連接機(jī)制的方法。

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

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

  2:PLT表的形式如下

  .PLT0: pushl 4(

轉(zhuǎn)自:
http://www.linux521.com/2009/system/200908/7856_1.html
posted on 2009-11-15 21:51 chatler 閱讀(277) 評(píng)論(0)  編輯 收藏 引用 所屬分類: FileFormat
<2010年4月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

常用鏈接

留言簿(10)

隨筆分類(307)

隨筆檔案(297)

algorithm

Books_Free_Online

C++

database

Linux

Linux shell

linux socket

misce

  • cloudward
  • 感覺這個(gè)博客還是不錯(cuò),雖然做的東西和我不大相關(guān),覺得看看還是有好處的

network

OSS

  • Google Android
  • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
  • os161 file list

overall

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲影视在线| 狂野欧美激情性xxxx| 国产精品人成在线观看免费 | 国产精品人成在线观看免费| 欧美久久婷婷综合色| 欧美日韩午夜精品| 国产精品yjizz| 国产亚洲aⅴaaaaaa毛片| 一区二区在线观看视频在线观看| 亚洲高清色综合| 中文精品一区二区三区| 欧美一区二区三区婷婷月色| 另类专区欧美制服同性| 亚洲美女少妇无套啪啪呻吟| 午夜精品久久久久久久久久久| 亚洲一区二区三区精品在线| 午夜一区二区三区不卡视频| 麻豆成人在线| 一本久久a久久免费精品不卡| 欧美亚洲色图校园春色| 欧美精品电影| 国产一区二区三区电影在线观看| 亚洲人屁股眼子交8| 午夜精品在线看| 欧美国产一区在线| 亚洲免费婷婷| 欧美日韩精品在线视频| 欧美国产视频在线| 国产精品一卡二卡| 亚洲精品日产精品乱码不卡| 午夜久久久久久| 亚洲国产精品久久久久秋霞蜜臀 | 亚洲日产国产精品| 久久精品人人做人人爽| 欧美精品在线观看91| 黑丝一区二区| 欧美一区二区视频在线| 亚洲激情在线播放| 久久久蜜臀国产一区二区| 国产午夜久久久久| 亚洲视频精选| 亚洲国产精品va在看黑人| 久久成人av少妇免费| 国产精品欧美日韩久久| 夜夜精品视频| 亚洲黄色一区| 欧美国产精品劲爆| 亚洲电影av| 久久香蕉国产线看观看网| 午夜电影亚洲| 国产精品一区二区久久| 亚洲女女女同性video| 亚洲剧情一区二区| 欧美精品网站| 欧美日韩成人在线观看| 亚洲国产精品欧美一二99| 久久午夜影视| 久久久久久久91| 狠狠综合久久av一区二区老牛| 久久av最新网址| 性久久久久久久久久久久| 国产麻豆精品theporn| 午夜影院日韩| 午夜亚洲伦理| 激情综合色综合久久综合| 久久久另类综合| 久久久久在线| 最新日韩中文字幕| 亚洲人成网站777色婷婷| 欧美久久久久中文字幕| 亚洲午夜精品一区二区| 亚洲婷婷免费| 国产一区二区三区在线观看免费| 久久成人免费电影| 欧美自拍偷拍午夜视频| 在线不卡欧美| 99国产精品视频免费观看一公开| 亚洲国产欧美日韩| 欧美视频三区在线播放| 蜜桃精品久久久久久久免费影院| 亚洲精品一区二区三区av| 日韩一级免费观看| 国产欧美精品在线播放| 久久综合久色欧美综合狠狠| 麻豆精品一区二区av白丝在线| 亚洲精品乱码久久久久久久久| 亚洲高清在线播放| 欧美性jizz18性欧美| 老司机精品福利视频| 欧美久久在线| 久久视频国产精品免费视频在线| 美女在线一区二区| 亚洲免费视频在线观看| 久久久噜噜噜久噜久久| 亚洲视频在线播放| 欧美伊人久久久久久午夜久久久久 | 亚洲美女毛片| 亚洲男人影院| 日韩视频免费大全中文字幕| 亚洲一级黄色| 99re亚洲国产精品| 欧美一区亚洲一区| 久久综合精品一区| 亚洲人体偷拍| 久久国产精品电影| 欧美激情一区二区三级高清视频| 午夜久久黄色| 欧美日韩精品欧美日韩精品| 久久九九国产精品怡红院| 欧美日韩国产999| 久久综合色婷婷| 国产精品视频男人的天堂| 欧美国产第一页| 欧美一级艳片视频免费观看| 欧美日本韩国在线| 久久久久久91香蕉国产| 欧美三级视频| 亚洲激情自拍| 在线观看亚洲一区| 亚洲视频 欧洲视频| 一区二区成人精品| 欧美成人在线免费视频| 欧美暴力喷水在线| 黄色一区二区三区| 羞羞色国产精品| 午夜欧美理论片| 欧美日韩在线精品一区二区三区| 亚洲国产精品视频| 亚洲黄色成人网| 麻豆精品视频在线观看视频| 久久亚洲精品一区二区| 国产欧美精品日韩精品| 亚洲小视频在线| 性久久久久久| 国产人成一区二区三区影院| 亚洲一区二区欧美| 午夜欧美不卡精品aaaaa| 国产精品麻豆欧美日韩ww| 亚洲视频狠狠| 先锋影音网一区二区| 国产精品日韩在线一区| 亚洲图片激情小说| 欧美一区二视频在线免费观看| 国产精品日韩在线播放| 亚洲欧美中文字幕| 久久久久综合| 亚洲国内欧美| 欧美日韩大片| 亚洲伊人伊色伊影伊综合网| 欧美影院午夜播放| 极品尤物av久久免费看 | 欧美成人一品| 日韩视频一区| 欧美一区二区精品| 伊人成人开心激情综合网| 另类综合日韩欧美亚洲| 欧美国产精品劲爆| 中国成人黄色视屏| 国产精品一区二区你懂的| 欧美一级夜夜爽| 亚洲国产精彩中文乱码av在线播放| 亚洲精品日产精品乱码不卡| 欧美日韩一区高清| 欧美在线免费一级片| 欧美激情精品久久久久久大尺度 | 亚洲国产精选| 亚洲午夜在线视频| 国产亚洲精品aa| 欧美国产综合| 亚洲欧美在线另类| 亚洲第一区在线观看| 午夜精品一区二区三区在线播放| 精品1区2区| 欧美午夜宅男影院| 久久久99久久精品女同性 | 久久这里只精品最新地址| 亚洲精品乱码久久久久久| 久久av一区| 一二三区精品福利视频| 国产综合网站| 午夜性色一区二区三区免费视频| 狠狠色狠狠色综合| 欧美日韩高清在线观看| 久久久www| 亚洲欧美电影院| 亚洲美女电影在线| 欧美成人久久| 久久精品在线播放| av成人动漫| 在线日韩av永久免费观看| 国产精品久久久久久久久免费桃花 | 免费视频一区| 校园激情久久| 亚洲视频一区在线观看| 亚洲黄色高清| 黄色国产精品| 国产主播一区二区| 国产日韩欧美在线| 国产精品日韩精品欧美精品| 欧美黄色一级视频|