IOS逆向初探
0x00 前言
本文记录了某次逆向一个简单APP的过程,来简单介绍一下IOS逆向的流程,比较基础,属于入门级教程。包括砸壳、HOOK、插件的编写等一系列流程。
0x01 背景
前段时间在一个老师那里看到一群考研人的打卡信息,该APP能够详细的记录和分析学习过程。

考研人打卡信息
于是就下载试用了一下。但是免费版有许多的限制。如免费版的话仅可以添加2个"习惯"类代办,

添加代办
使用背景图也是需要开通季度卡的(虽然并没什么用)。

背景
手机上打开"季度卡"页面,由于手机经过了越狱,在开通的时候提示非常抱歉,由于Apple的安全策略,暂不支持越狱用户购买,可点击右上角获取帮助-其他问题联系我们解决。

越狱禁止购买
虽然免费版不影响正常使用,但是本着学习的态度想查看一下其越狱检测的绕过,结果发现竟然可以白嫖使用VIP功能。
0x02 逆向分析
IOS下逆向常规操作判断该APP是否加壳(加密),有壳的话先进行砸壳,然后利用IDA或者Hopper对脱壳后的Mach-O文件进行分析。首先需要准备一下环境和工具。
1.准备工作
手机设备:一台越狱的IOS手机,版本为12.4.1,安装了OpenSSH和Frida,Frida版本为14.1.3。
逆向分析工具:IDA或者Hopper。
开发工具:Xcode。
抓包工具:BurpSuite 或者Charles。
电脑上安装Frida版本为14.1.3。
由于是APPStore下载的APP,是经过了加壳的。接下来开始对该APP进行砸壳。
2. 砸壳
砸壳的脚本有很多,如frida-ios-dump、dumpdecrypted、Clutch、yacd等,这里采用的工具是frida-ios-dump。
安装方法:
git clone https://github.com/AloneMonkey/frida-ios-dump
cd frida-ios-dump
pip install -r requirements.txt --upgrade
安装完成所需的依赖后打开dump.py进行配置。
User = 'root'
Password = 'alpine'\#默认的密码
Host = 'localhost'
Port = 2222 \#根据自己的端口进行修改
KeyFileName = None
使用方法:
python3 dump.py APP名字 或者python3 dump.py Bundle identifier
将手机与电脑连接,打开APP,执行frida-ps -Ua,查看APP名字和Identifier。
frida-ps -Ua
PID Name Identifier
---- ------ --------------------
7312 APP名字 com.xxxx.tomatodo
然后进行砸壳
iproxy 2222 22
python3 dump.py com.xxxx.tomatodo
也可以执行
python3 dump.py APP名字进行砸壳

砸壳
砸了壳后提取出TomatoTime可执行文件,扔到IDA或者Hopper里面分析。
3.分析
根据关键文字进行搜索,这里搜索的是"越狱"。由于Mac上的IDA7.0搜不出来中文字符,所以可以使用Hopper搜索,找到函数位置后使用IDA打开。也可以全程使用Hopper进行分析。
使用hopper搜索"越狱"字符串

搜索字符串
发现是在方法startPay:中

找到方法startPay:
找到后可以继续使用Hopper进行分析,或者在IDA中分析,我在这里采用了IDA。
直接在函数中搜索-[SeasonCardController startPay:]。

IDA搜索方法
发现是该APP判断是否越狱,是根据是否存在Cydia来进行判断的。当/Applications/Cydia.app文件存在时,则提示用户越狱。
绕过这种越狱检测的方法也很简单,直接进行Hook fileExistsAtPath:方法即可。当判断/Applications/Cydia.app文件存在时将返回值改为0,即可绕过这里的越狱判断。
4. 越狱绕过
根据上面的分析,开始对-[NSFileManager fileExistsAtPath:]进行Hook。
代码如下:
var jailbreakPaths = ["/Applications/Cydia.app"];
var isJailBreakChecked = false
Interceptor.attach(ObjC.classes.NSFileManager["- fileExistsAtPath:"].implementation, {
onEnter: function (args) {
isJailBreakChecked = false;
this.path = new ObjC.Object(args[2]).toString(); // check if the looked up path is in the list of common\_paths
if (jailbreakPaths.indexOf(this.path) > -1) {
console.log("fileExistsAtPath: check for -\> " + this.path);
isJailBreakChecked = true;
}
},
onLeave: function (retval) {
if (!isJailBreakChecked) {
return;
}
console.log("change before:"+retval);
retval.replace(0);//当判断/Applications/Cydia.app文件存在时将返回值改为0
console.log("change after:" + retval);
}
});
执行方法:
frida -U -l tomatodo-jailbreak-bypass.js -f com.xxxx.tomatodo --no-pause

越狱绕过
此时再次打开APP,可以成功进入季度卡开通界面。