一、砸壳
软件脱壳,顾名思义,就是对软件加壳的逆操作,把软件上存在的壳去掉(解密)。
1.1 砸壳原理
1.1.1 应用加壳(加密)
提交给Appstore
发布的App
,都经过官方保护而加密,这样可以保证机器上跑的应用是苹果审核过的,也可以管理软件授权(企业包默认情况下也是没有加密的,TF
是加壳的。)。经过App Store
加密的应用,我们无法通过Hopper
等反编译静态分析,也无法Class-Dump
,在逆向分析过程中需要对加密的二进制文件进行解密才可以进行静态分析,这一过程就是大家熟知的砸壳(脱壳)。
App Store
是通过对称加密(AES
)加壳的,为了速度和效率。
1.1.2 应用砸壳(解密)
静态砸壳
静态砸壳就是在已经掌握和了解到了壳应用的加密算法和逻辑后在不运行壳应用程序的前提下将壳应用程序进行解密处理。静态脱壳的方法难度大,而且加密方发现应用被破解后就可能会改用更加高级和复杂的加密技术。
动态砸壳
动态砸壳就是从运行在进程内存空间中的可执行程序映像(image
)入手,来将内存中的内容进行转储(dump
)处理来实现脱壳处理。这种方法实现起来相对简单,且不必关心使用的是何种加密技术。在iOS
中都是用的动态砸壳。
1.2 iOS应用运行原理
- 加了壳的程序
CPU
是读不懂的,只有解密后才能载入内存。 -
iOS
系统内核会对MachO
进行脱壳。 - 所以我们只需要将解密后的
MachO
拷贝出来。 - 非越狱手机做不到跨进程访问,越狱后拿到
root
权限就可以访问了。这就是砸壳的原理。(按页加解密-代码段)
二、Clutch
Clutch
是由KJCracks
开发的一款开源砸壳工具。工具支持iPhone
、iPod Touch
、iPad
。该工具需要使用iOS8.0
以上的越狱手机应用。
2.1安装
Clutch官网找到发布的版本下载:
查看这个文件可以看到支持arm_v7
、arm_v7s
、arm64
设备:
➜ 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
2.2 使用
- 映射端口,
python
或者iproxy
都可以 具体可以参考openssl中的内容
usbConnect.sh
- 拷贝
Clutch
到手机(注意加可执行权限)
scp -P 端口 文件 用户@地址:目录/别名
➜ scp -P 12345 ./Clutch-2.0.4 root@localhost:/var/root/Clutch
Clutch-2.0.4 100% 1204KB 32.1MB/s 00:00
手机端查看:
zaizai:~ root# ls
Application\ Support/ Clutch Library/ Media/
zaizai:~ root# ls -l
total 1204
drwxr-xr-x 3 root wheel 96 Mar 17 2018 Application\ Support/
-rw-r--r-- 1 root wheel 1232832 May 25 16:59 Clutch
drwxr-xr-x 11 root wheel 352 Oct 23 2019 Library/
drwxr-xr-x 2 root wheel 64 Feb 27 2008 Media/
加可执行权限:
zaizai:~ root# chmod +x Clutch
zaizai:~ root# ls -l
total 1204
drwxr-xr-x 3 root wheel 96 Mar 17 2018 Application\ Support/
-rwxr-xr-x 1 root wheel 1232832 May 25 16:59 Clutch*
drwxr-xr-x 11 root wheel 352 Oct 23 2019 Library/
drwxr-xr-x 2 root wheel 64 Feb 27 2008 Media/
- 列出可以砸壳的应用列表
Clutch -i
root# ./Clutch -i
- 砸壳
Clutch –d 应用ID
root# Clutch –d 4
砸壳成功后的应用在Device->private->var->mobileDocuments->Dumped
目录下。
自己拷贝的应用是加壳的。
- 在手机端通过
ps -A
找到进程:14837 ?? 0:03.93 /var/containers/Bundle/Application/8F382114-BBA7-4D81-AA3E-3CD02E03E23E/WeChat.app/WeChat 16560 ttys000 0:00.02 grep WeChat
- 然后拷贝:
scp -P 12345 root@localhost://var/containers/Bundle/Application/8F382114-BBA7-4D81-AA3E-3CD02E03E23E/WeChat.app/WeChat
➜ otool -l WeChat | grep crypt cryptoff 28672 cryptsize 4096 cryptid 1
三、插入动态库
是通过DYLD_INSERT_LIBRARIES
来实现的。
- 创建一个
HPHook
动态库,创建一个类实现一个+load
方法:
+ (void)load {
NSLog(@"\n\n\nInject SUCCESS \n\n\n");
}
编译拷贝出HPHook.framework
。
- 拷贝
HPHook.framework
到越狱手机
➜ scp -r -P 12345 HPHook.framework root@localhost:/var/root
CodeResources 100% 2258 301.0KB/s 00:00
HPHook 100% 85KB 9.0MB/s 00:00
HPHook.h 100% 422 91.2KB/s 00:00
module.modulemap 100% 93 25.4KB/s 00:00
Info.plist 100% 744 187.8KB/s 00:00
-
-r
:代表循环拷贝文件夹。
- 查看手机
App
进程(任意一个)
zaizai:/var/root mobile$ ps -A | grep InsertDemo
16708 ?? 0:00.13 /var/containers/Bundle/Application/5AC46FE0-EB40-4FE2-BEA5-1AED9C95E7E9/InsertDemo.app/InsertDemo
16710 ttys000 0:00.01 grep InsertDemo
-
HPHook.framework
插入步骤3中的App
zaizai:/var/root mobile$ DYLD_INSERT_LIBRARIES=HPHook.framework/HPHook /var/containers/Bundle/Application/5AC46FE0-EB40-4FE2-BEA5-1AED9C95E7E9/InsertDemo.app/InsertDemo
2021-05-25 18:32:07.606 InsertDemo[16797:7420505]
Inject SUCCESS
这个时候就插入成功了。
iOS9.1
以后root
用户不能用DYLD_INSERT_LIBRARIES
(会报错kill 9
),需要切换到mobile
用户(su mobile
)。
主流App
会有防护,可以自己创建一个App
插入。
高版本的iOS
系统可能会遇到错误。
四、dumpdecrypted
dumpdecrypted
是Github
开源工具。这个工具就是通过建立一个名为dumpdecrypted.dylib
的动态库,插入目标应用实现脱壳。
4.1 安装
dumpdecrypted官网直接
git clone
通过
make
编译生成动态库:
➜ dumpdecrypted-master make
`xcrun --sdk iphoneos --find gcc` -Os -Wimplicit -isysroot `xcrun --sdk iphoneos --show-sdk-path` -F`xcrun --sdk iphoneos --show-sdk-path`/System/Library/Frameworks -F`xcrun --sdk iphoneos --show-sdk-path`/System/Library/PrivateFrameworks -arch armv7 -arch armv7s -arch arm64 -dynamiclib -o dumpdecrypted.dylib dumpdecrypted.o
ld: warning: directory not found for option '-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.4.sdk/System/Library/PrivateFrameworks'
ld: warning: directory not found for option '-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.4.sdk/System/Library/PrivateFrameworks'
ld: warning: directory not found for option '-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.4.sdk/System/Library/PrivateFrameworks'
直接在clone
的目录make
,最后会生成dumpdecrypted.dylib
:
- 拷贝到手机
➜ dumpdecrypted-master scp -P 12345 dumpdecrypted.dylib mobile@localhost:/var/mobile/
mobile@localhost's password:
dumpdecrypted.dylib 100% 209KB 24.6MB/s 00:00
- 通过
DYLD_INSERT_LIBRARIES
环境变量插入动态库执行
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/containers/Bundle/Application/36B02DC8-B625-4633-A2C7-45079855BFAC/Aweme.app/Aweme
需要将
dumpdecrypted.dylib
拷贝到mobile
路径中,为了导出有写的权限。dumpdecrypted.dylib
会导出和自己同一目录。
五、frida-iOS-dump
该工具基于frida
提供的强大功能通过注入js
实现内存dump
然后通过python
自动拷贝到电脑生成ipa
文件。
5.1 安装
5.1.1 Mac安装
- 查看
python
版本(Mac
自带)
➜ ~ python --version
Python 2.7.16
如果是
python3
这里需要改成python3
。根据自己的版本进行配置。
2.查看pip
版本
➜ ~ pip --version
pip 19.0.1 from /Library/Python/2.7/site-packages/pip-19.0.1-py2.7.egg/pip (python 2.7)
如果没有安装,执行:
sudo easy_install pip
卸载
pip
:python -m pip uninstall pip
,如果是python3
就安装pip3
。
3.安装frida
sudo pip install frida-tools
出现这个提示表明目录不归当前用户所有。请检查该目录的权限和所有者。需要
sudo
的-H
标志。
sudo -H pip install frida-tools
sudo -H
:set-home
将HOME
变量设为目标用户的主目录pip list
:列出所有安装的库
pip list --outdated
:列出所有过期的库
pip install --upgrade 库名
:更新库
5.1.2 iOS安装
- 添加源(可能需要科学上网)
https://build.frida.re
-
安装Frida
frida安装
iOS
端插件版本要与mac
端frida
版本对应,不一致可能会导致无法dump
。可以通过pip
升级。另外需要检查dump.py
中python
版本的配置。
5.2 Mac配置ios-dump
- 下载脚本
sudo git clone https://github.com/AloneMonkey/frida-ios-dump
或者直接去github
下载。然后拷贝到/opt
目录。
当然如果电脑上安装了
Monkey
那直接在monkey
目录中安装frida
就好了。不然的话导出环境变量可能会有冲突。(monkey
中已经导出dump.py
了)。直接在Monkey/bin
目录进行安装,将安装需要的内容直接从下载的frida-ios-dump
中拷贝到Monkey/bin
目录(其实只需要requirements.txt
,dump.js
和dump.py
。然后在该目录下安装依赖。
- 安装依赖
//sudo pip install -r /opt/frida-ios-dump/requirements.txt –upgrade
sudo pip install -r requirements.txt --ignore-installed six
在这个过程中有可能报错:
*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
版本://卸载 $sudo pip uninstall prompt-toolkit //安装指定版本 $sudo pip install prompt-toolkit==1.0.6
- 修改dump.py
User = 'root'
Password = 'alpine'
Host = 'localhost'
Port = 12345
一般只需要修改Port
就好了,和自己映射的本地端口一致。
5.3 frida 命令
-
frida-ps
:列出电脑上的进程
➜ ~ frida-ps
PID Name
----- --------------------------------------------------------------------------------
514 AirPlayUIAgent
573 AppSSOAgent
65527 Backup and Sync from Google
533 Backup and Sync from Google
636 CoreLocationAgent
73560 CoreServicesUIAgent
-
frida-ps -U
:列出手机进程
➜ ~ frida-ps -U
PID Name
----- -----------------------------------------------
15758 AlipayWallet
16643 BTFuwa
18079 CAReportingService
11127 CMFSyncAgent
1644 CommCenter
17367 ContainerMetadataExtractor
6691 EscrowSecurityAlert
16196 HeuristicInterpreter
11204 IDSRemoteURLConnectionAgent
16218 MQQSecure
11119 MobileGestaltHelper
17611 PhotosReliveWidget
10051 PinCleaner
-
frida -U 微❤
:进入微❤进程,调试微❤
➜ ~ frida -U AlipayWallet
____
/ _ | Frida 14.2.18 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
更多信息查看官网:https://frida.re/docs/ios/
5.4 砸壳
5.4.1 查看安装的应用
dump.py -l
可以查看已经安装的应用
➜ ~ dump.py -l
/Library/Python/2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in the next release.
from cryptography.hazmat.backends import default_backend
PID Name Identifier
----- ------------ -------------------------------
13582 微❤ com.tencent.xin
10769 支付宝 com.alipay.iphoneclient
9912 相机 com.apple.camera
11265 腾讯手机管家 com.tencent.mqqsecure
- Acrobat com.adobe.Adobe-Reader
- App Store com.apple.AppStore
- Cydia com.saurik.Cydia
- Enframe me.sspai.Enframe
- Excel com.microsoft.Office.Excel
这个时候是不需要映射的。
5.4.2 导出ipa
包
dump.py bundleId/displayName
:
//dump.py 微❤
dump.py com.tencent.xin
- 可以通过
bundleId
或者displayName
导出应用,推荐使用bundleId
。displayName
可能会有同名。如果有同名哪个排在前面导出哪个。 - 导出
ipa
包时需要app
在运行状态(正常情况下会自动打开App
),最好在前台不锁屏。 - 导出的
ipa
包一般在你执行导出命令的目录。(如果配置了环境变量,任何目录都可以执行)目录没有权限会报错。 - 导出包的时候是需要打开端口映射的。
验证(需要解压拿到.app
):
➜ otool -l WeChat.app/WeChat | grep crypt
cryptoff 16384
cryptsize 101646336
cryptid 0
-
cryptid
为0
表示没有加密,否则是加密的包。
错误信息
-
ImportError: No module named typing
pip
安装后报错:
➜ ~ sudo pip install frida-tools
Traceback (most recent call last):
File "/usr/local/bin/pip", line 11, in
load_entry_point('pip==21.1.1', 'console_scripts', 'pip')()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources/__init__.py", line 489, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources/__init__.py", line 2843, in load_entry_point
return ep.load()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources/__init__.py", line 2434, in load
return self.resolve()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources/__init__.py", line 2440, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "/Library/Python/2.7/site-packages/pip-21.1.1-py2.7.egg/pip/__init__.py", line 1, in
from typing import List, Optional
ImportError: No module named typing
解决方案:
pip版本
sudo easy_install pip==19.0.1
直接指定版本安装。
2.Invalid requirement: '–upgrade'
直接替换掉–upgrade
命令:
//sudo pip install -r /opt/frida-ios-dump/requirements.txt –upgrade
sudo pip install -r requirements.txt --ignore-installed six
3.如果遇见命令输入没有反映,电脑端frida
没有问题。那么需要重新安装手机端frida
。
4.Start the target app QQMusic unable to launch iOS app: The operation couldn’t be completed. Application info provider (FBSApplicationLibrary) returned nil for ""
如果App
启动后还是无法dump
,直接通过BundleId
dump
就好了。
总结
- 应用砸壳:一般应用为了防止反编译分析会对应用进行加密(加壳)。砸壳就是解密的过程。
- 静态砸壳:已经知道了解密方式,不需要运行应用的情况下直接解密。
- 动态砸壳:在应用启动之后从内存中找到应用的位置,dump(内存中)数据。
-
Clutch
( 命令行工具)-
Clutch -i
:列出可以砸壳的应用列表。 -
Clutch –d 应用ID
:砸壳
-
-
dumpdecrypted
(动态库)- 通过
DYLD_INSERT_LIBRARIES
环境变量插入动态库载入某个进程。 - 配置
DYLD_INSERT_LIBRARIES=dumpdecrypted路径 Macho路径
- 通过
-
frida-iOS-dump
(利用frida
加载脚本砸壳)- 安装
frida
(Mac
和iPhone
都需要) - 下载
frida-iOS-dump
脚本工具 - 执行
dump.py displayName /BundleId
- 安装