PLT-hook技術

最近在學習apk的hook,貼一下自己的理解。

以下內容僅爲個人看法,不代表100%正確,如有錯誤還請指出。

1.什麼是hook技術

hook技術是一種攔截用戶函數調用的技術。通過hook技術可以實現統計用戶對某些函數的調用次數,對函數注入新的功能的目標。比如我想知道一個遊戲運行時PSS的大小,那麼我就可以使用hook技術來計算每一個函數調用時的開銷。譬如 hook malloc,calloc,realloc 和 free,我們就能統計出各個動態庫分配了多少內存,哪些內存一直被佔用沒有釋放。

2.什麼是PLT

在瞭解PLT技術之前需要先了解一下什麼是共享庫動態鏈接技術(linker)

大家應該聽說過靜態鏈接技術,是以一種將多個可鏈接目標文件鏈接爲一個獨立的可執行文件的過程。在鏈接的過程中,連接器會將靜態庫中的函數完整的複製到可執行文件的文本段中。在一個運行較多進程的系統中,這種鏈接方式對於內存消耗是不可小覷的。對於一個遊戲來說,調用的函數個數數不勝數,所以會導致size變得很大。爲了解決這個問題,共享庫誕生了,共享庫是一個目標模塊或者說目標文件,在運行或者加載時,可以加載到內存的任意位置,並和內存中的程序鏈接起來,這個過程是一個叫做動態鏈接器的組件完成的。

3.PLT

PLT(Procedure Linkage Table)全稱程序鏈接表,主要用於協助程序完成延遲加載的功能,假設程序調用一個動態庫中的函數,因爲動態庫可以被加載到內存中的任意位置,因此我們無法去預測這個函數的運行時地址。正常的做法是爲該函數調用生成一個重定位記錄,然後動態鏈接器在程序加載的時候去解析它。但是這並不符合位置無關代碼的做法,因爲需要鏈接器修改調用模塊的文本段。GNU使用延遲加載的技術去解決這個問題,把對函數地址的解析延遲到了對於函數的實際調用的時刻。使用這種技術,在第一次函數調用時的開銷較大,但是在之後的調用中只會花費一條指令和一個間接的內存引用。

延遲調用的完成需要PLT和GOT(Global Offset Table)全局偏移量表協作完成。如果一個目標模塊調用任何在共享庫中的函數,那麼它就有自己的GOT和PLT。GOT是數據段的一部分,PLT是代碼段的一部分。下面我們來講講PLT和GOT表中的內容:

PLT表中的每一項是一個16字節代碼。PLT[0]是一個特殊條目,它跳轉到動態鏈接器中。PLT[1]是系統啓動函數的條目。從PLT[3]開始是用戶調用的動態庫函數的條目。

4.GOT

GOT中每個表項是8字節的地址類型數據。和PLT類似,GOT[0]和GOT[1]也是特殊條目,包含動態鏈接器在解析函數地址時會使用的信息。GOT[2]是動態鏈接器在ld-linux.so模塊中的入口點。其餘的每一個條目對應一個被調用的函數,其地址在需要時進行解析。每個條目都有一個對應的PLT條目。

例子:

比如我遊戲裏有一個函數Attack,實際上我們打包成apk,在手機上運行時調用此函數的時候,是沒有那麼簡單的。
在android手機上對於Attack函數的調用,實際上調用的是PLT中的Attack條目,而PLT中Attack條目中執行的是JMP(GOT4),也就是還需要跳轉到GOT4中才是要執行函數Attack的基地址。在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章