什麼是 MachO?
mach-o(Mach Object File Format)是 Mac 和 iOS 平臺上可執行文件的格式,相似於 windows 平臺上的exe. 常見MachO格式的文件:windows
- .o
- .a .dylib .framework
- 二進制可執行文件
- .dsym
加載與執行
首先了解下什麼是進程,進程是一個程序的執行實體. 那 App 的啓動就能夠分爲兩步:安全
- 內核建立一個進程,分配空間,加載 dyld
- dyld 加載根據mach-o的格式將可執行文件加載到內存. 以後系統經過
解析文件
、創建依賴
、初始化運行環境
、執行進程
這幾步來真正的運行App.
MachO的結構
結構圖數據結構
從圖上能夠看出 Mach-O 文件的結構,包括 Mach-O的頭部,Load Command, Data.架構
Header
Header: 在<mach-o/loader.h>中定義了 Header 的數據結構:函數
上圖代碼是 64 位的 Header 數據結構,跟 32 位基本沒有差異,mach_header_64多了一個額外的預留字段
uint32_t reserved
.
- magic: 魔數, FAT文件(包含多個架構)爲
0xcafebabe
, armV7 是0xfeedface
, arm64是0xfeedfacf
.
- cputype: CPU 架構以及子版本
- filetype: 文件類型,常見的有MH_OBJECT(目標文件),MH_EXECUTABLE(二進制文件),MH_DYLIB(動態庫)
- ncmds: 加載命名的數量
- sizeofcmds: 全部加載命名的大小
- flags: dyld 加載須要的一些標記
- reserved: 64位預留字段
LoadCommands
用於告訴loader如何設置並加載二進制數據,對系統內核加載器和動態連接器(dyld)起指導做用.ui
(經過 MachOView 查看獲得) 列舉幾個經常使用的部分
- LC_SEGMENT_64: 定義一個Segment,加載後被映射到內存中,包括裏面的節.
- LC_MAIN: 程序的入口, dyld獲取該地址,而後跳轉到該處執行;
- LC_LOAD_DYLIB: 依賴的動態庫,包括動態庫名稱/當前版本號/兼容版本號;
Data (數據段 segment)
存放數據:代碼、字符常量、類、方法等, 能夠擁有多個segment,每一個segment能夠有零到多個section。每一個段都有一段虛擬地址映射到進程的地址空間. 先來看下數據結構, LC_SEGMENT_64
定義了一個 64 位的 segment. 其定義以下:ssr
dyld 將 fileoff(基於當前架構的文件偏移量)處 fileSize 大小的內容加載到虛擬內存的 vmaddr處,其大小爲 vmsize,segment 的權限由 initprot 進行初始化.
LC_SEGMENT_64
包括了一下 4 種:
- _PAGEZERO: 空指針陷阱段,用與捕捉對 iNULL指針的引用;
- _TEXT: 代碼段/只讀數據段;
- _DATA: 讀取/寫入數據的段;
- _LINKEDIT: dyld 須要的信息;
這裏重點說下_TEXT字段,對於還要適配 iOS 8的 App, 可用的_TEXT段只有60M,這致使不少大團隊對包大小異常敏感,也搞出來了不少trick的辦法來解決.
Section
在Segment 裏面會包含不一樣的 section,其結構以下圖:3d
- sectname: section 的名字
- segname: segment 的名字
- addr: 映射到虛擬地址的偏移
- size: section 的大小
- offset: section 在當前架構中的偏移
- align: section的字節對齊大小 n
- reloff: 重定位入口的文件偏移
- nreloc: 重定位入口的個數
- flags: section的類型與屬性:
- reserved: 保留位
__TEXT Segment的 Section:指針
- __text: 可執行文件的代碼區域
- __objc_methname: 方法名
- __objc_classname: 類名
- __objc_methtype: 方法簽名
- __cstring: 類C 風格的字符串. __DATA Segment 的 Section:
- __nl_symbol_ptr: 非懶加載指針表,dyld 加載會當即綁定
- __ls_symbol_ptr: 懶加載指針表
- __mod_init_func: constructor 函數
- __mod_term_func: destructor 函數
- __objc_classlist: 類列表
- __objc_nlclslist: 實現了 load 方法的類
- __objc_protolist: protocol的列表
- __objc_classrefs: 被引用的類列表
- __objc _catlist: Category列表
Loader Info (連接信息)
一個完整的用戶級MachO文件的末端是一系列連接信息。其中包含了動態加載器用來連接可執行文件或者依賴所需使用的符號表、字符串表等code
能用來作什麼? (代碼待開源)
- Category的方法覆蓋檢查
- 包瘦身,無用代碼檢查
- 代碼覆蓋率靜態檢查
參考
iOS應用逆向與安全