iOS应用脱壳(解密)的几种方式

我们日常开发提交给Appstore发布的App,都经过官方保护而加密,这样可以保证机器上跑的应用是苹果审核过的,也可以管理软件授权。经过App Store加密的应用,我们无法通过Hopper等反编译静态分析,也无法Class-Dump,在逆向分析过程中需要对加密的二进制文件进行解密才可以进行静态分析,这一过程就是大家熟知的砸壳(脱壳)

脱壳原理:从内存中dump出MachO

一、Clutch

由KJCracks开发的一款开源砸壳工具。

具体操作

1、使用Clutch,下载最新的release版本,可得到一个名为Clutch-2.0.4的胖二进制文件。
2、通过usb登录越狱设备。
3、通过命令scp -P 12345 Clutch-2.0.4 root@localhost:/usr/bin将其拷贝到越狱设备的指定目录下。
可通过mv Clutch-2.0.4 Clutch对其重命名。

4、查看Clutch的可执行权限。没有的话就chmod +x Clutch添加权限即可。
5、进入到越狱设备的命令行操作界面。通过Clutch命令可查看相关命令帮助信息。

1
2
3
4
5
6
7
8
9
10
11
Dyoung5s:~ root# pwd
/var/root
Dyoung5s:~ root# Clutch
Usage: Clutch [OPTIONS]
-b --binary-dump <value> Only dump binary files from specified bundleID
-d --dump <value> 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

6、Clutch -i 显示可砸壳的应用列表。

1
2
3
4
5
6
7
8
9
10
Dyoung5s:~ root# Clutch -i
Installed apps:
1: 微博国际版 <com.weibo.international>
2: 淘宝-双十二购物,移动生活社区 <com.taobao.taobao4iphone>
3: 今日头条极速版 <com.ss.iphone.article.lite>
4: QQ <com.tencent.mqq>
5: DingTalk <com.laiwang.DingTalk>
6: 酷狗音乐-就是歌多 <com.kugou.kugou1002>
7: 抖音短视频 <com.ss.iphone.ugc.Aweme>
8: 爱思助手 <com.diary.mood>

7、Clutch -d 4选择要砸壳的应用,并进行砸壳,成功后有如下提示。将其拷贝出来即可。我们也可以通过otool -l查看其cryptid字段以验证是否砸壳成功。

二、dumpdecrypted

通过建立一个名为dumpdecrypted.dylib的动态库,插入目标应用实现脱壳。

1、下载dumpdecrypted,并通过make命令编译生成dylib库。

2、通过命令scp -P 12345 dumpdecrypted.dylib root@localhost:~/将动态库拷贝越狱设备的指定目录。

3、通过ps -A查看当前进程,并通过如下命令将其动态库插入到指定进程中。即可生成对应进程应用的MachO文件。

1
2
//后面加上的进程路径。
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/A8CC18F5-9213-482E-B145-C36EFE9ACED0/DingTalk.app/DingTalk


三、frida-ios-dump

安装

1、下载pip

1
sudo easy_install pip

2、通过pip下载frida_tools

1
2
3
sudo -H pip install frida_tools
//如果报下图中的错误则更换为另外一条命令。
sudo pip install six --upgrade --ignore-installed six

3、直接clonefrida-ios-dump到本地目录,进入目录可发现dump.py脚本文件。

4、修改dump.py文件中的如下信息,确保与越狱设备信息匹配。

5、在越狱设备中添加https://build.frida.re源,并且安装Frida插件.

dump应用

将脱壳应用在设备上置于运行状态。进入脚本所在文件夹,通过./dump.py 微信便可成功脱壳应用。成功后会在脚本文件所在文件夹中生成ipa包。

以上dump时的操作可写成脚本,将frida-ios-dump文件夹放置sh脚本文件的同级目录中。编写脚本,并配置环境变量即可。

1
2
//脚本内容:
dump.py的路径 $1
遇到的一些坑:

1、No module named xxx。 通过pip install --user xxx下载即可。

2、from scp import xxx,同上执行pip install --user xxx即可。

3、生成ipa,存放到脚本文件所在文件夹时没有写的权限。可直接对文件夹执行sudo chmod -R 777 文件夹路径即可。

四、lldb手动dump

准备

1、在手机中配置好debugserver
2、通过以下命令导出需要dump应用的可执行文件到当前路径。xxxx代表应用进程路径。

1
scp -P 12345 root@localhost:xxxx ./

3、查看瘦身后的可执行文件的加密信息。并记录。

1
2
3
4
●  otool -l Aweme_arm64 | grep cry
cryptoff 16384
cryptsize 52527104
cryptid 1

分析:
cryptoff:指加密文件的头所对应的偏移。这个数字之前代表着可执行文件的header。
cryptsize: 加密的数据长度,我们需要把这段时间拷贝出来。

实操

1、开启debugserver服务,依附到我们想要dump应用的进程中。

1
debugserver *:9393 -a Aweme

2、电脑进入lldb调试环境,连接到对应的debugserver端口。

1
process connect [connect://localhost:9393](connect://localhost:9393)

3、通过image list指令拿到可执行文件的头地址,加上之前的cryptoff得到需要拷贝数据的起始地址。

4、按字节读取内存中的可执行文件,并拷贝到电脑。(耗时动作)

1
2
3
4
5
//--force:按字节读取。
//0x00000001000c4000+16384:需要拷贝内容的起始地址。
//52527104:需要拷贝内容的大小。
//./decrypted.bin : 在当前目录下生成一个名为decrypted.bin的二进制包。
memory read --force --outfile ./decrypted.bin --binary --count 52527104 0x00000001000c4000+16384

5、将二进制文件包替换之前拷贝出来的可执行文件中的对应部分,得到一个新的可执行文件。

1
2
3
4
//dd:用指定大小的文件写到另一个文件当中。
//bs:一个一个字节写入
//conv:指定转换文件的方式。
dd seek=16384 bs=1 conv=notrunc if=./decrypted.bin of=./Aweme_arm64

6、通过otool -l查看新的可执行文件,得知cryptid仍为1,这里是因为我们并没有对header文件作修改,所以字段的值仍保持之前加密的键值。但是可执行文件的内容却被我们解密了的。可以通过class-dump验证。

7、通过Mach0View 修改cryptid的值为0。如果不修改class-dump会不成功。因为这个工具首先会拿到header获取cryptid的值,如果是已加密的话就会放弃后面的dump工作了。

8、通过class-dump -H Aweme_arm64 -o ./AwemeHeaders能导出应用的头文件,便可证明lldb手动脱壳成功。

补充

frida_tools的一些使用

1、配置端口映射。
通过frida-ps列出当前应用进程。
通过usb连接好手机后,通过frida-ps -U列出usb设备的应用进程。

2、通过frida -U 微信附加进程到微信。

3、执行ObjC可拿到附加进程应用的所有Object-C对象。

插入自定义动态库到指定应用

通过这样的操作,进程没有被污染,在以后的每次执行时候不会执行我们所插入的动态库的方法。这里只相当于一次性插入。上文的dumpdecrypted便是用到了这样的原理。

1、使用Xcode生成framework文件。通过以下命令拷贝到越狱设备中。

1
scp -r -P 12345 DyInsert.framework/ root@localhost:~/

2、通过以下命令将动态库插入到指定进程即可。

1
DYLD_INSERT_LIBRARIES=DyInsert.framework/DyInsert    /var/mobile/Containers/Bundle/Application/4560ADA4-9AE4-4E9D-BE84-ABF666B12A7A/WeChat.app/WeChat