iOS逆向 MachO文件
作者: 我是好寶寶
鏈接:https://juejin.im/post/5df47aebe51d4558483d9717
一、MachO初探
1.定義
MachO
其實是 Mach Object
文件格式的縮寫,是mac以及iOS上可執行文件的格式,類似於Windows上的PE格式(Portable Executable)、Linux上的elf格式(Executable and Linking Format)
它是一種用於可執行文件、目標代碼、動態庫的文件格式,作爲.out格式的替代,MachO提供了更強的擴展性
2.常見的MachO文件
-
目標文件.o
-
庫文件
-
.a
-
.dylib
-
.Framework
-
可執行文件
-
dyld(動態鏈接器)
-
.dsym(符號表:Relese環境運行生成
3.查看文件類型
$ file xxx.xx
二、關於架構
1.架構表
其實iPhone不同的型號對應的架構是不一樣的
2.生成多種架構
新建一個工程,真機運行,查看可執行文件僅僅是一個arm64架構的
將項目最低適配系統調爲iOS9.0,真機運行
Relese環境
爲什麼要改爲iOS9.0呢 ?是因爲iPhone5c等armv7、armv7s架構不支持iOS11.0
爲什麼要Relese環境運行呢 ?因爲Xcode默認Debug只生成單一架構
怎麼生成所有架構
?Xcode10中只包含了v7和64,需要在 Architectures
中添加
三、通用二進制文件
1.定義
通用二進制文件(Universal binary)也被叫做 胖二進制(Fat binary)
-
蘋果公司提出的一種程序代碼,能同時適用多種架構的二進制文件
-
同一個程序包中同時爲多種架構提供最理想的性能
-
因爲需要儲存多種代碼,通用二進制應用程序通常比單一平臺二進制的程序要大
-
但是由於兩種架構有共通的非執行資源,所以並不會達到單一版本的兩倍之多
-
而且由於執行中只調用一部分代碼,運行起來也不需要額外的內存
2.拆分/合併架構
架構拆分
合併架構
通用二進制
大小爲342kb,四個架構大小爲80+80+80+81=321kb
What!爲什麼不是單純的1+1=2?
因爲不同架構之間代碼部分是不共用的 (因爲代碼的二進制文件不同的組合在不同的 cpu 上可能會是不同的意義),而公共資源文件是公用的
利用上述方法可以給我們的app瘦身
結論:
① 胖二進制
拆分後再重組會得到原始 胖二進制
② 通用二進制
的大小可能大於子架構大小之和,也可能小於,也可能等於,取決於 公共資源文件
的多少
3.終端命令行
// 查看二進制文件
$ lipo -info xx
// 通用二進制文件
// 拆分二進制文件
lipo xxx -thin armv7 -output xxx
// 組合二進制文件
lipo -create x1 x2 x3 x4 -output xxx
四、MachO文件
1.整體結構
用 MachOView
打開會看到 通用二進制文件
由 Fat Header
和 四個可執行文件
組成
可執行文件
是由
Header
、
Load commands
和
Data
組成
我們可以這麼理解,把
通用二進制文件
看作四本翻譯語言不同的書,每本書有
標題(header)
、
目錄(load commands)
、
內容(data)
-
header:
-
load commands:
-
data:
另外我們也可以通過 otool
命令行查看MachO文件結構
$ otool -f universe
2.header
header
包含了該二進制文件的字節順序、架構類型、加載指令的數量等,使得可以快速確認一些信息,比如當前文件用於 32 位
還是 64 位
,對應的處理器是什麼、文件類型是什麼
Xcode中 shift+command+O
-> load.h
->如下信息
struct mach_header_64 {
uint32_t magic; /* 魔數,快速定位64位/32位 */
cpu_type_t cputype; /* cpu 類型 比如 ARM */
cpu_subtype_t cpusubtype; /* cpu 具體類型 比如arm64 , armv7 */
uint32_t filetype; /* 文件類型 例如可執行文件 .. */
uint32_t ncmds; /* load commands 加載命令條數 */
uint32_t sizeofcmds; /* load commands 加載命令大小*/
uint32_t flags; /* 標誌位標識二進制文件支持的功能 , 主要是和系統加載、鏈接有關*/
uint32_t reserved; /* reserved , 保留字段 */
};
mach_header_64(64位)對比mach_header(32位)只多了一個保留字段
3.load commands
load commands
是一張包括區域的位置、符號表、動態符號表等內容的表。它詳細保存着加載指令的內容,告訴鏈接器如何去加載這個 Mach-O 文件。通過查看內存地址我們發現,在內存中 load commands
是緊跟在 header
之後的
4.data
data
是MachO文件中最大的部分,其中 _TEXT段
、 _DATA段
能給到很多信息
load commands
和 data
之間還留有不少空間,給我們留下了注入代碼的衝破口
_TEXT段
_DATA段
五、dyld
dyld(the dynamic link editor)是蘋果的動態鏈接器,是蘋果操作系統的一個重要組成部分,在系統內容做好程序準備工作之後,交由dyld負責餘下的工作
系統庫的方法由於是公用的,存放在共享緩存中,那麼我們的MachO在調用系統方法時,dyld會將MachO裏調用存放在共享緩存中的方法進行符號綁定。這個符號在 release環境
是會被自動去掉的,這也是我們經常使用收集 bug 工具時需要恢復符號表的原因
如果感覺這篇文章不錯可以點擊在看:point_down: