iOS逆向 dyld流程

欢迎阅读iOS逆向系列(按序阅读食用效果更加)c++

写在前面

dyld做为苹果的动态连接器,是苹果操做系统的一个重要组成部分,在系统内容作好程序准备工做以后交由dyld负责余下的工做。所以了解dyld的加载过程对咱们的逆向之旅有必定的帮助bootstrap

因为在iOS探索系列已经经过iOS探索 浅尝辄止dyld加载流程dyld有过必定的介绍,本文只会精简介绍一下具体流程缓存

1、_dyld_start

_dyld_start是程序执行的起点,能够经过bt指令查看到 bash

在汇编中 _dyld_start调用 dyldbootstrap::start

2、dyldbootstrap::start

dyldbootstrap::start函数中作了一些保护手段,并调用dyld::_main 微信

3、dyld::_main

3.1 配置环境变量

只要设置了这两个环境变量参数,在App启动时就会打印相关参数、环境变量信息 函数

3.2 加载共享缓存库

调用checkSharedRegionDisable函数检查并加载共享缓存库(iOS没法禁用共享缓存库) post

3.3 实例化主程序

调用instantiateFromLoadedImage函数ui

  • isCompatibleMachO检查machO的兼容性
  • instantiateMainExecutable -> sniffLoadCommands实例化主程序

3.4 加载动态库

越狱的插件通常是在这里发光发热的 spa

3.5 连接主程序

连接主程序和动态库 操作系统

接下来就是dyld最重要的部分

3.6 初始化方法

调用initializeMainExecutable初始化方法,这是一个复杂的遍历过程——先处理动态库,再处理主程序

initializeMainExecutable调用runInitializers

runInitializers调用 processInitializers
processInitializers调用 recursiveInitialization
recursiveInitialization调用 notifySingledoInitialization
notifySingle先判断 sNotifyObjCInit是否为空,再调用 sNotifyObjCInit回调
全局搜索,发现是在 registerObjCNotifiers中注册的 sNotifyObjCInit回调
_dyld_objc_notify_register调用 registerObjCNotifiers
objc源码中的 _objc_init处调用了 _dyld_objc_notify_register
做为 _dyld_objc_notify_register的第二个参数, notifySingle回调被调用也随之调用,而后遍历调用动态库中的 +load方法


notifySingle以后会调用doInitialization

  • doImageInit会去判断libSystem是否初始化

doModInitFunctions遍历调用c++构造方法

3.7 进入主程序

至此,dyld流程就结束了,接下来就是main函数的舞台

4、dyld流程图

5、证实

新建动态库,分别在主程序和动态库中添加+load方法c++构造方法

+ (void)load {
    NSLog(@"主程序——load");
}

__attribute__((constructor)) void funcCooci(){
    printf("主程序——c++");
}
复制代码
Framework(Feng)——load
Framework(Feng)——c++
主程序——load
主程序——c++
复制代码

事实证实动态库先于主程序执行+load方法c++构造方法

  • 多个动态库的执行前后顺序取决于General -> Framework, Libraries, and Embedded Content顺序
  • 主程序中多个编译单元的执行前后顺序取决于Build Phases -> Compile Sources顺序

写在后面

迫于我的的强迫症,仍是选择了在iOS逆向系列中加了一篇关于dyld流程的文章,但与iOS探索系列不一样的是,这篇文章更加精炼、易于理解

相关文章
相关标签/搜索