Linux/Unix平臺可執行檔案格式分析(轉)

ba發表於2007-08-15
Linux/Unix平臺可執行檔案格式分析(轉)[@more@]  本文討論了 UNIX/LINUX 平臺下三種主要的可執行檔案格式:a.out(assembler and link editor output 彙編器和連結編輯器的輸出)、COFF(Common Object File Format 通用物件檔案格式)、ELF(Executable and Linking Format 可執行和連結格式)。首先是對可執行檔案格式的一個綜述,並透過描述 ELF 檔案載入過程以揭示可執行檔案內容與載入執行操作之間的關係。隨後依此討論了此三種檔案格式,並著重討論 ELF 檔案的動態連線機制,其間也穿插了對各種檔案格式優缺點的評價。最後對三種可執行檔案格式有一個簡單總結,並提出作者對可檔案格式評價的一些感想。

  可執行檔案格式綜述

  相對於其它檔案型別,可執行檔案可能是一個作業系統中最重要的檔案型別,因為它們是完成操作的真正執行者。可執行檔案的大小、執行速度、資源佔用情況以及可擴充套件性、可移植性等與檔案格式的定義和檔案載入過程緊密相關。研究可執行檔案的格式對編寫高效能程式和一些駭客技術的運用都是非常有意義的。

  不管何種可執行檔案格式,一些基本的要素是必須的,顯而易見的,檔案中應包含程式碼和資料。因為檔案可能引用外部檔案定義的符號(變數和函式),因此重定位資訊和符號資訊也是需要的。一些輔助資訊是可選的,如除錯資訊、硬體資訊等。基本上任意一種可執行檔案格式都是按區間儲存上述資訊,稱為段(Segment)或節(Section)。不同的檔案格式中段和節的含義可能有細微區別,但根據上下文關係可以很清楚的理解,這不是關鍵問題。最後,可執行檔案通常都有一個檔案頭部以描述本檔案的總體結構。

  相對可執行檔案有三個重要的概念:編譯(compile)、連線(link,也可稱為連結、聯接)、載入(load)。源程式檔案被編譯成目標檔案,多個目標檔案被連線成一個最終的可執行檔案,可執行檔案被載入到記憶體中執行。因為本文重點是討論可執行檔案格式,因此載入過程也相對重點討論。下面是LINUX平臺下ELF檔案載入過程的一個簡單描述。

  1:核心首先讀ELF檔案的頭部,然後根據頭部的資料指示分別讀入各種資料結構,找到標記為可載入(loadable)的段,並呼叫函式 mmap()把段內容載入到記憶體中。在載入之前,核心把段的標記直接傳遞給 mmap(),段的標記指示該段在記憶體中是否可讀、可寫,可執行。顯然,文字段是隻讀可執行,而資料段是可讀可寫。這種方式是利用了現代作業系統和處理器對記憶體的保護功能。著名的Shellcode(參考資料 17)的編寫技巧則是突破此保護功能的一個實際例子。

  2:核心分析出ELF檔案標記為 PT_INTERP 的段中所對應的動態聯結器名稱,並載入動態聯結器。現代 LINUX 系統的動態聯結器通常是 /lib/ld-linux.so.2,相關細節在後面有詳細描述。

  3:核心在新程式的堆疊中設定一些標記-值對,以指示動態聯結器的相關操作。

  4:核心把控制傳遞給動態聯結器。

  5:動態聯結器檢查程式對外部檔案(共享庫)的依賴性,並在需要時對其進行載入。

  6:動態聯結器對程式的外部引用進行重定位,通俗的講,就是告訴程式其引用的外部變數/函式的地址,此地址位於共享庫被載入在記憶體的區間內。動態連線還有一個延遲(Lazy)定位的特性,即只在"真正"需要引用符號時才重定位,這對提高程式執行效率有極大幫助。

  7:動態聯結器執行在ELF檔案中標記為 .init 的節的程式碼,進行程式執行的初始化。在早期系統中,初始化程式碼對應函式 _init(void)(函式名強制固定),在現代系統中,則對應形式為
CODE:
void
__attribute((constructor))
init_function(void)
{
……
}

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-959430/,如需轉載,請註明出處,否則將追究法律責任。

Linux/Unix平臺可執行檔案格式分析(轉)
請登入後發表評論 登入
全部評論

相關文章