Mach-O是Mach object的縮寫,是Mac\iOS上用來存儲程序、庫的標準格式html
xun是蘋果MacOS\iOS等操做系統的內核git
Mach-O類型 | 示例文件 |
---|---|
MH_OBJECT | 目標文件(.o) 靜態庫文件(.a)注: |
MH_EXECUTE | 可執行文件,存放App的全部源碼信息,在.app/xx |
MH_DYLIB | 動態庫文件.dylib 或者 .framework/xx |
MH_DYLINKER | 動態連接編輯器,也就是以前所說的/usr/lib/dyld工具 |
MH_DSYM | 此文件中存儲這二進制文件符號信息,在開發中,咱們常用此文件來分析App的崩潰信息 |
能夠點擊官網查看Mach-O的介紹。github
Mach-O由3個部分組成緩存
Raw segment data存放了全部的原始數據,而Load commands至關於Raw segment data的索引目錄sass
file 文件路徑
複製代碼
#查看Mach-O文件的header信息
otool -h 文件路徑
#查看Mach-O文件的load commands信息
otool -l 文件路徑
複製代碼
更多使用方法,終端輸入otool -help查看bash
#查看架構信息
lipo -info 文件路徑
#導出某種類型的架構
lipo 文件路徑 -thin 架構類型 -output 輸出文件路徑
#合併多種架構類型
lipo 文件路徑1 文件路徑2 -output 輸出文件路徑
複製代碼
通用二進制文件就是同時適用於多種架構的二進制文件,它包含了多種不一樣架構的獨立的二進制文件,它有如下特色網絡
dyld是iOS中用來加載可執行文件、動態庫的工具,其實它自己也是一個Mach-O文件。架構
dyld能夠用來加載如下三種類型的Mach-O文件app
經過查看dyld的源碼能夠看到加載文件時的類型校驗框架
想要了解Mach-O文件,首先要了解從編寫代碼,開發App到App打包並安裝到手機上的整個過程。
初步瞭解了什麼是Mach-O文件,以及App從開發到安裝的過程,咱們就能夠來學習如何逆向一款App
靜態分析的工具備MachOView、class-dump、Hopper Disassembler、ida等等,後面會一一學習
動態調試的工具備debugserver、LLDB等等
class-dump的做用就是把Mach-O文件的class信息給導出來,生成對應的.h頭文件
在Mac中,終端執行的全部指令都會去/usr/bin目錄和/usr/local/bin目錄下尋找
# -H表示須要生成頭文件 -o用於指定頭文件的存放目錄
class-dump -H Mach-O文件路徑 -o 頭文件存放目錄
複製代碼
Hopper Disassmbler能夠將Mach-O文件的機器語言反編譯成彙編代碼、OC僞代碼或者是Swift僞代碼。最常使用的快捷鍵有
#找出哪裏引用了這個方法
Shift + Option + X
複製代碼
下載地址:pan.baidu.com/s/1yP_VcBlQ…
在iOS開發中,有不少功能都是現成可用的,不關你的App在用,其它的App也在用,好比UIKit框架、GUI框架、I/O、網絡等等。這些庫都是經過連接器連接到Mach-O文件中的。
靜態庫是編譯時連接的庫,須要鏈接進入Mach-O文件中,若是須要更新就必須從新編譯一次,沒法作到動態加載和更新
Mach-O是文件編譯以後的產物,因此動態庫並無參與Mach-O文件的編譯和連接。因此Mach-O文件中沒有包含動態庫的符號定義,也就是說這些符號會直接顯示未定義,可是他們的名字和對應庫的路徑會被記錄下來。在運行時經過dlopen和dlsym導入動態庫時,會根據記錄的路徑找到對應的庫,再經過記錄的名字符號找到綁定的地址。
從iOS3.1開始,爲了提升性能,絕大部分的系統動態庫文件都打包存放到了一個緩存文件中(dyld shared cache),緩存路徑是/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX
dyld_shared_cache_armX裏面的X表明ARM處理器指令集的架構
ARM指令集(CPU指令的集合)有如下幾種
ARM指令集 | 支持的設備 |
---|---|
armv6 | iPhone、iPhone3G iPod Touch、iPod Touch2 |
armv7 | iPhone3GS、iPhone四、iPhone4S iPad、iPad二、iPad3(The New iPad)、iPad mini iPod、Touch3G、iPod Touch四、iPod Touch5 |
armv7s | iPhone五、iPhone5C、iPad4 |
arm64 | iPhone5S、iPhone六、iPhone6 Plus、iPhone6S、iPhone6S Plus iPhoneSE、iPhone七、iPhone7Plus、iPhone八、iPhone8 Plus、iPhoneX iPad五、iPad Air、iPad Air二、iPad Pro、iPad Pro2 iPad mini with Retina display、iPad mini三、iPad mini4 iPod Touch6 |
以上全部的指令集都是向下兼容的 爲何要使用動態庫共享緩存呢?最大的好處就是節省內存。
因爲動態庫共享緩存太大,若是想獲取其中某個動態庫,例如UIKit,就須要從動態庫共享緩存中抽取對應的動態庫
使用dyld源碼中提供的方式來進行抽取,工具在源碼中的launch-cache/dsc_extractor.cpp文件中
clang++ -o dsc_extractor dsc_extractor.cpp
複製代碼
此處是將dsc_extractor.cpp編譯生成可執行文件dsc_extractor
./dsc_extractor 動態庫共享緩存文件的路徑 用於存放抽取結果的目錄
複製代碼
建議抽取armv7s架構的動態庫,arm64抽取時會報以上錯誤,緣由是dsc_extractor.bundle不能在Xcode10以後使用