写点什么

iOS App 注入 SDK 调试

发布于: 2 小时前

前言

本文仅作为技术分享,对于一些 iOS SDK 开发以及维护所遇到的场景问题进行处理,例如:

  1. 客户想提前知晓线上 App 集成我们 SDK 后,是否会有 SDK 兼容性问题,例如 Crash,符号冲突

  2. 客户线上 App 集成了我们 SDK,出现了问题,如何进行排查

  3. 我们想测试 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

  1. 点击 Cydia->软件源->编辑->添加 添加源 build.frida.re ,apt.cydiami.com,并进行更新。

  2. 搜索 SSH ,选择 OpenSSH 进行安装

  3. 搜索 frida ,由于是 5S,我们选择 Frida for pre-A12 devices

  4. 搜索 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

  • 安装脚本依赖环境

cd frida-ios-dump目录下csudo pip install -r requirements.txt --upgrade
复制代码
  • 安装 usbmuxd 与手机通信 brew install usbmuxd

  • 通过 USB 使用 ssh 连接设备,将 22 映射到电脑上的 2222 端口

iproxy 2222 22
复制代码
  • 另开终端加入连接 密码为设备的登录密码 alpine,需要保持连接

ssh -p 2222 root@127.0.0.1或 ssh root@127.0.0.1 -p 2222
复制代码
  • 由于是动态砸壳,我们打开需要砸壳的 app,使用 frida-ps -Ua 查看正在运行的应用程序,记录下标识

 PID  Name   Identifier           ----  -----  ---------------------4621  爱思极速版  rn.notes.best        4650  番茄小说   com.dragon.read      4720  设置     com.apple.Preferences4547  邮件     com.apple.mobilemail 
复制代码
  • 然后 cd 到 frida-ios-dump 目录下,执行 dump.py 命令

dump.py com.dragon.read
复制代码
  1. 这里第一次运行在 0.00B [00:00, ?B/s] 卡住了,执行 Ctrl + C 取消,再重新开始 dump.py

  2. 最终在 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,再运行即可。

注入 SDK

  • 可以运行之后,我们在工程中初始化 pod,

修改pod文件,注释use_frameworks!# platform :ios, '9.0'
target 'PlayTheApp' do # Comment the next line if you don't want to use dynamic frameworks # use_frameworks! pod 'GrowingAnalytics-cdp/Autotracker' # Pods for PlayTheApp
end
target 'PlayTheAppDylib' do # Comment the next line if you don't want to use dynamic frameworks # use_frameworks! pod 'GrowingAnalytics-cdp/Autotracker' # Pods for PlayTheAppDylib
end

复制代码
  • 查找对应的 appdelegate 类,使用 class-dump 命令

1class-dump -H xxx.app -o yourDir/Headers
复制代码

发现其 AppDelegate 类叫 XXXXAppDelegate


// See <http://iphonedevwiki.net/index.php/Logos>
#import <UIKit/UIKit.h>#import "GrowingAutotracker.h"
static NSString *const kGrowingProjectId = @"91eaf9b283361032";
%hook XXXXAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BOOL result = %orig; GrowingTrackConfiguration *configuration = [GrowingTrackConfiguration configurationWithProjectId:kGrowingProjectId]; configuration.debugEnabled = YES; configuration.impressionScale = 1.0; configuration.dataCollectionServerHost = @"https://run.mocky.io/v3/08999138-a180-431d-a136-051f3c6bd306"; [GrowingAutotracker startWithConfiguration:configuration launchOptions:launchOptions]; return result;}
%end


复制代码

然后再编译运行,已经可以在 App 中调试 SDK,并有相关日志输出了。

至此我们解决了 前言 中所述的第 1 以及第 3 个场景问题,对于第 2 个问题,如何排查线上 App 所出现的 SDK 问题,则需要通过 MonkeyDev 运行之后观察日志输出,搭配注入代码,找准合适的入口方法或函数,进行方法交换,测试修改后,判定出现问题的点再判断如何解决。

局限性

对于此方案仍有不足

  1. 对于部分 App,即使砸壳后也无法正常使用。

  2. 如果 App 集成了老版本 SDK,想要注入新版本 SDK,就需要替换原文件或重命名。

此方案仍具有局限性,但足以应付大多数情况,后续我们也在完善这些不足,向自动化平台方案发展。

  1. 如果 App 集成了老版本 SDK,想要注入新版本 SDK,就需要替换原文件或重命名。

此方案仍具有局限性,但足以应付大多数情况,后续我们也在完善这些不足,向自动化平台方案发展。


发布于: 2 小时前阅读数: 2
用户头像

GrowingIO 技术团队经验分享 2020.05.09 加入

GrowingIO(官网网站www.growingio.com)的官方技术专栏,内容涵盖微服务架构,前端技术,数据可视化,DevOps,大数据方面的经验分享。 公众号:GrowingIO技术团队

评论

发布
暂无评论
iOS App注入SDK调试