蘋果開發者對它必定不陌生,特別是喜歡逆向的同窗,對它的研究更是必不可少。在可安裝的每個.app包中,都有一個與app同名的可執行文件,它可能長這樣:(若是你碰到顯示爲白色的MachO文件,說明當前用戶對其沒有可執行權限) bash
MachO實際上是Mach Object的縮寫,是在Mac以及iOS上可執行的一種文件格式,包括但不限於:可執行文件(.out .o)、動態庫、靜態庫、dyld、目標文件,官方文檔中列舉以下: 它相似於Windows上的PE、Linux上的ELF格式,咱們用file命令看上圖中 AlipayWallet 的文件類型信息: 能夠看到,該示例的MachO文件屬於通用二進制文件(蘋果提出的一種能同時適用多種架構二進制文件的程序代碼),並支持在兩種架構上運行:arm_v7和arm64,包含了多種架構的MachO文件能夠經過lipo thin命令進行拆分:lipo AlipayWallet -thin armv7 -output alipayArmv7
,一樣也能用lipo create進行合併:
lipo alipayArm64 alipayArmv7 -create -output AlipayWalletNew
,你們能夠本身實踐一下。
來用MachOView驗證一下該示例的MachO文件結構: 數據結構
除了用MachOView能查看MachO文件信息,還能夠經過otool命令查看,咱們先來分析Header中的內容:otool -h AlipayWallet
: 架構
#define CPU_TYPE_ARM((cpu_type_t) 12)
#define CPU_SUBTYPE_ARM_V7((cpu_subtype_t) 9)
#define CPU_TYPE_ARM64((cpu_type_t) 16777228)
#define CPU_SUBTYPE_AR64M_ALL((cpu_subtype_t) 0)
複製代碼
#define MH_EXECUTE 0x2 /* demand paged executable file */
複製代碼
這裏爲你準備了 mach_header 的蘋果官方文檔說明:(更多詳細定義請參考loader.h) app
咱們繼續用命令查看:otool -l alipayArm64
,該示例共有75個加載指令,咱們只截取一個做爲表明,分別爲出如今segment和section中的每個參數進行註釋:函數
Load command 1
cmd LC_SEGMENT_64 // cmd 是load command的類型,LC_SEGMENT_64的含義是將這個64位的段映射到進程地址空間,即加載命令
cmdsize 712 // 表明load command的大小
segname __TEXT // 16字節的段名字 __TEXT
vmaddr 0x0000000100000000 // 段的虛擬內存起始地址
vmsize 0x00000000036a4000 // 段的虛擬內存大小
fileoff 0 // 段在文件中的偏移量
filesize 57294848 // 段在文件中的大小
maxprot 0x00000005 // 段頁面所須要的最高內存保護(4=r,2=w,1=x)
initprot 0x00000005 // 段頁面初始的內存保護
nsects 8 // 段中包含section的數量
flags 0x0 // 其餘雜項標誌位
Section
sectname __text // 第一個是__text ,就是主程序代碼
segname __TEXT // 該section所屬的 segment名,第一個是__TEXT
addr 0x0000000100006110 // 該section在內存的啓始位置,0x100006110
size 0x000000000358a268 // size 該section的大小,0x358a268
offset 24848 // 24848 0x6110
align 2^4 (16) // 字節大小對齊,16
reloff 0 // 重定位入口的文件偏移 0
nreloc 0 // 須要重定位的入口數量 0
flags 0x80000400 // 包含section的type和attributes
reserved1 0 // ...保留用
reserved2 0 // ...保留用
複製代碼
註釋完畢,我又爲你準備了 segment和section 的蘋果官方文檔說明:(更多詳細定義請參考loader.h) post
我總結了最多見的加載命令以下:若是說前面兩部分的主要做用,是讓kern內核知道如何讀取MachO文件,並指定MachO文件的動態連接器(dyly)用來完成後續的動態庫加載,而後設置好程序入口等一些列程序啓動前的信息,那麼Data和連接信息部分,就至關於當程序運行起來後,爲每個映射到虛擬內存中的指令操做提供真實的物理地址支持。詳細的過程會面會單獨寫一篇文章展開來說。學習
理解原理很重要,瞭解MachO格式的結構和加載運行,不只能夠幫助咱們理解MacOS和iOS的app可執行文件啓動過程,還能作且不限於:優化
但願你有所收穫!下篇咱們主要圍繞dyld講動態加載過程,see you~ui
參考文章:加密