1、动态库共享缓存
从iOS3.1开始,为了提高性能,绝大部分系统动态库文件都打包存放到了一个缓存文件中( dyld shared cache ),缓存文件在iPhone中的路径:/Svstem/Library/Caches/com.apple.dyld/dyld_shared_cache_armX
其中 dyld_shared_cache_armX 中的 X 代表ARM处理器指令集架构,各个指令集架构对应的设备如下:
armv6:
iPhone、iPhone3G、iPod Touch、iPod Touch2
armv7:
iPhone3GS、iPhone4、iPhone45
iPad、iPad2、iPad3(The New iPad)
iPad mini
iPod Touch3G、iPod Touch4 iPod Touch5
armv7s:
iPhone5、iPhone5C
iPad4
arm64:
iPhone 5s 及之后的设备
所有指令集原则上都是向下兼容的
动态库共享缓存一个非常明显的好处就是节省内存,把多个动态库文件合并成一个共享缓存类似于“压缩”的操作,可以节省额外的内存开销,对比如下图所示:
现在的ida、Hopper反编译工具都可以识别动态库共享缓存:
2、动态库的加载
在Mac/iOS中,是使用了 dyld 程序来加载动态库,文件位于iPhone中的/usr/lib/dyld。
可以翻译为 dynamic link editor,即动态链接编辑器 或者 dynamic loader,即动态加载器
观察 dyld源码 可知加载动态库的代码调用过程如下:
load - loadPhase0 - loadPhase1 - loadPhase2 - loadPhase4 - loadPhase5 - loadPhase5load - 最终调用了findInSharedCacheImage 去加载共享缓存中的动态库:
dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, orgPath, &shareCacheResults);
3、抽取动态库
找到dyld源码中的 dsc_extractor.cpp,并编译该文件(只保留 #if 0 和 #endif 中间的部分):
$ clang++ -o dsc_extractor dsc_extractor.cpp
得到可执行文件 dsc_extractor:
将可执行文件复制到动态库共享缓存相同目录下:
执行dsc_extrator进行抽取操作:
$ ./dsc_extractor dyld_shared_cache_arm64 arm64
arm64是导出文件夹名称
抽取完成后就可以得到系统的动态库文件了。
经测试iOS 14.7的动态库无法抽取,iOS 14.3可以。