什么是脱壳
iOS端App在上线之前会有苹果商店进行FairPlayDRM数字版权加密保护,我们称之为“加壳”。要对App Store分发的iOS App进行分析,我们需要先对App进行解密,我们称之为“脱壳”,有些人也称为“砸壳”。脱壳之后的二进制文件就是原始的、未加密的二进制文件。
注意,对于macOS上的App,苹果官方是不会对其进行加壳的。所以分析macOS App不需要执行脱壳操作。
判断是否加壳
网上有很多文章介绍如何判断iOS App是否被加壳。这里进行简单的介绍。
大家通常使用的判断加壳的方式是是使用machOView可视化工具或otool命令行工具。
这两个工具本质上都是看LC_ENCRYPTION_INFO
(LC代表load command)中的Crypt ID
字段。
使用otool检测
otool是Xcode自带的命令行工具,安装了Xcode的macOS系统不需要额外安装otool。
使用otool的如下命令可以检测App是否被加壳。如下:
代码语言:javascript复制otool -l mach-O文件 | grep crypt
例如:
image.png
如上:TEST是笔者App的已经脱壳的可执行文件。cryptid为0说明未加壳或已脱壳,cryptid为1说明App已加壳。
使用MachOView检测
不想使用otool命令行还可以使用MachOView,MachOView是一款开源的Mach-O可视化工具。通过MachOView可以清晰的查看Mach-O问价的内部结构。这里是MachOView的地址
)。将代码下载到本地使用Xcode编译成功后打开APP即可。使用MachOView打开目标Mach-O文件。展开“Load Commands”节点,选择“LC_ENCRYPTION_INFO_64”节点,右边的crypt ID即代表了是否加密。为0则代表未加密(没有壳或已脱壳),为1则代表已加密(已加壳)。
image.png
脱壳
按照脱壳的时机来区分,给App脱壳的方式分为两种:静态脱壳、动态脱壳。
静态脱壳:破解App的加壳原理,通过反向操作给App去壳。
动态脱壳:将App加载进内存,直接dump加载进内存的App的即可。
从操作难度上来看动态脱壳相对简单一些,因笔者也没有实践过静态脱壳,本文只介绍动态脱壳。
笔者了解到的冬天脱壳方式主要有三种:Clutch、dumpdecrypted、Frida。
关于Clutch和dumpdecrypted的使用方式网上教材众多,本文只是简单的罗列步骤,重点讲解Frida的使用。
Clutch
1.下载Clutch:https://github.com/KJCracks/Clutch/releases并重命名为Clutch
image.png
2.将Clutch文件拷贝到越狱iPhone的/usr/bin目录下
image.png
3.以root管理员身份登录iPhone,给Clutch赋予执行权限 chomd x /usr/bin/Clutch
image.png
4.Clutch -i
查看已经安装的App
5.Clutch -d app bundleId
执行脱壳操作。比如给上图的微信脱壳,命令如下:
// 通过bundleId来指定脱壳的App
# Clutch -d com.tencent.xin
// 或者 通过App的序号来指定脱壳的App
# Clutch -d 5
注意:因为是动态脱壳,使用Clutch脱壳前需要先启动目标App。
- 脱壳后的文件路径。脱壳成功后,命令行会列出脱壳后的文件在:/private/var/mobile/Documents/Dumped/ 目录下。 如果脱壳中遇到错误,但仍有部分文件脱壳成功(比如下面要说的Clutch -d 报错),那么此时产生的临时文件路径是:/var/tmp/clutch
- 将脱壳的文件从iPhone导出到电脑。有多重方式,可以用iOS逆向之必要软件安装 - 简书 中介绍的可视化工具。也可以用scp命令。该命令在iPhone上执行,命令格式如下(scp的详细使用见Linux scp命令 | 菜鸟教程):
iPhone:/ root# scp iPhone本地源文件 电脑userName@电脑ip地址:电脑目标路径
执行Clutch 命令报错:killed 9
执行Clutch -i报错:killed 9,如下图:
代码语言:txt复制iPhone:/usr/bin root# Clutch -i
Killed: 9
iPhone:/usr/bin root# Clutch -i
Killed: 9
解决办法:
iPhone 终端输入以下4条命令(参考自:越狱设备运行Clutch报错:Killed: 9
_jinrui_w的博客-CSDN博客)
iPhone:/usr/bin root# cd /private/var/mobile/Documents/
iPhone:/private/var/mobile/Documents root# ldid -e `which bash` > end.xml
iPhone:/private/var/mobile/Documents root# ldid -Send.xml `which Clutch`
iPhone:/private/var/mobile/Documents root# inject `which Clutch`
Clutch -d 命令报错:Error: Could not obtain mach port, either the process is dead (codesign error?) or entitlements were not properly signed!
如下图:
参考文章:Error: Could not obtain mach port, either the process is dead (codesign error?) or entitlements were not properly signed! · Issue #144 · KJCracks/Clutch · GitHub
按照提问者的说法,在/var/tmp/clutch目录下找到了dump出来的部分文件。
dumpdecrypted
dumpdecrpyted是开源的,需要先进行编译,然后再将编译好的dylib复制到越狱iPhone上。具体步骤如下:
1.通过git地址下载源码。
2.目录下执行make命令执行编译操作。
image.png
3.编译成功后目录下会多出一个dylib动态库文件。
image.png
4.将dylib复制到越狱设备的/var/root目录下(以root用户身份登录)
image.png
5.root身份登录iPhone并进入到dylib所在的iPhone目录
image.png
6.使用环境变量DYLD_INSERT_LIBRARIES将动态库dumpdecrpyted注入到需要脱壳的目标mach-O文件中。命令格式DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib 可执行文件路径
例如:
代码语言:javascript复制 DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/containers/Bundle/Application/5B7E8BAE-3F8E-448A-829E-452912476BC8/TEST.app/TEST
7.执行成功后目录下会多出一个xxx.decrypted文件。该文件就是脱壳后的可执行文件。
Frida
Frida-ios-dump基于Frida(一款跨平台的轻量级的Hook框架)提供的强大的功能,通过注入JS实现内存dump,然后利用Python脚本自动将内存复制到macOS,从而生成最终的脱壳后的ipa文件。
Frida-ios-dump的原理和dumpdecrypted一样,都是通过把内存汇总已解密的数据dump出来再修复mach-O,dan dumpdecrypted仅能dump主程序,对于框架需要自行修改源代码才能完成,操作比较麻烦。Frida-ios-dump提供的强大功能允许我们一键快速完成脱壳。
使用Frida脱壳要求越狱设备上安装Frida插件。具体操作步骤如下:
1.首先Cydia中添加源Frida源:https://build.frida.re
2.搜索并安装对应版本的Frida。笔者的越狱iPhone是64位的,iOS 版本是10.13.5,所以下载并安装了Frida for pre-A12 devices
3.Mac上在github上下载Frida-ios-dump:https://github.com/AloneMonkey/frida-ios-dump
4.进入本地的Frida-ios-dump目录下执行sudo pip install -r requirements.txt --upgrade
来安装python依赖
注意
:如果这一步安装Python依赖失败:可以尝试手动逐个安装requirements.txt中的python依赖库
5.mac终端执行iproxy 2222 22。把Mac上的2222端口映射到iPhone的22。前提是要保证此时iPhone已经和Mac通过usb进行了连接
注意
:如果这一步出现command not found:iproxy。说明Mac本地还没有iproxy。只需终端执行brew install usbmuxd。在安装usbmuxd的过程中iproxy会被自动安装。安装好后执行iproxy 2222 22
6.电脑当前目录下继续执行./dump.py -l
命令。列出iPhone上当前的所有应用
image.png
7.终端执行./dump.py bundleId
即可对app进行脱壳。
注意
:这一步需要我们把app启动
8.脱壳成功后,会在电脑的当前目录新增一个ipa文件。该文件就是脱壳后的APP包。
分离架构
我们最终脱壳出的二进制文件和使用的越狱设备有关。即arm64的越狱设备只能脱壳出arm64的可执行文件。Mach-O通常是胖二进制格式,也就是一个Mach-O文件包含多种架构,比如:arm64、armv7、armv7s等。胖二进制的目的是为了支持更多架构的iPhone。关于每款iPhone的架构可以自行Google。
搞过静态库和动态库的开发者对于分离架构应该并不陌生。在合并和分离二进制文件的时候,我们通常使用lipo命令。lipo是macOS自带的工具,其功能非常强大。下面列举了lipo命令常用的几个命令:
代码语言:javascript复制# 查看可执行文件的架构信息
命令格式:lipo -info Mach-O文件
# lipo -info WeChat
# 分离出某种特定架构
命令格式:lipo mach-O文件 -thin 架构类型 -output 分离的mach-O文件
# lipo WeChat -thin arm64 -output WeChat_arm64
# 合并多种架构
命令格式:lipo mach-O文件1 mach-O文件2 -output 合成的mach-O文件
# lipo WeChat_arm64 WeChat_armv7 -output WeChat
补充:查看可执行文件架构还可以使用file命令:
file Mach-O文件
例如:file WeChat
参考文章&链接
MachOView:https://github.com/gdbinit/MachOView
Clutch:https://github.com/KJCracks/Clutch/releases
dumpdecrypted:https://github.com/stefanesser/dumpdecrypted
frida-ios-dump:https://github.com/AloneMonkey/frida-ios-dump
《iOS应用逆向与安全之道》