反编译 iOS 系统库二进制文件
前言
有时一些 Crash 是挂在系统库,如 CoreFoundation 里,因为是闭源的,没法直接分析代码。不过我们可以找到对应系统库的二进制文件进行反编译,查看对应汇编指令,结合 Crash 时的一些寄存器,以此猜测其执行流程。
笔者较常使用的反编译工具是 https://hopperapp.com/,免费版本每次可使用半小时,时间到后重新打开即可。
模拟器
模拟器相对简单些,以 Xcode 13.2.1 为例,其路径为:
1 | /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot |
以下是该目录存放库的几个主要子目录:
/System/Library/Framework
: 公开 Framework/System/Library/PrivateFrameworks
: 私有 Framework/Applications
: 系统 App/usr/lib
: UNIX 动态库
如 CoreFoundaion 二进制文件的存放路径为:
1 | /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation |
将之丢进 Hopper 里分析即可。
真机
找到 dyld_shared_cache
为了加快动态库的加载及减少磁盘体积占用,系统启动后会将一些动态库等 Mach-O 合并到一起作为缓存,合并后的二进制为 dyld_shared_cache
(名字后面可能还会跟着架构名,如 dyld_shared_cache_arm64e
) ,其路径为(不同机器可能会有点不一样):
1 | /System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e |
详情可查看 https://iphonedev.wiki/index.php/Dyld_shared_cache
所以我们只要拿到 dyld_shared_cache,再用一个工具提取出来即可。拿到这个文件有两种方式:
- 越狱机器,可直接去上面说的路径拿到;
- 非越狱机器,可下载对应机器、版本的 ipsw 固件文件,将之解压出来,内容如下:
1 | $ ls -al ~/Desktop/dyld/iPhone13,4_15.1.1_19B81_Restore |
找到最大的一个 dmg 文件打开,如上面 6G 多的 018-98837-002.dmg
,内容如下:
1 | $ ls -al /Volumes/SkyB19B81.D54pOS |
dyld_shared_cache 路径同样是上述所说的:
1 | /System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e |
生成提取工具
找到 dyld_shared_cache 后我们需要将之还原出来。
由于 dyld 是开源的,所以我们可以拿源码自己编译工具来进行提取,其开源代码可在 https://opensource.apple.com/tarballs/dyld/ 下载,解压。
- 查找
dsc_extractor.cpp
:
1 | $ cd ~/Desktop/dyld/dyld-852.2 |
- 使用
clang++
生成可执行指令:
1 | $ clang++ dyld3/shared-cache/dsc_extractor.cpp |
报错了,我们只需要提取功能就可以,所以需要修改该 cpp 文件,只保留相关代码。该代码在文件最下方(注意 #if 0
及下面的 #endif
也去掉),最终保留的代码如下:
1 | // test program |
好了,再来一次:
1 | $ clang++ dyld3/shared-cache/dsc_extractor.cpp |
如果报 fprintf 及 stderr 等错误,再去上述代码里注释掉重新执行命令即可。
最后没有报错后,生成可执行文件:
1 | clang++ -o dsc_extractor dsc_extractor.cpp |
此时在 dyld3/shared-cache
目录下会生成一个 dsc_extractor
可执行文件。
提取 dyld_shared_cache
命令用法:
1 | dsc_extractor 动态库文件路径 提取出来之后存放路径 |
执行命令:
1 | $ ./dsc_extractor /Volumes/SkyB19B81.D54pOS/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e arm64e |
之后就可以找到对应的二进制文件,如 CoreFoundation:
1 | ./arm64e/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation |
最后就可以把这二进制文件丢进 Hopper 里进行分析了。
附录
汇编指令手册查询:
https://developer.arm.com/documentation/dui0801/g/A64-General-Instructions/BL
iOS 崩溃日志在线符号化实践:
https://jishuin.proginn.com/p/763bfbd66433
Author: Arvit
Link: https://arvit.xyz/2022/03/01/iOS_system_dynamic_library/
License: 知识共享署名-非商业性使用 4.0 国际许可协议