iOS App 注入 SDK 调试
前言
本文仅作为技术分享,对于一些 iOS SDK 开发以及维护所遇到的场景问题进行处理,例如:
客户想提前知晓线上 App 集成我们 SDK 后,是否会有 SDK 兼容性问题,例如 Crash,符号冲突
客户线上 App 集成了我们 SDK,出现了问题,如何进行排查
我们想测试 SDK 在某一款 App 中是否功能正常
对于这些问题,一般来说我们无法拿到 App 的源码,想要处理这些场景,就需要拿到客户 App 文件并注入代码,接下来我们从 iOS 越狱、frida 砸壳、MonkeyDev 来讲述如何实现。
iOS 越狱
为什么需要越狱?因为正常情况下,我们无法从手机中获取到 App 的包文件,只能通过越狱机 动态砸壳 获得 ipa 包,使用目前主流的 unc0ver 进行越狱。
unc0ver
对于 iOS 的越狱,这里使用的是 unc0ver ,最新版本支持 iOS 11 - iOS 14.3 版本的非完美越狱,这里采用使用 iphone 5S, iOS 12.4.9 为例,进行 非完美越狱
越狱有分为“完美越狱”和“不完美越狱”。完美越狱简单地说就是越狱很彻底,破解了操作系统的读写权限,完美越狱完成以后可以自由使用,开关机,下载等。称为“完美越狱”。而不完美越狱,则表示 iPhone 或 iPad 不能像越狱之前一样随时可以关机,关机重启后越狱失效,需要再进行越狱操作。
对于 unc0ver ,我们使用 Xcode + iOS App Signer 方式进行安装 unc0ver App
通过上述步骤生成的 unc0ver ipa 是符合苹果要求的,你也可以通过 i4助手(爱思助手) 进行快捷安装到手机中。
打开 unc0ver,点击 Jailbreak 进行越狱,期间弹出 REBEL 不要管它,叉掉,继续。提示你重启就重启,该允许的允许,然后继续打开 unc0ver 继续,直到 unc0ver 完成越狱,越狱好后,手机界面会多出 Cydia 和 Substitude,同时打开 unc0ver 显示 Re-Jailbreak 。
配置 Cydia
点击 Cydia->软件源->编辑->添加 添加源 build.frida.re ,apt.cydiami.com,并进行更新。
搜索 SSH ,选择 OpenSSH 进行安装
搜索 frida ,由于是 5S,我们选择 Frida for pre-A12 devices
搜索 AFC ,安装 AFC2 iOS12 系统文件访问
至此,越狱完成,可以访问系统文件了。
Frida 砸壳
砸壳的目的是为了获取 ipa 包,由于 Appstore 默认给应用程序加了壳(并不知道其使用了那种加密方式),所以需要先砸壳(相当于获取解密后的文件),你可以通过 AppStore 下载你需要砸壳的 App ,也可以下载 i4 助手 上的 App ,安装到手机上后,我们进行动态砸壳。
动态砸壳:在运行进程内存中的可执行程序映像入手,将内存中的内容进行转储处理来实现砸壳。该方法相对简单,并且不用关心应用所使用的加密技术。
对于各种砸壳方案,这里使用的 Frida 砸壳:
下拉 frida-ios-dump
git clone https://github.com/AloneMonkey/frida-ios-dump
下拉仓库。
安装 Python brew install python
安装 wget brew install wget
安装 pip
wget <https://bootstrap.pypa.io/get-pip.py> sudo python get-pip.py
安装 frida sudo pip install frida –-upgrade –ignore-installed six
安装脚本依赖环境
安装 usbmuxd 与手机通信 brew install usbmuxd
通过 USB 使用 ssh 连接设备,将 22 映射到电脑上的 2222 端口
另开终端加入连接 密码为设备的登录密码 alpine,需要保持连接
由于是动态砸壳,我们打开需要砸壳的 app,使用 frida-ps -Ua 查看正在运行的应用程序,记录下标识
然后 cd 到 frida-ios-dump 目录下,执行 dump.py 命令
这里第一次运行在 0.00B [00:00, ?B/s] 卡住了,执行 Ctrl + C 取消,再重新开始 dump.py
最终在 frida-ios-dump 目录下得到砸壳 ipa 文件
MonkeyDev
原有 iOSOpenDev 的升级,非越狱插件开发集成神器,这里仅仅使用了其部分功能,具体的安装步骤说明见 MonkeyDev安装 。
使用
拿着之前通过 Frida 砸壳获取的 ipa 包(例如:某宝,某度,某某音乐),先创建一个 MonkeyDev 工程。这里以 PlayTheApp 为例
将砸壳的 ipa 放到 PlayTheApp/TargetApp/ 下,然后拖拽至工程文件中。
设置主工程的证书,dylib 的不用设置
提示 Showing All Messages Signing for "PlayTheAppDylib" requires a development team. Select a development team in the Signing & Capabilities editor. ,此时选择 PlayTheAppDylib->Build Settings->Add User-Defined Setting 添加 CODE_SIGNING_ALLOWED 为 NO,再运行即可。
file not found: /usr/lib/libstdc++.dylib 问题 原因是新版本 xcode 去掉了 libstdc++这个库,从老版本复制过来即可,这里直接使用 Github 上的 GitHub - devdawei/libstdc-: Xcode 10、11 和 12 中删除的 libstdc++ 库 (目录权限问题这里不再阐述)
注入 SDK
可以运行之后,我们在工程中初始化 pod,
查找对应的 appdelegate 类,使用 class-dump 命令
发现其 AppDelegate 类叫 XXXXAppDelegate
然后使用 logos 注入 SDK 初始化代码,使用文档查看官网 Logos - iPhone Development Wiki
然后再编译运行,已经可以在 App 中调试 SDK,并有相关日志输出了。
至此我们解决了 前言 中所述的第 1 以及第 3 个场景问题,对于第 2 个问题,如何排查线上 App 所出现的 SDK 问题,则需要通过 MonkeyDev 运行之后观察日志输出,搭配注入代码,找准合适的入口方法或函数,进行方法交换,测试修改后,判定出现问题的点再判断如何解决。
局限性
对于此方案仍有不足
对于部分 App,即使砸壳后也无法正常使用。
如果 App 集成了老版本 SDK,想要注入新版本 SDK,就需要替换原文件或重命名。
此方案仍具有局限性,但足以应付大多数情况,后续我们也在完善这些不足,向自动化平台方案发展。
如果 App 集成了老版本 SDK,想要注入新版本 SDK,就需要替换原文件或重命名。
此方案仍具有局限性,但足以应付大多数情况,后续我们也在完善这些不足,向自动化平台方案发展。
版权声明: 本文为 InfoQ 作者【GrowingIO技术专栏】的原创文章。
原文链接:【http://xie.infoq.cn/article/dcc6733a74c28401290ed2c6e】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论