前言
要想破解别人的App,第一步就是拿到ipa
包进行砸壳
,砸壳
也称作软件脱壳
,顾名思义,就是对软件加壳的逆
操作,把软件上存在的壳去掉(即解密)。
一、砸壳原理
1.1 应用加壳(加密)
提交给AppStore发布的App,都经过官方保护而加密,这样可以保证机器上跑的应用是苹果审核过的,也可以管理软件授权。
经过AppStore加密的应用,我们无法通过Hopper等反编译静态分析,也无法Class-Dump
。
在逆向分析过程中,需要对加密的二进制文件进行解密,然后才能进行静态分析,这一过程就是大家熟知的砸壳(脱壳)。
App Store是通过
对称加密(AES)
加壳的,为了速度和效率。
1.2 应用砸壳(解密)
-
静态砸壳
在已经掌握和了解到了壳应用的加密算法和逻辑后,在不运行壳应用程序的前提下,将壳应用程序进行解密处理。静态脱壳的方法难度大,而且加密方发现应用被破解后,就可能会改用更加高级和复杂的加密技术。 -
动态砸壳
从运行在进程内存空间中的可执行程序映像(image)
入手,将内存中的内容进行转储(dump)
处理来实现脱壳处理。这种方法实现起来相对简单,且不必关心使用的是何种加密技术。
在iOS系统中,应用砸壳所使用的都是
动态
砸壳技术。
1.3 iOS应用运行原理
-
加了壳
的程序CPU是读不懂的,只有解密
后才能载入内存。 - iOS系统内核会对
MachO
进行脱壳,所以我们只需要将解密后的MachO拷贝出来。 -
非越狱
手机做不到跨进程
访问,越狱
后拿到root权限
就可以访问了。这就是砸壳的原理。(按页加解密-代码段)
二、Clutch
Clutch
是由KJCracks
开发的一款开源砸壳
工具。工具支持iPhone、iPod Touch、iPad
,该工具需要使用iOS8.0以上
的越狱手机应用。
⚠️注意:
Clutch
属于命令行工具,适用于完美
越狱的设备。如果是非完美
越狱,砸壳时可能会出现问题
。
2.1 Clutch安装
- Clutch官网地址,直接找到Release版本
- 下载最新的
Clutch-2.0.4
- 使用
file
命令,查看Clutch
所支持的设备有哪些
file Clutch-2.0.4
-------------------------
Clutch-2.0.4: Mach-O universal binary with 3 architectures: [arm_v7:Mach-O executable arm_v7] [arm_v7s:Mach-O executable arm_v7s] [arm64:Mach-O 64-bit executable arm64]
Clutch-2.0.4 (for architecture armv7): Mach-O executable arm_v7
Clutch-2.0.4 (for architecture armv7s): Mach-O executable arm_v7s
Clutch-2.0.4 (for architecture arm64): Mach-O 64-bit executable arm64
可见,Clutch
是通用二进制文件,可以支持不同CPU架构的设备。
2.2 Clutch使用
- usb端口连接手机,使用
usbConnect.sh
和usb-iphone8.sh
,具体参考上篇文章
- 再新增终端窗口,将Clutch-2.0.4拷贝到手机的/var/root目录下,并且重命名为Clutch
scp -P 12345 ./Clutch-2.0.4 [email protected]:/var/root/Clutch
- 使用
-P
参数,指定USB连接的映射端口
,传输速度更快 - 前面是
本地文件路径
- 后面是
手机路径
,IP地址
要和登录时设置
的一致 - 拷贝的同时,可以
修改名称
- 如果拷贝的是
文件夹
,增加-r
参数
- 为
Clutch
增加可执行
权限
chmod +x Clutch
- 查看
Clutch
的用法
./Clutch
-------------------------
Usage: Clutch [OPTIONS]
-b --binary-dump Only dump binary files from specified bundleID
-d --dump Dump specified bundleID into .ipa file
-i --print-installed Print installed applications
--clean Clean /var/tmp/clutch directory
--version Display version and exit
-? --help Display this help and exit
-n --no-color Print with colors disabled
-
-b
仅从指定的bundleID
转储二进制文件 -
-d
将指定的绑定文件转储到.ipa
文件中 -
-i
打印安装的应用程序
例如查看安装的应用程序
./Clutch -i
-------------------------
1: 老司机汽车
2: 爱思加强版
3: 微信
⚠️注意:这里列出的软件,都可以进行
砸壳
。
砸壳演示
选择对WeChat
进行砸壳
./Clutch -d 3
-------------------------
com.tencent.xin contains watchOS 2 compatible application. It's not possible to dump watchOS 2 apps with Clutch 2.0.4 at this moment.
Zipping WeChat.app
ASLR slide: 0x1000b0000
Dumping (arm64)
Patched cryptid (64bit segment)
Writing new checksum
...
DONE: /private/var/mobile/Documents/Dumped/com.tencent.xin-iOS9.0-(Clutch-2.0.4).ipa
Finished dumping com.tencent.xin in 44.8 seconds
Clutch
同样使用的是动态砸壳
,所以理论上,砸壳前应该启动WeChat
,但是实际上并不需要,因为当Clutch
发现目标App未启动,会自动将其启动。
砸壳成功,给出.ipa包的路径
Device->private->var->mobileDocuments->Dumped
- 将砸壳后的.ipa包,导出到Mac电脑
-
在
root
目录下,连续2次cd ../
进入父文件夹,找到Device
目录
然后执行拷贝微信的
.ipa
包到Mac
电脑
scp -P 12345 root@localhost://Device->private->var->mobileDocuments->Dumped/com.tencent.xin-iOS9.0-(Clutch-2.0.4).ipa
- 解压出
MachO
文件,查看加密
状态
otool -l WeChat | grep crypt
-------------------------
cryptoff 16384
cryptsize 107446272
cryptid 0
cryptid
为0,处于未加密
状态,证明
三、dumpdecrypted
接着我们看看另一个砸壳工具 dumpdecrypted
。它是Github开源工具,通过建立一个名为dumpdecrypted.dylib
的动态库,插入
目标应用实现脱壳。
和
Clutch
一样,都是砸壳领域的经典插件。它们同样岁月沧桑,适用于完美越狱
的设备。如果是非完美
越狱,砸壳时可能会出现问题
。
3.1 插入自定义动态库
在演示dumpdecrypted
砸壳之前,我们看看如何在手机中插入一个自定义的动态库
。
- 创建
Inject
动态库,添加InjectCode
类,写入代码
#import "InjectCode.h"
@implementation InjectCode
+(void)load {
NSLog(@"\n\n\n\n\n\n\n\n\n\n");
}
@end
- 编译项目,生成
Inject.framework
- 将
Inject.framework
拷贝到手机的/var/root
目录下
scp -r -P 12345 ./Inject.framework [email protected]:/var/root
Inject.framework
是文件夹,所以需要加上-r
参数,拷贝目录下所有文件。
- USB连接手机
usb-iphone8.sh
- 查看WeCath进程
ps -A | grep WeChat
- 使用
DYLD_INSERT_LIBRARIES
,将Inject.framework
插入到WeCath
进程
DYLD_INSERT_LIBRARIES=Inject.framework/Inject /var/containers/Bundle/Application/B9046860-DDDA-44B4-AFF5-AF20FFA6FC9D/WeChat.app/WeChat
上图可见,出现了Killed: 9
的错误,因为
在
iOS 9.1
以上系统,不允许root用户
插入动态库.
解决方法 切换成mobile用户
,才可执行成功。
su mobile
Arons-iPhone8:~ mobile$ DYLD_INSERT_LIBRARIES=Inject.framework/Inject /var/containers/Bundle/Application/B9046860-DDDA-44B4-AFF5-AF20FFA6FC9D/WeChat.app/WeChat
2021-06-05 18:32:07.606 WeChat[16797:7420505]
注入的代码在WeChat
进程中执行成功!
3.2 dumpdecrypted安装
现在我们来安装下dumpdecrypted
官网链接
- 克隆
dumpdecrypted
git clone https://github.com/stefanesser/dumpdecrypted.git
- 进入
dumpdecrypted
目录,执行make
命令
编译生成动态库dumpdecrypted.dylib
3.3 dumpdecrypted砸壳演示
接下来,我们来使用dumpdecrypted.dylib
砸壳。
- 将
dumpdecrypted.dylib
拷贝到手机的/var/root
目录下
scp -P 12345 ./dumpdecrypted.dylib [email protected]:/var/root
- 使用
DYLD_INSERT_LIBRARIES
,将dumpdecrypted.dylib
插入到WeCath
进程
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/containers/Bundle/Application/B9046860-DDDA-44B4-AFF5-AF20FFA6FC9D/WeChat.app/WeChat
-------------------------
objc[5571]: Class MarsReachability is implemented in both /private/var/mobile/Containers/Bundle/Application/B1661526-3E43-4397-9E86-A9735DE89AE1/WeChat.app/Frameworks/mars.framework/mars and /private/var/mobile/Containers/Bundle/Application/B1661526-3E43-4397-9E86-A9735DE89AE1/WeChat.app/Frameworks/matrixreport.framework/matrixreport. One of the two will be used. Which one is undefined.
objc[5571]: Class WCLogger is implemented in both /System/Library/Frameworks/WatchConnectivity.framework/WatchConnectivity and /var/containers/Bundle/Application/B9046860-DDDA-44B4-AFF5-AF20FFA6FC9D/WeChat.app/WeChat. One of the two will be used. Which one is undefined.
mach-o decryption dumper
...
[+] Closing original file
[+] Closing dump file
在当前目录
下,导出WeChat.decrypted
文件,是砸壳后的MachO
文件。
⚠️注意:需要将
dumpdecrypted.dylib
拷贝到mobile
路径中,为了导出有写
的权限。dumpdecrypted.dylib
会导出和自己同一目录。
- 将
WeChat.decrypted
文件,导出到Mac电脑,otool查看是否加密
otool -l WeChat.decrypted | grep crypt
-------------------------
WeChat.decrypted:
cryptoff 16384
cryptsize 107446272
cryptid 0
cryptid
为0,处于未加密
状态,证明导出的WeChat.decrypted
砸壳成功
版本问题
使用dumpdecrypted
工具,要求Xcode SDK
与越狱设备iOS SDK
版本一致!
例如:对iOS 9.1
的设备插入dumpdecrypted.dylib
,就要使用老版本
的Xcode
对dumpdecrypted
进行make
。否则在插入dumpdecrypted.dylib
时,会出现以下错误
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/B1661526-3E43-4397-9E86-A9735DE89AE1/WeChat.app/WeChat
-------------------------
dyld: Symbol not found: ___chkstk_darwin
Referenced from: dumpdecrypted.dylib
Expected in: /usr/lib/libSystem.B.dylib
in dumpdecrypted.dylib
Trace/BPT trap: 5
四、frida-ios-dump
frida-ios-dump
工具是基于frida
提供的强大功能,通过注入js
实现内存dump
,然后通过python
自动拷贝到电脑
生成ipa文件
。
frida-ios-dump
支持众多版本的系统,非完美越狱
的环境也可使用
,是目前最常用、最稳定
的砸壳工具!
4.1环境配置
4.1.1 pip安装
pip
的安装和python
版本有关
-
python
安装使用pip
- 而
python3
安装使用pip3
- 查看
python
版本
python --version
-------------------------
Python 2.7.16
查看python3
版本
python3 --version
-------------------------
Python 3.8.2
查看pip
版本
pip -V
查看pip3
版本
pip3 -V
- 使用
easy_install
命令,安装pip
sudo easy_install pip
使用
easy_install
的方式,我没有安装成功。pip和pip3都尝试过,安装后一直提示版本问题,无法使用。
- 使用
get-pip
安装
git clone https://github.com/pypa/get-pip.git
指令执行完成后,我们来到public
目录下查看
- 使用
python3
执行get-pip.py
脚本,安装pip3
python3 get-pip.py
4.1.2 frida安装
- 在
iOS
手机端
打开
Cydia
,添加源:https://build.frida.re安装
Frida
- 在
Mac电脑
端
sudo pip3 install frida-tools
⚠️注意:可能会出现警告
you may want sudo's -H flag
上图意思是目录不归当前用户所有
。请检查该目录的权限和所有者,需要sudo的-H标志。
sudo -H
set-home
将HOME
变量设为目标用户的主目录
。
sudo -H pip3 install frida-tools
⚠️注意:出现
Uninstalling a distutils installed project (six)
提示,执行以下命令
sudo pip3 install frida --upgrade --ignore-installed six
4.1.3 frida使用
- 查看
Mac
电脑的进程
frida-ps
-
USB
连接设备,查看手机
上的进程
frida-ps -U
⚠️注意:如果执行
frida-ps -U
指令后没反应
进入frida-ios-dump
目录,然后执行sudo pip3 install -r requirements.txt --upgrade
即可!
- 进入WeChat进程
frida -U 微信
- 输出
WeChat
内存中的对象
ObjC
-
frida
更多语法
官方文档
frida优缺点
-
frida
擅长将js和python
脚本,注入
到目标程序并执行,它并不适合
作为动态分析
的工具使用。 -
frida-ios-dump
就是将dump.py
,通过frida
注入目标程序,从而实现应用砸壳。
4.2 frida-ios-dump的使用
在Mac电脑,配置
frida-ios-dump
右边官网链接克隆
frida-ios-dump
sudo git clone https://github.com/AloneMonkey/frida-ios-dump
查看frida-ios-dump
目录
- 安装依赖
sudo pip3 install -r requirements.txt --upgrade
4.2.1出现的错误
-
prompt-toolkit
版本不兼容问题
frida-tools 1.2.2 has requirement prompt-toolkit<2.0.0,>=0.57, but you'll have prompt-toolkit 2.0.7 which is incompatible.
解决 需要降低prompt-toolkit
版本
- 卸载prompt-toolkit
sudo pip uninstall prompt-toolkit
- 安装指定版本
sudo pip install prompt-toolkit==1.0.6
-
-H
警告,同样使用sudo -H
解决
sudo -H pip3 install -r requirements.txt --upgrade
4.2.2 frida-ios-dump砸壳演示
- 进入
frida-ios-dump
目录,执行dump.py
脚本
./dump.py 微信
-------------------------
Traceback (most recent call last):
File "./dump.py", line 11, in
import frida
ImportError: No module named frida
遇到上述问题,先检查frida-ios-dump
目录的读写权限
,没有则加一个
- 打开
dump.py
文件,需要将python
修改为python3
- 再执行
./dump.py 微信
-------------------------
[Errno None] Unable to connect to port 2222 on 127.0.0.1, ::1 or fe80::1
Try specifying -H/--hostname and/or -p/--port
还是执行失败
了,因为在dump
的时候,会将ipa包
导出到Mac电脑
,此时需要USB连接设备
。所以在dump
之前,应该先执行usbConnect.sh
脚本
- 检查
dump.py
文件中的User、Password、Host、Port
,是否和usbConnect.sh
脚本中的配置一致, 修改Port
,将2222
修改为12345
- 再次执行
dump.py
脚本
./dump.py 微信
-------------------------
Start the target app 微信
Dumping 微信 to /var/folders/jl/d06jlfkj2ws74_5g45kms07m0000gn/T
[frida-ios-dump]: ilink_network.framework has been loaded.
...
Generating "微信.ipa"
执行成功后,会在frida-ios-dump
目录下,成功导出微信.ipa
可以将其配置为
环境变量
,方便使用!
五、iOS终端支持中文
iOS终端
默认是不支持中文
的。解决方案
- 创建
.inputrc
隐藏文件,写入以下代码
set convert-meta off
set output-meta on
set meta-flag on
set input-meta on
- 将
.inputrc
文件,拷贝到手机的/var/root
目录下
scp -P 12345 .inputrc root@localhost:/var/root
- 在
iOS终端
输入中文验证
总结
- 砸壳原理
- 应用
加壳
一般应用为了防止反编译分享,会对应用进行加密(加壳) - 应用
砸壳
砸壳(脱壳)就是解密的过程
◦静态
砸壳 已经知道了解密方式,不需要运行应用的情况下,直接解密
◦动态
砸壳 在应用启动后,从内存中找到应用的位置,dump
(内存中导出)数据
- 应用
-
Clutch
- 是一个命令行工具
-
Clutch -i
查看安装的应用程序 -
Clutch -d 应用编号
导出ipa包
-
dumpdecrypted
- 是一个动态库,不能独立运行
- 通过
DYLD_INSERT_LIBRARIES
环境变量,插入动态库,载入某个进程
DYLD_INSERT_LIBRARIES = 库路径(库的可执行文件) MachO路径
-
iOS 9.1以上
系统,不允许root
用户使用DYLD_INSERT_LIBRARIER
方式插入动态库,需要su mobile
切换成mobile
用户
-
frida-ios-dump
- 利用
frida
加载脚本砸壳 -
Mac
和iPhone
都需要安装frida
, - 下载
frida-ios-dump
脚本工具 - 执行
dump.py
,参数是应用名称
或BundleID
- 利用
- iOS终端
支持中文
- 创建
.inputrc
隐藏文件,写入代码 - 拷贝到手机的
/var/root
目录下
- 创建