寫(xiě)在前面
dyld
作為蘋(píng)果的動(dòng)態(tài)鏈接器,是蘋(píng)果操作系統(tǒng)的一個(gè)重要組成部分吻谋,在系統(tǒng)內(nèi)容做好程序準(zhǔn)備工作之后交由dyld
負(fù)責(zé)余下的工作忠蝗。因此了解dyld
的加載過(guò)程對(duì)我們的逆向之旅有一定的幫助
一、_dyld_start
_dyld_start
是程序執(zhí)行的起點(diǎn)漓拾,可以通過(guò)bt指令
查看到
在匯編中_dyld_start
調(diào)用dyldbootstrap::start
二阁最、dyldbootstrap::start
dyldbootstrap::start
函數(shù)中做了一些保護(hù)手段,并調(diào)用dyld::_main
三骇两、dyld::_main
3.1 配置環(huán)境變量
只要設(shè)置了這兩個(gè)環(huán)境變量參數(shù)速种,在App啟動(dòng)時(shí)就會(huì)打印相關(guān)參數(shù)、環(huán)境變量信息
3.2 加載共享緩存庫(kù)
調(diào)用checkSharedRegionDisable
函數(shù)檢查并加載共享緩存庫(kù)(iOS無(wú)法禁用共享緩存庫(kù))
3.3 實(shí)例化主程序
調(diào)用instantiateFromLoadedImage
函數(shù)
-
isCompatibleMachO
檢查machO的兼容性 -
instantiateMainExecutable -> sniffLoadCommands
實(shí)例化主程序
3.4 加載動(dòng)態(tài)庫(kù)
越獄的插件一般是在這里發(fā)光發(fā)熱的
3.5 鏈接主程序
鏈接主程序和動(dòng)態(tài)庫(kù)
接下來(lái)就是dyld最重要的部分
3.6 初始化方法
調(diào)用initializeMainExecutable
初始化方法低千,這是一個(gè)復(fù)雜的遍歷過(guò)程——先處理動(dòng)態(tài)庫(kù)配阵,再處理主程序
initializeMainExecutable
調(diào)用runInitializers
runInitializers
調(diào)用processInitializers
processInitializers
調(diào)用recursiveInitialization
recursiveInitialization
調(diào)用notifySingle
和doInitialization
notifySingle
先判斷sNotifyObjCInit
是否為空,再調(diào)用sNotifyObjCInit
回調(diào)
全局搜索示血,發(fā)現(xiàn)是在registerObjCNotifiers
中注冊(cè)的sNotifyObjCInit
回調(diào)
_dyld_objc_notify_register
調(diào)用registerObjCNotifiers
在objc源碼
中的_objc_init
處調(diào)用了_dyld_objc_notify_register
作為_dyld_objc_notify_register
的第二個(gè)參數(shù)棋傍,notifySingle
回調(diào)被調(diào)用也隨之調(diào)用,然后遍歷調(diào)用動(dòng)態(tài)庫(kù)中的+load
方法
在notifySingle
之后會(huì)調(diào)用doInitialization
-
doImageInit
會(huì)去判斷libSystem
是否初始化
doModInitFunctions
遍歷調(diào)用c++構(gòu)造方法
3.7 進(jìn)入主程序
至此难审,dyld流程就結(jié)束了瘫拣,接下來(lái)就是main函數(shù)的舞臺(tái)
四、dyld流程圖
五告喊、證明
新建動(dòng)態(tài)庫(kù)麸拄,分別在主程序和動(dòng)態(tài)庫(kù)中添加+load方法
和c++構(gòu)造方法
+ (void)load {
NSLog(@"主程序——load");
}
__attribute__((constructor)) void funcCooci(){
printf("主程序——c++");
}
Framework(Feng)——load
Framework(Feng)——c++
主程序——load
主程序——c++
事實(shí)證明動(dòng)態(tài)庫(kù)
先于主程序
執(zhí)行+load方法
和c++構(gòu)造方法
- 多個(gè)動(dòng)態(tài)庫(kù)的執(zhí)行先后順序取決于
General -> Framework, Libraries, and Embedded Content
順序
- 主程序中多個(gè)編譯單元的執(zhí)行先后順序取決于
Build Phases -> Compile Sources
順序
寫(xiě)在后面
想了解更多逆向相關(guān)知識(shí)不妨動(dòng)動(dòng)小手,添加一下咱們的交流群642363427來(lái)為你的技術(shù)多添一份光彩黔姜。