参考资料:
https://opensource.apple.com/tarballs/dyld/dyld-360.18.tar.gz
https://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_exec.c
1 、解析mach-o文件,确定该文件是一个有效的Mach-O文件,所以内核为程序(fork)创建一个进程并开始程序执行过程(execve)
2、加载命令。内核配合动态连接器,进入加载指令指定分配的地址空间。段的虚拟内存保护标志也按指示添加上(例如__TEXT是只读)
a 动态库信息
b 符号表地址信息
c 动态符号表地址信息
d 常量字符串表地址信息
e 动态库加载信息
f 符号函数地址
g 依赖动态库信息
h 动态链接器路径信息
3 根据动态库加载信息,把__DATA段section __nl_symbol_ptr区占位符换为调用dylib的dyld_stub_binder函数的汇编指令。
4 根据LC_MAIN的entry point调用指定entry offset偏移地址执行entry offset相关汇编指令。
5 第一次运行到动态库函数时,进行一次懒加载动态绑定,并且动态链接器自动修改_la_symbol_ptr区的地址,指向动态库对应符号的地址。
6 第二次运行到动态库函数时,直接jmp到指定的符号地址
总结:
通过对Mach-O文件的分析,我们知道代码段(__TEXT)都是只读区,包含了程序逻辑处理。但是对于动态库的函数调用借助了数据段(__DATA)的_la_symbol_ptr区和_nl_symbol_pt区。用户可以去修改这两个区的数据,因此我们可以利用这个特性去替换相关函数的调用(如:fishhook)。注:通过DYLD_INSERT_LIBRARIES进行代码注入是dyld提供的功能。
链接:https://www.jianshu.com/p/e839543675b5
來源:简书