天天看點

iOS小技能:對symbol的了解

前言

  1. 對symbol table 的symbol的了解(public symbol 、private symbol 、stripped symbol)
  2. Mach-O 初識
  3. 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

iOS小技能:對symbol的了解

​​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 中。這使得檔案每頁的内容都能及時被校驗确并保不被篡改。

IV hook 的方式