前言

本文仅作为技术分享,对于一些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/AloneMonke...
    下拉仓库。
  • 装置Python
    brew install python
  • 装置wget
    brew install wget
  • 装置pip
    wget https://bootstrap.pypa.io/get... 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,再运行即可。

  • file not found: /usr/lib/libstdc++.dylib 问题

起因是新版本xcode去掉了libstdc++这个库,从老版本复制过去即可,这里间接应用Github上的 GitHub - devdawei/libstdc-: Xcode 10、11 和 12 中删除的 libstdc++ 库 (目录权限问题这里不再论述)

注入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 PlayTheAppendtarget 'PlayTheAppDylib' do  # Comment the next line if you don't want to use dynamic frameworks  # use_frameworks!  pod 'GrowingAnalytics-cdp/Autotracker'  # Pods for PlayTheAppDylibend
  • 查找对应的appdelegate类,应用class-dump命令
1class-dump -H xxx.app -o yourDir/Headers

发现其 AppDelegate 类叫 XXXXAppDelegate

  • 而后应用logos注入SDK初始化代码,应用文档查看官网 Logos - iPhone Development Wiki
// 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,就须要替换原文件或重命名。

此计划仍具备局限性,但足以应酬大多数状况,后续咱们也在欠缺这些有余,向自动化平台计划倒退。