前言
- 對symbol table 的symbol的了解(public symbol 、private symbol 、stripped symbol)
- Mach-O 初識
- hook方式彙總
I 對symbol的了解
1.1 什麼是symbol?
計算機中,一個函數的指令被存放在一段記憶體中,當程序需要執行這個函數的時候,它必須知道要去記憶體的哪個地方找到這個函數,然後執行它的指令。
也就是說,程序要根據這個函數的名稱,找到它在記憶體中的位址,而這個名稱與位址的映射關系,是存儲在 “symbol table”中。
“symbol table”中的
symbol
就是這個函數的名稱,
程序會根據這個
symbol
找到它在記憶體中的位址,然後跳轉過去執行。
symbol 跟函數名不同。
1.2 symbol的分類
為了避免其他app利用symbol,執行其他app庫的函數symbol 被分為2類
public symbol 和private symbol
第三類 stripped symbol
:
symbol的來源: symbol通常由 IDA 對二進制檔案的分析結果中提取。
II MSHookFunction 和 MSFindSymbol
2.1 MSHookFunction
MSHookFunction 作用于C 和C++函數通過編寫彙編指令,在進行執行到 function 時 轉而執行 replacement,同時儲存在 function 的指令及其傳回位址,使得使用者可以選擇性的執行 function ,并保證程序能夠在執行完 replacement 後繼續正常運作。
CydiaSubstrate(由MobileHooker、 MobileLoader 、Safe mode組成) 是對MSHookMessageEx進行封裝。
iOS 的底層是用 C C++ 實作的,編譯之後生成的大都是 subroutine, class-dump 拿它沒辦法,隻能使用IDA 工具。——-
是以在OC 開發中使用C 語言實作算法相關的功能,代碼更具安全性。
2.2 MSFindSymbol
MSHookFunction 直接作用private symbol是無效的,是以saurik 提供 MSFindSymbol 的 API 來通路private symbol。
void *MSFindSymbol(MSImageRef image, const char
MSImageRef image;
image = MSGetImageByName("/usr/lib/libSystem.B.dylib");
void *(*palloc)(size_t);
palloc = (void *(*)(size_t)) MSFindSymbol(image, "_malloc");
void *data = (*palloc)(1024);
free(data);
III Mach-O
Mach-O 是針對不同運作時可執行檔案的檔案類型。
3.1 檔案類型:
- Executable: 應用的主要二進制
- Dylib: 動态連結庫(又稱 DSO 或 DLL)
- Bundle: 不能被連結的 Dylib,隻能在運作時使用 dlopen() 加載,可當做 macOS 的插件。
- Image: executable,dylib 或 bundle
- Framework: 包含 Dylib 以及資源檔案和頭檔案的檔案夾
3.2 Mach-O 鏡像檔案
iOS 可執行檔案是 Mach-O 格式,主要由 Header、Load Commands、Data 三部分
Header 頭部
,包含可以執行的CPU架構,比如x86,arm64
Load commands 加載指令
,包含檔案的組織架構和在虛拟記憶體中的布局方式
Data資料
,存儲了實際的内容,主要是程式的指令和資料,它們的排布完全依照 Load Commands 的描述.
包含load commands中需要的各個段(segment)的資料
Mach-O 檔案中的 Data 部分主要是以 Segment(段)和 Section (節)的方式來組織内容的, 被劃分成一些 segement,每個 segement 又被劃分成一些 section。
- segment 的名字都是大寫的,
。頁的大小跟硬體有關,在 arm64 架構一頁是 16KB,其餘為 4KB。且空間大小為頁的整數
- section 雖然沒有整數倍頁大小的限制,但是 section 之間不會有重疊。
3.3 幾乎所有 Mach-O 都包含這三個segment(支援使用者自定義Segment)
__TEXT,__DATA 和 __LINKEDIT
- __TEXT 代碼段,隻讀可執行(r-x)
被執行的代碼包括函數,和隻讀的字元串,類似__TEXT,__text的都是代碼段 、包含 Mach header
- __DATA 資料段,包括可讀寫的全局變量、靜态變量
類似中的__DATA,__data都是資料段
可讀寫(rw-)
- __LINKEDIT :包含啟動 App 需要的資訊【方法和變量的
】(比如函數的名稱、bind & rebase位址)以及代碼簽名、符号表等資訊。中繼資料(位置,偏移量)
隻讀(r–)
3.4 ASLR位址空間布局随機化
-
Address Space Layout Randomization
位址空間布局随機化,鏡像會在随機的位址上加載。這其實是一二十年前的舊技術了。
3.5 代碼簽名
可能我們認為 Xcode 會把整個檔案都做加密 hash 并用做數字簽名。
其實為了在運作時驗證 Mach-O 檔案的簽名,并不是每次重複讀入整個檔案,而是把每頁内容都生成一個單獨的加密散列值,并存儲在 __LINKEDIT 中。這使得檔案每頁的内容都能及時被校驗确并保不被篡改。