看雪上這篇文章講述了兩種對so進行加固的方法:1. 分離section浩姥,對整個section進行加密。2.在.text section直接尋找目標(biāo)函數(shù)并進行加密状您,兩種方式的實踐代碼見文末勒叠。
這里講一些我在學(xué)習(xí)過程中的一些額外發(fā)現(xiàn),如有理解不對的地方膏孟,歡迎斧正眯分。
一. 關(guān)于ELF的鏈接視圖和裝載視圖(執(zhí)行視圖)。在所有介紹ELF文件格式的文檔中柒桑,都會出現(xiàn)這樣一張圖:
當(dāng)初看這張圖并沒有很深的認識”拙觯現(xiàn)在回過頭看看,發(fā)現(xiàn)有了一些新的認識魁淳。
在C代碼 從源代碼到可執(zhí)行文件——編譯全過程解析中飘诗,我們看到C程序經(jīng)過 預(yù)處理、編譯界逛、匯編昆稿、鏈接 之后,形成可執(zhí)行文件或者共享目標(biāo)文件息拜。其中的鏈接環(huán)節(jié)溉潭,就會需要節(jié)區(qū)頭部表净响。當(dāng)然這里說的是靜態(tài)鏈接。靜態(tài)鏈接完成后喳瓣,節(jié)區(qū)頭部表在后續(xù)的加載執(zhí)行中已經(jīng)不會再用到了馋贤。
我們再來看看動態(tài)鏈接:動態(tài)鏈接的典型場景就是一個可執(zhí)行文件加載了一個so文件,并執(zhí)行了so的函數(shù)畏陕。詳細解釋如下(摘自ELF文件格式):
3.8.3 動態(tài)鏈接
3.8.3.1 程序解釋器
可執(zhí)行文件可以包含 PT_INTERP 程序頭部元素配乓。在 exec() 期間,系統(tǒng)從
PT_INTERP 段中檢索路徑名蹭秋,并從解釋器文件的段創(chuàng)建初始的進程映像扰付。也就是說,
系統(tǒng)并不使用原來可執(zhí)行文件的段映像仁讨,而是為解釋器構(gòu)造一個內(nèi)存映像羽莺。接下來是解
釋器從系統(tǒng)接收控制,為應(yīng)用程序提供執(zhí)行環(huán)境洞豁。
解釋器可以有兩種方式接受控制盐固。?
接受一個文件描述符,讀取可執(zhí)行文件并將其映射到內(nèi)存中?
根據(jù)可執(zhí)行文件的格式丈挟,系統(tǒng)可能把可執(zhí)行文件加載到內(nèi)存中刁卜,而不是為解釋器提
供一個已經(jīng)打開的文件描述符。
解釋器可以是一個可執(zhí)行文件曙咽,也可以是一個共享目標(biāo)文件蛔趴。
共享目標(biāo)文件被加載到內(nèi)存中時,其地址可能在各個進程中呈現(xiàn)不同的取值例朱。系統(tǒng)
在 mmap 以及相關(guān)服務(wù)所使用的動態(tài)段區(qū)域創(chuàng)建共享目標(biāo)文件的段孝情。因此,共享目標(biāo)
解釋器通常不會與原來的可執(zhí)行文件的原始段地址發(fā)生沖突洒嗤。
可執(zhí)行文件被加載到內(nèi)存中固定地址箫荡,系統(tǒng)使用來自其程序頭部表的虛擬地址創(chuàng)建
各個段。因此渔隶,可執(zhí)行文件解釋器的虛擬地址可能會與原來的可執(zhí)行文件的虛擬地址發(fā)
生沖突羔挡。解釋器要負責(zé)解決這種沖突。
3.8.3.2 動態(tài)加載程序
在構(gòu)造使用動態(tài)鏈接技術(shù)的可執(zhí)行文件時间唉,連接編輯器向可執(zhí)行文件中添加一個類
型為 PT_INTERP 的程序頭部元素绞灼,告訴系統(tǒng)要把動態(tài)鏈接器激活,作為程序解釋器呈野。系
統(tǒng)所提供的動態(tài)鏈接器的位置是和處理器相關(guān)的镀赌。
Exec() 和動態(tài)鏈接器合作,為程序創(chuàng)建進程映像际跪,其中包括以下動作:
(1). 將可執(zhí)行文件的內(nèi)存段添加到進程映像中商佛;
(2). 把共享目標(biāo)內(nèi)存段添加到進程映像中;
(3). 為可執(zhí)行文件和它的共享目標(biāo)執(zhí)行重定位操作姆打;
(4). 關(guān)閉用來讀入可執(zhí)行文件的文件描述符良姆,如果動態(tài)鏈接程序收到過這樣的
文件描述符的話;
(5). 將控制轉(zhuǎn)交給程序幔戏,使得程序好像從 exec 直接得到控制玛追。
鏈接編輯器也會構(gòu)造很多數(shù)據(jù)來協(xié)助動態(tài)鏈接器處理可執(zhí)行文件和共享目標(biāo)文件。
這些數(shù)據(jù)包含在可加載段中闲延,在執(zhí)行過程中可用痊剖。如:?
類型為 SHT_DYNAMIC 的 .dynamic 節(jié)區(qū)包含很多數(shù)據(jù)。位于節(jié)區(qū)頭部的結(jié)構(gòu)保存
了其他動態(tài)鏈接信息的地址垒玲。?
類型為 SHT_HASH 的 .hash 節(jié)區(qū)包含符號哈希表陆馁。?
類型為 SHT_PROGBITS 的 .got 和 .plt 節(jié)區(qū)包含兩個不同的表:全局偏移表和過
程鏈接表。
因為任何符合 ABI 規(guī)范的程序都要從共享目標(biāo)庫中導(dǎo)入基本的系統(tǒng)服務(wù)合愈,動態(tài)鏈
接器會參與每個符合 ABI 規(guī)范的程序的執(zhí)行叮贩。...
也就是說,動態(tài)鏈接時通過段去解析出對應(yīng)的section的內(nèi)容佛析。即:動態(tài)鏈接時也沒有使用到節(jié)區(qū)頭部表益老。
因此,我們可以猜測寸莫,節(jié)區(qū)頭部表在程序執(zhí)行過程中并不會被用到捺萌,既然不會被用到,ELF頭部中的e_shoff膘茎、e_shentsize桃纯、e_shnum和e_shstrndx可以隨意修改而不會影響到程序執(zhí)行。
二. 關(guān)于節(jié)和段辽狈。在鏈接視圖中慈参,數(shù)據(jù)被劃分為節(jié):
節(jié)區(qū)滿足以下條件:
(1). 目標(biāo)文件中的每個節(jié)區(qū)都有對應(yīng)的節(jié)區(qū)頭部描述它刮萌,反過來驮配,有節(jié)區(qū)頭部不意
味著有節(jié)區(qū)着茸。
(2). 每個節(jié)區(qū)占用文件中一個連續(xù)字節(jié)區(qū)域(這個區(qū)域可能長度為 0)壮锻。
(3). 文件中的節(jié)區(qū)不能重疊,不允許一個字節(jié)存在于兩個節(jié)區(qū)中的情況發(fā)生涮阔。
(4). 目標(biāo)文件中可能包含非活動空間(INACTIVE SPACE)掰邢。這些區(qū)域不屬于任何
頭部和節(jié)區(qū)掰伸,其內(nèi)容未指定多搀。
在加載視圖中,數(shù)據(jù)被劃分為段:
可執(zhí)行文件或者共享目標(biāo)文件的程序頭部是一個結(jié)構(gòu)數(shù)組惯退,每個結(jié)構(gòu)描述了一個段
或者系統(tǒng)準(zhǔn)備程序執(zhí)行所必需的其它信息。目標(biāo)文件的“段”包含一個或者多個“節(jié)區(qū)”,
也就是“段內(nèi)容(Segment Contents)”。程序頭部僅對于可執(zhí)行文件和共享目標(biāo)文件
有意義。
看一個實際的例子:
readelf的輸出
轉(zhuǎn)為直觀的表格
從圖中可以看出:a. 一個節(jié)區(qū)可以同時屬于多個段區(qū)b. 一個段區(qū)可以包含多個節(jié)區(qū)c. 段區(qū)由多個節(jié)區(qū)組成時,這些節(jié)區(qū)是連續(xù)的d. 我們看到.comments、.note.gnu.gold-ve、.ARM.attributes、.shstrtab 并沒有被映射到段靡馁,因此可以猜測這些區(qū)間的內(nèi)容修改不會影響程序的執(zhí)行奈嘿。
三. 總結(jié)ELF中可以被修改又不影響執(zhí)行的區(qū)域
a. ELF頭部中的:e_shoff、e_shentsize、e_shnum袄膏、e_shstrndx
b. 整個section頭部表
c. 沒有被映射到段的節(jié)(具體會有不同)码党,比如上面的.comments揖盘、.note.gnu.gold-ve兽狭、.ARM.attributes箕慧、.shstrtab伐庭。
四. 測試結(jié)果
清零ELF頭部的e_shoff似忧、e_shentsize、e_shnum蘑秽、e_shstrndx
清零節(jié)區(qū)頭部表(010Editor中已經(jīng)解析不出節(jié)區(qū)表了),清空沒有被映射到段的節(jié)區(qū)
替換so,打包簽名后,正常運行:
測試的apk見:
https://github.com/difcareer/SoEncrypt2/raw/master/app/src/main/misc/trip.apk
五. 作用
- 這些區(qū)域可以被精心構(gòu)造,影響到ELF解析工具,比如readelf,IDA等。比如前面看雪那篇文章中提到的分離section方式加固中窍蓝,因為修改了ELF頭部中的section相關(guān)的字段,就會導(dǎo)致IDA打開報錯回铛。
- 這些區(qū)域可以用來存儲自定義的內(nèi)容验残,甚至是被移除來壓縮ELF跟继。
本文代碼參見:
通過分離section,加密section:https://github.com/difcareer/SoEncrypt
通過查找函數(shù)并加密函數(shù):https://github.com/difcareer/SoEncrypt2
參考鏈接:
http://bbs.pediy.com/showthread.php?t=191649
http://www.wjdiankong.cn/android%e9%80%86%e5%90%91%e4%b9%8b%e6%97%85-%e5%9f%ba%e4%ba%8e%e5%af%b9so%e4%b8%ad%e7%9a%84%e5%87%bd%e6%95%b0%e5%8a%a0%e5%af%86%e6%8a%80%e6%9c%af%e5%ae%9e%e7%8e%b0so%e5%8a%a0%e5%9b%ba/
http://zke1ev3n.me/2015/12/27/Android-So%E7%AE%80%E5%8D%95%E5%8A%A0%E5%9B%BA/
http://blog.chinaunix.net/attachment/attach/26/40/46/9726404697228d82cda2af11366fa7722d3a4f1a58.pdf