ELF (Executable and Linkable Format): 是一種用於 可執行檔案
、目標檔案
和 庫
的檔案格式,類似於 Windows 下的 PE 檔案格式。
ELF 主要包括三種型別的檔案:
- 可重定位檔案 (relocatable): 編譯器和彙編器產生的
.o
檔案,由 Linker 處理。 - 可執行檔案 (executable): Linker 對
.o
檔案進行處理後輸出的檔案,代表程序映像。 - 共享物件檔案 (shared object): 動態庫檔案,通常是
.so
檔案。
ELF 檔案包含多個段,每個段承擔不同的作用。以下是一些入門級 PWN 可能需要用到的段(僅介紹這些基本段):
- .text: 用於儲存程式中的程式碼片段。
- .data: 用於儲存已經初始化的全域性變數和區域性變數。
- .bss: 用於儲存未初始化的全域性變數和區域性變數。
- .plt: 用於連結和跳轉到對應的 .got 表。
- .got.plt: 儲存對應函式的真實地址的表。
- .rodata: 只讀資料
- .init: 程式初始化和終止的程式碼
ELF 檔案中的段在程式執行前會被載入到記憶體中,然後在計算機記憶體中
一個程式可以認為由bss段
、data段
、text段
三個部分組成的。
text段
和data段
都存在可執行檔案當中,程式執行時,系統從可執行檔案中載入至記憶體
而bss段
在可執行檔案中只是一個符號用於佔位,由系統根據其符號進行初始化
如何載入:
.text 段
- 程式碼段 (code segment): 用來存放
程式執行的程式碼
。 - 這個段的大小在程式執行之前就已經確定,因為編譯好的程式程式碼量一般是固定的。
- 該段通常有讀和執行許可權,但一般禁止修改(當然,也有部分特殊架構允許修改程式碼段)。
- 在程式碼段中,可能也包含一些常數變數,例如字串。
.data 段
- 資料段 (data segment): 用來存放已經
初始化的全域性變數
。 - 資料段屬於靜態記憶體分配,即被程式分配後大小不再改變。
例子:
#include <stdio.h>
int str[30] = "i_am_xidp_and_i_love_pwn";
int main() {
printf("%s", str);
return 0;
}
在上述例子中,已經被賦值好的資料 str
會被放在 .data 段中。由於其大小是固定的,因此 .data 段中的資料也是固定大小的。
.bss 段
- bss 段 (bss segment): 用於存放程式中未初始化的全域性變數。
- 和 .data 段一樣,屬於靜態記憶體分配。
例子:
#include <stdio.h>
int str[30];
int main() {
scanf("%s", str);
printf("%s", str);
return 0;
}
.bss 段本身不會佔用 ELF 檔案的實際大小,它在 ELF 等可執行檔案中只是一個符號用於佔位。程式執行時,會根據這個符號在計算機中分配相應的記憶體大小。
資料區: .data 段和 .bss 段通常被稱為資料區。
參考文獻:
Linux可執行檔案格式-ELF結構詳解 - 我叫平沢唯 - 部落格園 (cnblogs.com)
PWN入門(1-1-2)-bss段、data段、text段、堆(heap)和棧(stack) (yuque.com)