iOS逆向之深入解析MachO文件
生活随笔
收集整理的這篇文章主要介紹了
iOS逆向之深入解析MachO文件
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
MachO文件簡介
一、什么是MachO文件?
- Mach-O其實是Mach Object文件格式的縮寫,它是Mac以及iOS上一種用于可執行文件、目標代碼、動態庫的文件格式,類似于Windows上面的PE格式(Portable Executable),linux上的elf格式(Executable and Link Format)。
- 它是一種用于可執行文件、目標代碼、動態庫的文件格式,作為.out格式的替代,MachO提供了更強的擴展性。
二、Mach-O文件格式
- 目標文件.o
- 庫文件:.a .dylib .Framework
- 可執行文件
- dyld(動態鏈接器)
- .dsym(符號表:Relese環境運行生成)
三、查看文件類型
- $ file xxx.xx
系統架構
一、iPhone不同的型號對應的架構
| 32位模擬器 | i386 |
| 64位模擬器 | x86_64 |
| iPhone4、iPhone4S | armv7 |
| iPhone5、iPhone5C | armv7s |
| iPhone5s——iPhoneX | arm64 |
| iPhone XS、iPhone XS Max、iPhoneXR、iPhone11… | arm64e |
二、Xcode中指令集相關選項(Build Setting)
- Architectures
指定工程被編譯成可支持哪些指令集類型,支持的指令集越多,就會編譯出包含多個指令集代碼的數據包,對應生成二進制 .ipa 包會變大。 - Valid Architectures
限制可能被支持的指令集的范圍,即:Xcode編譯出來的二進制包類型最終從這些類型產生,而編譯出哪種指令集的包,將由Architectures與Valid Architectures的交集來確定 - Build Active Architecture Only
指定是否只對當前連接設備所支持的指令集編譯。當其值設置為YES,是為了debug的時候編譯速度更快,它只編譯當前的Architecture版本,而設置為no時,會編譯所有的版本。 所以,一般debug的時候可以選擇設置為YES,release的時候要改為NO。
三、生成多種架構
- 新建一個工程,真機運行,查看可執行文件僅是一個arm64架構的,將項目最低適配系統調為iOS9.0,真機運行 Relese環境:
- 為什么要改為iOS9.0呢 ?是因為iPhone5c等armv7、armv7s架構不支持iOS11.0;
- 為什么要Relese環境運行呢 ?因為Xcode默認Debug只生成單一架構;
- 怎么生成所有架構 ?Xcode10中只包含了v7和64,需要在 Architectures 中添加:
通用二進制文件(Universal binary)
一、簡介
- 通用二進制文件也被叫做胖二進制(Fat binary);
- 蘋果公司提出的一種程序代碼,能同時適用多種架構的二進制文件;
- 同一個程序包中同時為多種架構提供最理想的性能;
- 由于需要儲存多種代碼,通用二進制應用程序通常比單一平臺二進制的程序要大;
- 由于兩種架構有共通的非執行資源,所以并不會達到單一版本的兩倍之多;
- 由于執行中只調用一部分代碼,運行起來也不需要額外的內存;
二、拆分/合并架構
① 終端命令
- 架構查看
- 架構合并
- 架構分離
② 結論
- 胖二進制拆分后再重組會得到原始胖二進制;
- 通用二進制的大小可能大于子架構大小之和,也可能小于,也可能等于,取決于公共資源文件的多少;
MachO文件結構
一、蘋果官方結構
主要組成可以大概分為三大塊:
- Header部分(包含該二進制文件的一般信息):字節順序、架構類型、加載指令的數量等。使得可以快速確認一些信息,比如當前文件用于32位還是64位,對應處理器是什么,文件類型是什么。
- Load commands 部分(一張包含很多內容的表);內容區包括區域的位置、符號表、動態符號表等。
- Data段:包含Segement的具體數據。
二、整體結構
- 使用 MachOView 打開會看到通用二進制文件由 Fat Header 和可執行文件組成(可執行文件是由 Header 、 Load commands 和 Data 組成):
- 可執行文件是由 Header 、 Load commands 和 Data 組成:
- 可以使用otool命令來查看Mach-O文件,也可以使用MachOView這個工具查看剛剛生成的MachO文件,先cd到當前文件夾,然后:
- header 包含了該二進制文件的字節順序、架構類型、加載指令的數量等,使得可以快速確認一些信息,比如當前文件用于 32 位 還是 64 位 ,對應的處理器是什么、文件類型是什么;Xcode中 shift+command+O -> load.h -> 如下信息(mach_header_64(64位)對比mach_header(32位)只多了一個保留字段)
- load commands 是一張包括區域的位置、符號表、動態符號表等內容的表。它詳細保存著加載指令的內容,告訴鏈接器如何去加載這個 Mach-O 文件。通過查看內存地址發現,在內存中 load commands 是緊跟在 header 之后的;
- load commands的詳情:
- 部分字段說明:
- data 是MachO文件中最大的部分,其中 _TEXT段 、 _DATA段 能給到很多信息。load commands 和 data 之間還留有不少空間,給我們留下了注入代碼的沖破口:
| _text | 主程序代碼 |
| _stubs、_stub_helper | 動態鏈接 |
| _objc_methodname | 方法名稱 |
| _objc_classname | 類名稱 |
| _objc_methtype | 方法類型 |
| _cstring | 靜態字符串常量 |
| _got=Non-Lazy Symbol Pointers | 非懶加載符號表 |
| _la_symbol_ptr => Lazy Symbol Pointers | 懶加載符號表 |
| _objc_classlist | 方法名稱 |
| … | … |
dyld
- dyld(the dynamic link editor)是蘋果的動態鏈接器,是蘋果操作系統的一個重要組成部分,在系統內容做好程序準備工作之后,交由dyld負責余下的工作。
- 系統庫的方法由于是公用的,存放在共享緩存中,那么我們的MachO在調用系統方法時,dyld會將MachO里調用存放在共享緩存中的方法進行符號綁定。這個符號在 release環境 是會被自動去掉的,這也是經常使用收集 bug 工具時需要恢復符號表的原因。
總結
以上是生活随笔為你收集整理的iOS逆向之深入解析MachO文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS之CALayer的CAEmitte
- 下一篇: 【数据结构与算法】之单向循环链表的创建/