iOS越狱初体验
iOS越狱能做到什么?
- 查看 第三方APP UI 排版方式、布局实现技术
- 获取三方App内部资源 .assets/.plist/icon…
- 修改APP 功能重新打包 (EX: 去广告)
- 反编译推测原始工程代码内容
- dump 出 .h 头文件 / keycahin / db
越狱环境
macOS 版本:10.15 Catalina
iOS 版本:iPhone 5s (iOS 9.0.1/ 完美越狱*必要)
Cydia: Open SSH
逆向工程大致流程:
- 解密并导出应用程序、class-dump导出头文件
- 从当面界面入手,获取当前界面布局和控制器VC
- hook相关类,记录输出调用的顺序和参数
- 关键函数,查看调用堆栈,hook测试结果
- 静态分析+动态调试分析关键函数的实现逻辑
- 模拟或篡改函数调用逻辑
- 制作插件或移植到非越狱设备上
1、越狱环境搭建
- 完美越狱的5c手机iOS8-iOS8.4 or 完美越狱的5s系统iOS9-iOS9.1
- Mac安装
- iFunBox:管理文件系统
- iPhone安装
- 爱思助手
- Cydia
- 通过Cydia安装下面的源到越狱设备上
- Apple File Conduit 2:可以访问整个iOS文件系统
- iFile: 可以自由访问iOS文件系统
2、Mac远程登录到iPhone
使用SSH(Secure Shell安全外壳协议)来远程登录iPhone
- 使用SSH将所有传输的数据加密,防止DNS欺骗和IP欺骗
- 使用OpenSSH协议让Mac远程登录到iPhone
iPhone上通过Cydia来安装OpenSSH工具
- Cydia搜索OpenSSH
- 安装Openssh
- Mac终端:
- ssh root@host
- 输入初始密码alpine
- 退出登录:exit
1 | $ ssh root@192.168.0.110 |
password for ssh root@host
1 | $ sudo -s |
报错:ImportError: No module named usbmux
重新下载 usbmuxd工具包
保留
python-client
文件夹
变更服务器身份信息
- 删除公钥信息:
ssh-keygen -R yourIPAddress
- 删除known_hosts文件:
vim ~/.ssh/known_hosts
SSH基于秘钥的客户端认证
在客户端生成一对秘钥:公钥+私钥
1 | $: ssh-keygen |
- 一路敲回车键(Enter)即可
- OpenSSH默认生成的是RSA密钥,可以通过-t参数指定密钥类型
- 生成的公钥:~/.ssh/id_rsa.pub
- 生成的私钥:~/.ssh/id_rsa
将客户端的公钥追加到服务器的授权文件尾部:~/.ssh/authorized_keys
1 | ssh-copy-id root@yourIPAddress |
shell脚本文件
通过sh、bash、source命令执行sh脚本文件
- sh和bash会在当前shell环境启动一个子进程来执行文件,执行后返回到父进程的shell环境
- 执行cd时,子进程会进入到cd的目录,但是父进程的环境并未改变-即目录没有改变
source
- 在当前shell环境执行脚本文件
- 执行cd后自动跳转到cd的目录
- source可以用”.”代替,比如”.test.sh”使用source来执行shell脚本test.sh
基于秘钥登录
1、在客户端生成一对相关联的密钥,将客户端的公钥信息追加到服务器的授权文件尾部(~/.ssh/authorized_keys):
- 生成秘钥:
ssh-keygen
- 追加到服务器授权文件:
ssh-copy-id root@手机IP地址
- 复制客户端的公钥:
scp ~/.ssh/id_rsa.pub root@服务器主机地址:~
- SSH登录服务器:ssh root@服务器主机地址
- 生成秘钥:
2、执行脚本:
python ~/tcprelay.py -t 22:10086
- 利用usbmuxd编写的py脚本将Mac的10086端口连接到iPhone上的22端口上Mac登录到10086端口:
ssh -p 10086 root@localhost
- 利用usbmuxd编写的py脚本将Mac的10086端口连接到iPhone上的22端口上Mac登录到10086端口:
3、Mac登录到10086端口:
ssh -p 10086 root@localhost
1 | 5s:~/.ssh root# cat authorized_keys |
1 | 5s:~/.ssh root# cd /etc/ssh |
基于USB登录
下载usbmuxd工具包(下载v1.0.8版本,主要用到里面的一个python脚本:tcprelay.py)
https://cgit.sukimashita.com/usbmuxd.git/snapshot/usbmuxd-1.0.8.tar.gz1、Mac登录到10010端口:
python tcprelay.py -t 22:10010
2、将iPhone的22端口(SSH端口)映射到Mac本地的10010端口:
ssh root@localhost -p 10010
1
2
3
4$ python ~/pathto/python-client/tcprelay.py -t 22:10010
$ ssh root@localhost -p 10010
3、Cycript动态调试
- 它是Objective-C++、JavaScript、Java等语法的混合产物
- 用来修改和调试正在运行中的Mac/iOS 应用
- 官网:http://www.cycript.org/
- Cydia安装Cycript后,即可在iPhone上调试运行中的App
1、Cycript安装问题
1 | $ cycript |
方式1:替换libruby.2.6.dylib
解决方式一:由于我的MacOS是版本10.15.4 Catalina,自带ruby版本是2.6
如果你用homebrew已经安装过高版本的Ruby,那么你可以进到/usr/local/Cellar/ruby/2.6.0/lib这个目录下,将libruby.2.6.dylib拷贝一份,然后改名为libruby.2.0.0.dylib。并将改名后的文件拷贝到Cycript.lib目录下即可。
1 | ~: $ source .bash_profile |
如果是使用iTerm2+oh my zsh组合,可以在.zshrc配置文件中导入source .bash_profile
,这样每次打开就不用手动执行了!
1 | $ open ~/.zshrc |
方式2:安装ruby2.0
方式二:测试该方式对于MacOS Catalina无效,中文博客都是这种方式,brew install ruby@2.0 也无法在Catalina系统上通过,所以直接修改libruby.2.6.dylib为libruby.2.0.0.dylib是简单有效的方法
1、关闭Mac的SIP
- 电脑重启,听到咚的时候,按住
command+R
,进入恢复模式 - 打开终端,输入
csrutil disable
,重启
2、查看ruby版本安装ruby2.0
1 | $ cd /System/Library/Frameworks/Ruby.framework/Versions/ |
3、我的ruby版本是2.6直接把本机的ruby版本的复制一份,改为2.0即可
1、关闭系统的禁用新版SIP防护
电脑重启按住command+R,进入恢复模式
打开终端,输入csrutil disable,重启
如果想打开SIP,重复上两步,命令改为csrutil enable2、禁用SIP之后,在终端输入
sudo mount -uw /
,然后重启finder
之后就可以对文件夹进行复制了,复制之后,对文件夹和文件名称修改为2.0,就可以正常使用Cycript了
1 | sudo mkdir -p /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ |
2、Cycript使用
进程名称/进程ID
终端输入命令行:
1 | $ ps -A |
启动越狱iPhone上的App如下:
1 | /var/mobile/Containers/Bundle/Application/AAB4F619-1565-4D60-98B7-9A5465674C0E/ElevenPlayer.app/ElevenPlayer |
- ElevenPlayer
- Taobao4iPhone
- DingTalk
Cycript调试
1、通过Cydia安装Cycript
2、终端输入:
1 | cycript -p Taobao4iPhone |
Cycript基本语法
- UIApp: [UIApplication sharedApplication]
- var 变量名 = 变量值
- 通过内存地址获取内存中的对象: #内存地址
- 已经加载的所有OC类:ObjectiveC.classes
- 获取某个对象所有的成员变量:*对象名
- 递归打印view的所有子view:
view.recursiveDescription().toString()
等同于Xcode中的[view recursiveDescription]
- 筛选某种类型的对象:
choose(UIViewController) choose(UITableViewCell)
1 | 5s:~ root# cycript -p 1856 |
UIApp.keyWindow.recursiveDescription().toString()
可以打印所有层级
3、使用mjcript.cy
基于Cycript实现的一些实用函数,下载地址:https://github.com/CoderMJLee/mjcript
1、下载mjcript库
2、将
mjcript.cy
文件拖到/usr/lib/cycript0.9
3、SSH连接iOS设备
4、使用Cycript监听APP,通过命令
@import mjcript
导入
以前获取当前控制器
1 | cy# UIApp.keyWindow.rootViewController.presentedViewController |
mjcript获取当前控制器
1 | cy# MJFrontVc() |
获取实例方法和类方法
1 | cy# MJInstanceMethods(#0x12fe775e0) |
python获取unicode
1 | $ python |
获取网易登录界面
1 | cy# MJFrontVc() |
获取login相关方法
1 | cy# MJInstanceMethods(#0x12fe775e0,/login/) |
获取login相关成员变量
1 | cy# MJIvars(#0x12fe775e0,/login/) |
4、Reveal安装与使用
安装
当前的Cydia中软件源-http://apt.so/codermjlee已连接不上,直接下载Reveal2Loader_1.0-3的deb文件
- 网盘链接: 提取码: gk6j
下载后直接把deb文件放在手机的
Device/var/root
路径下安装之前需要先Cydia中安装
Applist
和RocketBootstrap
Cydia中安装ExtensionList
安装reveal2load报错extensionlist is not installed.:
1 | 5s:~ root# dpkg -i Reveal2Loader_1.0-3_iphoneos-arm.deb |
解决方法:
Cydia搜索并安装
ExtensionList 1.0-1
再次执行
dpkg -i Reveal2Loader_1.0-3_iphoneos-arm.deb
1
2
3
4
55s:~ root# dpkg -i Reveal2Loader_1.0-3_iphoneos-arm.deb
(Reading database ... 3164 files and directories currently installed.)
Preparing to unpack Reveal2Loader_1.0-3_iphoneos-arm.deb ...
Unpacking reveal2loader (1.0-3) over (1.0-3) ...
Setting up reveal2loader (1.0-3) ...- done
**The operation couldn’t be completed. **
The app is linked against an older version of the Reveal library. You may need to update the Reveal library in your app.
Reveal破解版不可用
如有破解版Reveal可参考:https://www.jianshu.com/p/f37ea9b9d2f3
5、脱壳
5.1 通过ipa获取Mach-O
PP助手下载的ipa包是解密后的包
Apple Configurator 2下载的ipa包是加密包
使用Apple Configurator 2下载ipa
2、进入Finder:
~/Library/Group Containers/K36BKF7T3D.group.com.apple.configurator/Library/Caches/Assets/TemporaryItems/
获取ipa,记得复制出来,弹框消失后IPA文件也会消失3、如果在解压ipa包时,出现“IPA已损坏 移除到垃圾篓”之类的提示,可以尝试把后缀名.ipa修改成.zip
4、解压zip包->进入Payload-> 右键显示包内容->获取可执行文件如下
4中获取的可执行文件不能正常导出头文件的话,直接查找越狱设备的一下路径:
/var/mobile/Containers/Bundle/Application/
可以获取当前越狱设备中安装的应用的.app文件,直接拷贝到Mac的Desktop上ps -A
查看当前App也能看到上面这个路径
5.2 Class-dump
1、下载地址:http://stevenygard.com/projects/class-dump/
2、打开终端输入 open /usr/local/bin
3、把dmg文件中的class-dump文件复制到 /usr/local/bin
4、更改权限:终端输入 sudo chmod 777 /usr/local/bin/class-dump
5、显示class-dump的用法和版本: class-dump --help
6、cd 到5.1获取的Mach-O文件所在目录
用终端输入命令 class-dump -H [MachO文件的路径] -o [输出文件夹路径]
,就可以得到所有的.h文件了
自己编译的项目没有加密,能够解析出来。class-dump不能直接将AppStore上的app的头文件导出来,你只会导出CDStructures.h这个头文件,而这里边基本是没有信息的。相当于Apple在app上加了一层壳(加密了),需要把这层壳砸破。
class-dump -H test.decrypted -o test,但是只能导出CDStructures.h,这个文件,但是
于是就使用class-dump -arch armv64 -H test.decrypted -o test 来导出,竟然能导出所有的头文件了。
5.2查看可执行文件是否加密?
使用MachOView
- Load Commands -> LC_ENCRYPTION_INFO -> Crypt ID的值
- 0代表未加密
使用otool
1 | otool -l machoFile | grep cycript |
5.3、Clutch脱壳
/usr/bin/Clutch Permission denied
1 | 5s:~ root# Clutch |
权限不够,输入命令如下:
1 | 5s:~ root# chmod +x /usr/bin/Clutch |
Clutch -i 查看可以脱壳的App
1 | 5s:~ root# Clutch -i |
Cluth -d 获取ipa文件
1 | 5s:~ root# Clutch -d 4 |
脱壳后生成IPA文件
IPA生成后的路径: /var/mobile/Documents/Dumped/
拷贝到桌面上查看当前的加密状态
1 | $ otool -l BaoManReader_old | grep crypt |
class-dump导出头文件headers
1 | $ class-dump -H BaoManReader -o Headers |