最近經(jīng)常用到PLT hook,接下來幾篇文章,給大家介紹一下PLT hook的原理、使用、案例、以及一些注意事項(xiàng)。
今天是第一篇,先來介紹一下PLT Hook的基本原理。
ELF文件格式
ELF:Executable and Linkable Format
動(dòng)態(tài)鏈接庫就是ELF格式的文件,要搞清楚PLT Hook的原理,首先要了解ELF文件格式。

ELF分為連接視圖和執(zhí)行視圖。
- 連接視圖:ELF未被加載到內(nèi)存執(zhí)行前,以section為單位的數(shù)據(jù)組織形式
- 執(zhí)行視圖:ELF被加載到內(nèi)存后,以segment為單位的數(shù)據(jù)組織形式
PLT Hook是運(yùn)行中修改內(nèi)存中的數(shù)據(jù),所以我們主要關(guān)心的是執(zhí)行視圖。
linker依據(jù)ELF文件執(zhí)行視圖中的信息,用mmap將ELF加載到內(nèi)存中,執(zhí)行relocation將外部引用的絕對(duì)地址填入GOT表和DATA中。
PLT Hook的執(zhí)行時(shí)機(jī),是在linker將ELF加載到內(nèi)存之后。Hook的原理,是解析內(nèi)存中的ELF數(shù)據(jù),修改relocation結(jié)果。
裝載、動(dòng)態(tài)鏈接、重定位
1. 裝載
使用System.loadLibrary的方式,加載目標(biāo)共享庫,內(nèi)部其實(shí)也是調(diào)用linker中的dlopen、dlsym、dlclose函數(shù)對(duì)目標(biāo)共享庫進(jìn)行裝載。
2. 動(dòng)態(tài)鏈接
動(dòng)態(tài)鏈接的基本思想是把程序按照模塊拆分成各個(gè)相對(duì)獨(dú)立部分,在程序運(yùn)行時(shí)才將它們鏈接在一起。當(dāng)共享庫被裝載的時(shí)候,動(dòng)態(tài)鏈接器linkder會(huì)將共享庫裝載到進(jìn)程的地址空間,并且將程序中的符號(hào)綁定到動(dòng)態(tài)鏈接庫中,進(jìn)行重定位工作。
3. 重定位
共享庫需要重定位的主要原因是導(dǎo)入符號(hào)的存在。動(dòng)態(tài)鏈接下,一旦依賴于其他共享對(duì)象,就會(huì)有導(dǎo)入符號(hào)。這些導(dǎo)入符號(hào)在編譯的時(shí)候是未知的,只有在運(yùn)行的時(shí)候才確定,所以需要就這些導(dǎo)入符號(hào)的引入進(jìn)行修正,即進(jìn)行重定位。
PLT Hook的原理,就是改變導(dǎo)入符號(hào)重定位的結(jié)果。
linker

linkder在加載ELF時(shí)的最主要工作是relocation,這個(gè)過程的目的是為當(dāng)前ELF的每個(gè)“導(dǎo)入符號(hào)”找到對(duì)應(yīng)的外部符號(hào)(函數(shù)或數(shù)據(jù))的絕對(duì)地址。
這些地址會(huì)寫在以下幾個(gè)地方:
- .got.plt: GOT表,保存外部函數(shù)的絕對(duì)地址
- .data, .data.rel.ro:保存外部數(shù)據(jù)(包含函數(shù)指針)的絕對(duì)地址
要完成 relocation 過程,需要依賴于 ELF 中的以下信息:
- .rel.plt,.rela.plt:用于關(guān)聯(lián) .dynsym 和 .got.plt。這就是我們經(jīng)常會(huì)聽到的 “PLT 表”。
- .rel.dyn,.rela.dyn,.rel.dyn.aps2,.rela.dyn.aps2:用于關(guān)聯(lián) .dynsym 和 .data,.data.rel.ro。
relocation完成后的函數(shù)調(diào)用關(guān)系如下:

PLT和GOT表
- PLT表:程序鏈接表(Procdure Link Table),外部調(diào)用的跳板,.plt
- GOT表:全局偏移表 (Global Offset Table),記錄外部調(diào)用的入口地址,.got
由上面的分析可知,當(dāng)我們調(diào)用某個(gè)函數(shù)的時(shí)候,并不是直接調(diào)用函數(shù)的地址,而是經(jīng)過PLT表,跳轉(zhuǎn)到GOT表,獲取目標(biāo)函數(shù)的全局偏移。這個(gè)時(shí)候就可以通過基址+偏移的方式。定位到真正的函數(shù)地址。
PLT Hook基本原理
PLT Hook就是改變了原來的relocation后的地址。主要流程:
- 通過符號(hào)名,在hash table中找到對(duì)應(yīng)的符號(hào)信息
- 再找到對(duì)應(yīng)的PLT信息
- 最后找到GOT表中的絕對(duì)地址的值
- 修改這個(gè)絕對(duì)地址的值,為我們的“代理函數(shù)”的地址