Android之區(qū)段信息解析
? 背景
在進(jìn)行對(duì)so的動(dòng)態(tài)調(diào)試分析或者靜態(tài)代碼分析的過(guò)程中,都免不了和如下的區(qū)段相關(guān)信息打交道。
上圖是ida工具中靜態(tài)分析so文件代碼中的展示,可以通過(guò)快捷鍵shift+F7進(jìn)行展示(也可以用ndk自帶的readelf程序進(jìn)行查看區(qū)段信息)。
上圖通過(guò)ndk自帶的?readelf程序進(jìn)行查看so文件的區(qū)段信息(命令:readelf -S xx.so)。
下面就針對(duì)以上的區(qū)段名稱信息做下梳理。
LOAD解析
它表示的是共享文件(so文件)的加載部分,linker會(huì)根據(jù)load區(qū)段中的偏移信息把整個(gè)so文件加載起來(lái)。
plt解析
plt也稱為:過(guò)程鏈接表,主要用于函數(shù)和全局變量的調(diào)用。
Plt它是延遲綁定,延遲綁定的規(guī)則為只有在符號(hào)被真正引用時(shí)才進(jìn)行重定位,而不是在剛開(kāi)始就對(duì)所有的動(dòng)態(tài)符號(hào)進(jìn)行重定位,一方面加快了程序的啟動(dòng),將整個(gè)動(dòng)態(tài)加載時(shí)間分?jǐn)偟匠绦蜻\(yùn)行期間,另一方面,對(duì)于共享庫(kù)中沒(méi)有用到的符號(hào),不再進(jìn)行重定位,節(jié)省了重定位的時(shí)間,隨著共享庫(kù)的發(fā)展更新,這種優(yōu)勢(shì)變得越來(lái)越明顯。
plt 的好處在于所有需要重定位的指令跳轉(zhuǎn)都保存在 plt 中,便于集中管理、索引,另一方面,plt 還實(shí)現(xiàn)了判斷符號(hào)是否重定位并提供動(dòng)態(tài)鏈接器的調(diào)用功能,這是延遲綁定技術(shù)的核心部分。
text解析
代碼段(code segment/text segment)通常是指用來(lái)存放程序執(zhí)行代碼的一塊內(nèi)存區(qū)域。
這部分區(qū)域的大小在程序運(yùn)行前就已經(jīng)確定,并且內(nèi)存區(qū)域通常屬于只讀(某些架構(gòu)也允許代碼段為可寫,即允許修改程序)。
在代碼段中,也有可能包含一些只讀的常數(shù)變量,例如字符串常量等。
bss解析
這個(gè)bss它包含著將出現(xiàn)在程序的內(nèi)存映像中的未初始化數(shù)據(jù),這個(gè)區(qū)段它不占用文件空間。
bss段的全稱:Block Started by Symbol,它通常是指用來(lái)存放程序中未初始化的全局變量的一塊內(nèi)存區(qū)域,它是屬于靜態(tài)內(nèi)存分配。當(dāng)程序運(yùn)行結(jié)束后有系統(tǒng)釋放。
init_array解析
init_array是程序代碼可以控制的最早時(shí)機(jī), 其次才加載Jni_onload。這個(gè)也是很多在動(dòng)態(tài)調(diào)試分析下斷點(diǎn)的關(guān)鍵地方。
它包含著進(jìn)程初始化所運(yùn)行的函數(shù)指針數(shù)組。
它就如類對(duì)象的初始化構(gòu)造函數(shù)。
fini_array解析
它存儲(chǔ)的是終止函數(shù)段(也就是函數(shù)指針數(shù)組)。它是程序代碼中最后執(zhí)行的代碼。
它就像類對(duì)象的析構(gòu)函數(shù)。
got解析
它全名為 global offset table,即全局偏移表。
在執(zhí)行的指令中,本來(lái)需要引用符號(hào) A ,但是 A 存在于動(dòng)態(tài)庫(kù)中,鏈接過(guò)程并不知道它的地址,于是將 A 的地址部分改寫為 GOT 表中某一項(xiàng)數(shù)據(jù),在編譯階段 GOT 表中是沒(méi)有真實(shí)數(shù)據(jù)的,但是在動(dòng)態(tài)鏈接的加載階段,動(dòng)態(tài)鏈接器就可以將符號(hào) A 的真實(shí)地址填寫到 GOT 表中對(duì)應(yīng)的數(shù)據(jù)項(xiàng)中,這樣指令對(duì) A 就產(chǎn)生了正確的引用。
GOT 中每一個(gè)表項(xiàng)占用 4 個(gè)字節(jié)(32位),表示運(yùn)行時(shí)的符號(hào)的真實(shí)地址。它是針對(duì)外部符號(hào)引用的。
用來(lái)存放鏈接器找到的 函數(shù)/變量地址,也就是函數(shù)的絕對(duì)地址。
data解析
數(shù)據(jù)段:data segment.
它通常是指用來(lái)存放程序中已初始化的全局變量的一塊內(nèi)存區(qū)域,它是屬于靜態(tài)內(nèi)存分配。
它在程序的內(nèi)存映像中存在。
ret解析
它的作用:本程序裝載進(jìn)內(nèi)存時(shí),通過(guò)自己的rel表項(xiàng)告訴鏈接器,哪些地方需要重定位。
只要是rel開(kāi)頭的它都是表示跟重定位相關(guān)的信息。
rodata解析
它主要是字符串常量段。
它包含著只讀數(shù)據(jù),這些數(shù)據(jù)通常會(huì)參與進(jìn)程映像的只讀代碼段。
extern解析
它表示是外部的導(dǎo)入函數(shù),就是這個(gè)so文件中需要使用到的外部的函數(shù)。
data.rel.ro解析
它的作用就是表示程序初始化時(shí)的只讀數(shù)據(jù)段。
ARM.extab解析
.ARM.extab 作為 .ARM.exidx 的附屬存在,存放數(shù)據(jù),但無(wú)法直接找到每段數(shù)據(jù)的入口。
ARM.exidx解析
它包含用于展開(kāi)堆棧信息的部分。
dynsym和dynstr解析
dynsym和dynstr統(tǒng)稱為符號(hào)表。
對(duì)于在鏈接階段未解析的符號(hào),就需要在動(dòng)態(tài)鏈接階段進(jìn)行解析和重定位。
這些未解析的符號(hào)被保存在 .dynsym 中,而對(duì)應(yīng)的字符串被保存在 .dynstr。
在 .dynstr 和 .dynsym 相關(guān)都是以 '\0' 結(jié)尾的動(dòng)態(tài)符號(hào)表字符串信息。
dynsym是保存動(dòng)態(tài)鏈接相關(guān)符號(hào),記錄其偏移值。
dynstr是dynsym的輔助段。
更詳細(xì)可參考arm文檔:https://developer.arm.com/
本文轉(zhuǎn)載自微信公眾號(hào)「編碼安全」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系編碼安全公眾號(hào)。