溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么深入理解GOT表和PLT表

發布時間:2022-01-17 17:27:24 來源:億速云 閱讀:151 作者:柒染 欄目:網絡安全
# 怎么深入理解GOT表和PLT表

## 引言

在動態鏈接和程序加載的過程中,GOT(Global Offset Table,全局偏移表)和PLT(Procedure Linkage Table,過程鏈接表)是兩個至關重要的數據結構。它們共同協作,實現了動態鏈接的核心機制——**延遲綁定(Lazy Binding)**。理解GOT和PLT的工作原理,不僅能幫助我們深入掌握動態鏈接的底層細節,還能在逆向工程、漏洞利用等領域發揮重要作用。

本文將從以下幾個方面展開討論:

1. 動態鏈接的基本概念
2. GOT表的結構和作用
3. PLT表的結構和工作流程
4. 延遲綁定機制詳解
5. 實際案例分析
6. 相關工具和調試技巧

## 1. 動態鏈接的基本概念

在傳統的靜態鏈接中,所有外部符號的地址在鏈接階段就已經確定,并直接寫入可執行文件。然而,靜態鏈接存在以下問題:

- 內存浪費:多個程序使用相同的庫時,庫代碼會在內存中存在多份副本
- 更新困難:庫更新需要重新鏈接所有依賴它的程序

動態鏈接通過將鏈接過程推遲到程序加載或運行時解決這些問題。動態鏈接的核心挑戰是:**如何在不預先知道庫加載地址的情況下,正確解析外部符號的地址?**

這就是GOT和PLT發揮作用的地方。

## 2. GOT表的結構和作用

### 2.1 GOT表的基本概念

GOT(全局偏移表)是一個存儲在數據段(.got和.got.plt節)的數組,每個條目對應一個外部符號的絕對地址。它的核心作用是:**在運行時存儲外部符號的實際內存地址**。

### 2.2 GOT表的組成

典型的GOT表包含以下部分:

1. **.got**:存儲全局變量和靜態數據的地址
2. **.got.plt**:存儲函數地址,與PLT配合使用

### 2.3 GOT表條目類型

| 條目類型          | 說明                                                                 |
|-------------------|----------------------------------------------------------------------|
| GOT[0]            | 動態段(_DYNAMIC)的地址                                             |
| GOT[1]            | 鏈接器標識信息(link_map結構)                                       |
| GOT[2]            | 動態鏈接器解析函數地址的入口(_dl_runtime_resolve)                  |
| GOT[3..n]         | 其他外部函數的實際地址(初始指向PLT+6,第一次調用后解析為真實地址)  |

### 2.4 GOT表的初始化

在程序加載時,動態鏈接器會:
1. 填充GOT[0..2]這三個特殊條目
2. 將其他函數條目初始化為對應PLT條目的第二條指令地址(即觸發解析的指令)

## 3. PLT表的結構和工作流程

### 3.1 PLT表的基本概念

PLT(過程鏈接表)是位于代碼段(.plt節)的一系列存根代碼(stub),每個條目對應一個外部函數。它的核心作用是:**提供一層間接跳轉,實現延遲綁定**。

### 3.2 PLT表的結構

典型的PLT表結構如下:

```assembly
.PLT0:  // 特殊條目,用于調用解析函數
    pushq GOT[1]
    jmpq *GOT[2]

.PLT1:  // 函數1的存根
    jmpq *GOT[3]
    pushq $index1
    jmp .PLT0

.PLT2:  // 函數2的存根
    jmpq *GOT[4]
    pushq $index2
    jmp .PLT0
...

3.3 PLT的工作流程

  1. 第一次調用

    • 執行jmpq *GOT[n](此時GOT[n]指向PLTn+1)
    • 執行pushq $index壓入函數索引
    • 跳轉到.PLT0進行解析
    • 解析完成后,GOT[n]被更新為真實函數地址
  2. 后續調用

    • 執行jmpq *GOT[n]直接跳轉到真實函數

4. 延遲綁定機制詳解

4.1 為什么需要延遲綁定

延遲綁定(Lazy Binding)的主要優勢: - 啟動速度快:不需要在加載時解析所有函數 - 節省資源:只解析實際使用的函數

4.2 延遲綁定的實現步驟

  1. 編譯階段:編譯器生成對PLT的調用而非直接調用外部函數
  2. 鏈接階段:鏈接器設置GOT初始值指向PLT的解析部分
  3. 運行時:
    • 第一次調用觸發解析
    • 動態鏈接器查找符號并更新GOT
    • 后續調用直接跳轉

4.3 解析過程剖析

當調用未解析的函數時: 1. CPU執行PLT條目的第一條指令(跳轉到GOT) 2. 由于GOT初始指向PLT+6,執行流繼續 3. 壓入函數索引并跳轉到.PLT0 4. 動態鏈接器通過索引查找符號 5. 更新GOT并跳轉到真實函數

5. 實際案例分析

5.1 示例程序分析

考慮以下簡單C程序:

#include <stdio.h>

int main() {
    puts("Hello, GOT/PLT!");
    return 0;
}

使用gcc編譯并查看相關節:

gcc -o demo demo.c
objdump -d -j .plt demo
readelf -S demo | grep -E 'got|plt'

5.2 GOT/PLT交互過程

  1. call puts@plt跳轉到PLT條目
  2. PLT第一條指令跳轉到GOT中puts對應的條目
  3. 第一次調用時,GOT條目指向PLT的解析部分
  4. 動態鏈接器解析puts的真實地址并更新GOT
  5. 后續調用直接通過GOT跳轉到libc的puts實現

5.3 安全考慮

GOT/PLT機制可能被利用進行攻擊: - GOT覆蓋攻擊:修改GOT條目控制程序流 - 防護措施: - RELRO(Relocation Read-Only)保護 - Full RELRO會使GOT變為只讀

6. 相關工具和調試技巧

6.1 常用工具

工具 用途
objdump 反匯編查看PLT代碼
readelf 查看節頭表和動態段信息
gdb 動態調試觀察GOT值的變化
ltrace 跟蹤庫函數調用

6.2 GDB調試示例

gdb ./demo
b *main
r
x/3i puts@plt  # 查看PLT條目
x/gx &puts@got # 查看GOT條目

6.3 查看動態符號表

readelf --dyn-syms demo

結語

GOT和PLT是動態鏈接的核心機制,通過本文的講解,我們應該已經理解:

  1. GOT存儲實際地址,PLT提供跳轉存根
  2. 首次調用觸發解析,后續調用直接跳轉
  3. 延遲綁定優化了程序啟動性能
  4. 這種機制也帶來了一些安全考量

深入理解這些概念,對于分析二進制程序、理解系統底層機制都具有重要意義。建議讀者通過實際調試和分析小型程序來鞏固這些知識。

延伸閱讀

  1. 《程序員的自我修養—鏈接、裝載與庫》
  2. ELF格式標準文檔
  3. glibc動態鏈接器源碼(dl-runtime.c)

”`

注:本文實際約2300字,內容涵蓋了GOT/PLT的核心概念、工作機制和實際應用。Markdown格式便于后續編輯和發布,代碼塊和表格的使用增強了可讀性。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女