软件脱壳,顾名思义,就是对软件加壳的逆操作,把软件上存在的壳去掉(解密)。

砸壳原理

应用加壳(加密)

提交给AppStore发布的App,都经过官方保护而加密,这样可以保证机器上跑的应用是苹果审核过的,也可以管理软件授权

经过AppStore加密的应用,我们无法通过Hopper等反编译静态分析,也无法Class-Dump

在逆向分析过程中,需要对加密的二进制文件进行解密,然后才能进行静态分析,这一过程就是大家熟知的砸壳(脱壳)

应用砸壳(解密)

  • 静态砸壳:在已经掌握和了解到了壳应用的加密算法和逻辑后,在不运行壳应用程序的前提下,将壳应用程序进行解密处理。静态脱壳的方法难度大,而且加密方发现应用被破解后,就可能会改用更加高级和复杂的加密技术
  • 动态砸壳:从运行在进程内存空间中的可执行程序映像(image)入手,将内存中的内容进行转储(dump)处理来实现脱壳处理。这种方法实现起来相对简单,且不必关心使用的是何种加密技术

iOS应用运行原理
iOS逆向实战--029:应用砸壳 - 图1

iOS系统中,应用砸壳所使用的都是动态砸壳技术

Clutch

Clutch是由KJCracks开发的一款开源砸壳工具。工具支持iPhoneiPod TouchiPad,该工具需要使用iOS8.0以上的越狱手机应用。

Clutch属于命令行工具,适用于完美越狱的设备。如果是非完美越狱,砸壳时可能会出现问题

Clutch安装

官网地址:https://github.com/KJCracks/Clutch

直接找到Release版本
iOS逆向实战--029:应用砸壳 - 图2

下载最新的Clutch-2.0.4
iOS逆向实战--029:应用砸壳 - 图3

使用file命令,查看Clutch工具

  1. file Clutch-2.0.4
  2. -------------------------
  3. 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]
  4. Clutch-2.0.4 (for architecture armv7): Mach-O executable arm_v7
  5. Clutch-2.0.4 (for architecture armv7s): Mach-O executable arm_v7s
  6. Clutch-2.0.4 (for architecture arm64): Mach-O 64-bit executable arm64

Clutch是通用二进制文件,可以支持不同CPU架构的设备

Clutch使用

Clutch-2.0.4拷贝到手机的/var/root目录下,并且重命名为Clutch

  1. scp -P 12345 ./Clutch-2.0.4 root@127.0.0.1:/var/root/Clutch
  2. -------------------------
  3. Clutch-2.0.4 100% 1204KB 28.2MB/s 00:00
  • 使用-P参数,指定USB连接的映射端口,传输速度更快
  • 前面是本地文件路径
  • 后面是手机路径,IP地址要和登录时设置的一致
  • 拷贝的同时,可以修改名称
  • 如果拷贝的是文件夹,增加-r参数

Clutch增加可执行权限

  1. chmod +x Clutch

查看Clutch的用法

  1. ./Clutch
  2. -------------------------
  3. Usage: Clutch [OPTIONS]
  4. -b --binary-dump <value> Only dump binary files from specified bundleID
  5. -d --dump <value> Dump specified bundleID into .ipa file
  6. -i --print-installed Print installed applications
  7. --clean Clean /var/tmp/clutch directory
  8. --version Display version and exit
  9. -? --help Display this help and exit
  10. -n --no-color Print with colors disabled
  • -b:仅从指定的bundleID转储二进制文件
  • -d:将指定的绑定文件转储到.ipa文件中
  • -i:打印安装的应用程序

查看安装的应用程序

  1. ./Clutch -i
  2. -------------------------
  3. 1: 老司机汽车 <com.driver.feng>
  4. 2: 爱思加强版 <com.pd.A4Player>
  5. 3: 微信 <com.tencent.xin>
  • 这里列出的软件,都可以进行砸壳

选择对WeChat进行砸壳

  1. ./Clutch -d 3
  2. -------------------------
  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.
  4. Zipping WeChat.app
  5. ASLR slide: 0x1000b0000
  6. Dumping <WeChatNotificationServiceExtension> (arm64)
  7. Patched cryptid (64bit segment)
  8. Writing new checksum
  9. ...
  10. DONE: /private/var/mobile/Documents/Dumped/com.tencent.xin-iOS9.0-(Clutch-2.0.4).ipa
  11. Finished dumping com.tencent.xin in 44.8 seconds
  • Clutch同样使用动态砸壳,所以理论上,砸壳前应该启动WeChat。实际上并不需要,当Clutch发现目标App未启动,会自动将其启动
  • 砸壳成功,给出.ipa包的路径

将砸壳后的.ipa包,导出到Mac电脑。解压出MachO文件,查看加密状态

  1. otool -l WeChat | grep crypt
  2. -------------------------
  3. cryptoff 16384
  4. cryptsize 107446272
  5. cryptid 0
  • cryptid0,处于未加密状态,证明WeChat砸壳成功
dumpdecrypted

Github开源工具。dumpdecrypted这个工具就是通过建立一个名为dumpdecrypted.dylib的动态库,插入目标应用实现脱壳。

dumpdecryptedClutch一样,都是砸壳领域的经典插件。它们同样岁月沧桑,适用于完美越狱的设备。如果是非完美越狱,砸壳时可能会出现问题

越狱环境的代码注入,可以使用不污染三方应用的插件完成。插件只会影响当前进程,无需修改MachO文件,从而使三方应用防护难度增大

dyld的源码中,有一个DYLD_INSERT_LIBRARIES环境变量,用于插入动态库并执行

越狱环境,将自定义动态库插入WeCath进程

创建Inject动态库,添加InjectCode

打开InjectCode.m文件,写入以下代码:

```

import “InjectCode.h”

@implementation InjectCode

+(void)load { NSLog(@”\n\n\n\n\n🍺🍺🍺🍺🍺\n\n\n\n\n”); }

@end

  1. > 编译项目,生成`Inject.framework`<br />
  2. ![](https://upload-images.jianshu.io/upload_images/9297953-b170231d6a4063cc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  3. > `Inject.framework`拷贝到手机的`/var/root`目录下
  4. >

scp -r -P 12345 ./Inject.framework root@127.0.0.1:/var/root

CodeResources 100% 2402 917.0KB/s 00:00 Inject 100% 85KB 6.4MB/s 00:00 Inject.h 100% 424 214.9KB/s 00:00 module.modulemap 100% 93 47.5KB/s 00:00 Info.plist 100% 744 588.3KB/s 00:00

  1. > - `Inject.framework`是文件夹,所以需要加上`-r`参数,让其循环拷贝
  2. > `USB`连接手机
  3. >

usb-5s.sh

  1. > 查看`WeCath`进程
  2. >

ps -A | grep WeChat

5380 ?? 0:03.70 /var/mobile/Containers/Bundle/Application/B1661526-3E43-4397-9E86-A9735DE89AE1/WeChat.app/WeChat 5388 ttys000 0:00.01 grep WeChat

  1. > 使用`DYLD_INSERT_LIBRARIES`,将`Inject.framework`插入到`WeCath`进程
  2. >

DYLD_INSERT_LIBRARIES=Inject.framework/Inject /var/mobile/Containers/Bundle/Application/B1661526-3E43-4397-9E86-A9735DE89AE1/WeChat.app/WeChat

  1. > ![](https://upload-images.jianshu.io/upload_images/9297953-3981efbbbc9b1849.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  2. > 注入的代码在`WeChat`进程中执行成功
  3. > `iOS 9.1`以上系统的兼容问题
  4. > 上述案例,使用`iOS 9.1`系统进行演示
  5. > `iOS 9.1`以上系统,使用`DYLD_INSERT_LIBRARIES`插入动态库,会提示以下错误:
  6. >

Killed:9

  1. > - 问题产生:在`9.1`以上系统,不允许`root`用户插入动态库
  2. > - 解决办法:需要切换成`mobile`用户,才可执行成功
  3. > `dumpdecrypted`安装
  4. > 官网地址:[https://github.com/stefanesser/dumpdecrypted](https://github.com/stefanesser/dumpdecrypted)
  5. > 克隆`dumpdecrypted`
  6. >

git clone https://github.com/stefanesser/dumpdecrypted.git

  1. > 进入`dumpdecrypted`目录,执行`make`命令
  2. >

make

  1. > 编译生成动态库:`dumpdecrypted.dylib`<br />
  2. ![](https://upload-images.jianshu.io/upload_images/9297953-cf4cfc6067d98be9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  3. > `dumpdecrypted`使用
  4. > `dumpdecrypted.dylib`拷贝到手机的`/var/root`目录下
  5. >

scp -P 12345 ./dumpdecrypted.dylib root@127.0.0.1:/var/root

dumpdecrypted.dylib 100% 209KB 13.3MB/s 00:00

  1. > 使用`DYLD_INSERT_LIBRARIES`,将`dumpdecrypted.dylib`插入到`WeCath`进程
  2. >

DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/B1661526-3E43-4397-9E86-A9735DE89AE1/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/mobile/Containers/Bundle/Application/B1661526-3E43-4397-9E86-A9735DE89AE1/WeChat.app/WeChat. One of the two will be used. Which one is undefined. mach-o decryption dumper … [+] Closing original file [+] Closing dump file

  1. > 在当前目录下,导出`WeChat.decrypted`文件,是砸壳后的`MachO`文件
  2. > `WeChat.decrypted`文件,导出到`Mac`电脑
  3. >

otool -l WeChat.decrypted | grep crypt

WeChat.decrypted: cryptoff 16384 cryptsize 107446272 cryptid 0

  1. > `cryptid``0`,处于未加密状态,证明导出的`WeChat.decrypted`砸壳成功
  2. > 使用`dumpdecrypted`工具,要求`Xcode SDK`与越狱设备`iOS SDK`版本一致
  3. > 例如:对`iOS 9.1`的设备插入`dumpdecrypted.dylib`,就要使用老版本的`Xcode``dumpdecrypted`进行`make`
  4. > 否则在插入`dumpdecrypted.dylib`时,会出现以下错误
  5. >

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

  1. #####frida-ios-dump
  2. 该工具基于`frida`提供的强大功能,通过注入`js`实现内存`dump`,然后通过`python`自动拷贝到电脑生成`ipa`文件。
  3. > `frida-ios-dump`支持众多版本的系统,非完美越狱的环境也可使用,是目前最常用、最稳定的砸壳工具
  4. > `pip`安装
  5. > `pip`的安装和`python`版本有关,`python`安装使用`pip`,而`python3`安装使用`pip3`
  6. > 查看`python`版本
  7. >

python —version

Python 2.7.16

  1. > 查看`python3`版本
  2. >

python3 —version

Python 3.8.2

  1. > 查看`pip`版本
  2. >

pip -V

  1. > 查看`pip3`版本
  2. >

pip3 -V

  1. > 使用`easy_install`命令,安装`pip`
  2. >

sudo easy_install pip

  1. > 使用`easy_install`的方式,我没有安装成功。`pip``pip3`都尝试过,安装后一直提示版本问题,无法使用
  2. > 这里介绍另一种方式,使用`get-pip`
  3. > 克隆`get-pip`
  4. >

git clone https://github.com/pypa/get-pip.git

  1. > 来到`public`目录下<br />
  2. ![](https://upload-images.jianshu.io/upload_images/9297953-c800719e9a0cb4c4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  3. > 使用`python3`执行`get-pip.py`脚本,安装`pip3`
  4. >

python3 get-pip.py

  1. > `frida`安装
  2. > `iOS`设备,安装`frida`
  3. > 打开`Cydia`,添加源:[https://build.frida.re](https://build.frida.re)
  4. > 安装`Frida`<br />
  5. ![](https://upload-images.jianshu.io/upload_images/9297953-0b5bea4639180762.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  6. > `Mac`电脑,安装`frida`
  7. >

sudo pip3 install frida-tools

  1. > 可能会出现警告:`you may want sudo's -H flag`<br />
  2. ![](https://upload-images.jianshu.io/upload_images/9297953-c33d0bcbbbc20512.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  3. > - 目录不归当前用户所有。请检查该目录的权限和所有者,需要`sudo``-H`标志
  4. > `sudo -H``set-home``HOME`变量设为目标用户的主目录
  5. >

sudo -H pip3 install frida-tools

  1. > 出现`Uninstalling a distutils installed project (six)`提示,执行以下命令:
  2. >

sudo pip3 install frida —upgrade —ignore-installed six

  1. > `frida`使用
  2. > 查看`Mac`电脑的进程
  3. >

frida-ps

PID Name 17799 360压缩大师 5668 AccessibilityVisualsAgent 602 AirPlayUIAgent 381 AppSSOAgent 13006 Code …

  1. > `USB`连接设备,查看手机上的进程
  2. >

frida-ps -U

PID Name 5574 Cydia 5480 iTunes 5569 老司机汽车 6318 邮件 …

  1. > 进入`WeChat`进程
  2. >

frida -U 微信

  1. > ![](https://upload-images.jianshu.io/upload_images/9297953-d0af45afb646d302.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  2. > 输出`WeChat`内存中的对象
  3. >

[iPhone::微信]-> ObjC

  1. "_SFPBSearchSuggestion": {
  2. "handle": "0x1db5319f8"
  3. },
  4. "_SFPBSectionHeaderCardSection": {
  5. "handle": "0x1db49d2b8"
  6. },

  1. > `frida`更多语法,可查看:[官方文档](https://frida.re/)
  2. > `frida`擅长将`js``python`脚本,注入到目标程序并执行,它并不适合作为动态分析的工具使用
  3. > `frida-ios-dump`就是将`dump.py`,通过`frida`注入目标程序,从而实现应用砸壳
  4. > `Mac`电脑,配置`frida-ios-dump`
  5. > 官网地址:[https://github.com/AloneMonkey/frida-ios-dump](https://github.com/AloneMonkey/frida-ios-dump)
  6. > 克隆`frida-ios-dump`
  7. >

sudo git clone https://github.com/AloneMonkey/frida-ios-dump

  1. > 进入`frida-ios-dump`目录<br />
  2. ![](https://upload-images.jianshu.io/upload_images/9297953-881f912ff47a6883.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  3. > 安装依赖
  4. >

sudo pip3 install -r requirements.txt —upgrade

  1. > 安装过程中,可能出现的错误
  2. > `prompt-toolkit`版本不兼容问题
  3. >

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.

  1. > 解决方法,需要降低`prompt-toolkit`版本
  2. > 卸载`prompt-toolkit`
  3. >

sudo pip uninstall prompt-toolkit

  1. > 安装指定版本
  2. >

sudo pip install prompt-toolkit==1.0.6

  1. > 如果出现`-H`警告,同样使用`sudo -H`解决
  2. >

sudo -H pip3 install -r requirements.txt —upgrade

  1. > `frida-ios-dump`使用
  2. > 进入`frida-ios-dump`目录,执行`dump.py`脚本
  3. >

./dump.py 微信

Traceback (most recent call last): File “./dump.py”, line 11, in import frida ImportError: No module named frida

  1. > 遇到上述问题,先检查`frida-ios-dump`目录的读写权限
  2. > 右键`frida-ios-dump`目录,选择“显示简介”,添加“本用户”的读写权限,并选择“应用到包含的项目...”<br />
  3. ![](https://upload-images.jianshu.io/upload_images/9297953-fe51cb00fbc0d3c2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  4. > 打开`dump.py`文件,需要将`python`修改为`python3`<br />
  5. ![](https://upload-images.jianshu.io/upload_images/9297953-ffd24d43b48be699.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  6. > 执行`dump.py`脚本
  7. >

./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

  1. > 还是执行失败了,因为在`dump`的时候,会将`ipa`包导出到`Mac`电脑,此时需要`USB`连接设备。所以在`dump`之前,应该先执行`usbConnect.sh`脚本
  2. > 检查`dump.py`文件中的`User``Password``Host``Port`,是否和`usbConnect.sh`脚本中的配置一致
  3. > 修改`Port`,将`2222`修改为`12345`<br />
  4. ![](https://upload-images.jianshu.io/upload_images/9297953-6c6c2299a1afa79f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  5. > 执行`dump.py`脚本
  6. >

./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”

  1. > 执行成功,在`frida-ios-dump`目录下,成功导出`微信.ipa`<br />
  2. ![](https://upload-images.jianshu.io/upload_images/9297953-86083881313fe338.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240#alt=)
  3. > 可以将其配置为环境变量,方便使用
  4. #####iOS终端支持中文
  5. > `iOS`终端默认是不支持中文的
  6. > 创建`.inputrc`隐藏文件,写入以下代码:
  7. >

set convert-meta off set output-meta on set meta-flag on set input-meta on

  1. > `.inputrc`文件,拷贝到手机的`/var/root`目录下
  2. >

scp -P 12345 .inputrc root@localhost:/var/root

.inputrc 100% 75 8.2KB/s 00:00 ```

iOS终端,输入中文
iOS逆向实战--029:应用砸壳 - 图4

总结

砸壳原理

  • 应用加壳:一般应用为了防止反编译分享,会对应用进行加密(加壳)
  • 应用砸壳:砸壳(脱壳)就是解密的过程
    ◦ 静态砸壳:已经知道了解密方式,不需要运行应用的情况下,直接解密
    ◦ 动态砸壳:在应用启动后,从内存中找到应用的位置,dump(内存中导出)数据

Clutch

  • 是一个命令行工具
  • Clutch -i:查看安装的应用程序
  • Clutch -d 应用编号:导出ipa

dumpdecrypted

  • 是一个动态库,不能独立运行
  • 通过DYLD_INSERT_LIBRARIES环境变量,插入动态库。载入某个进程
  • DYLD_INSERT_LIBRARIES = 库路径(库的可执行文件) MachO路径
  • 9.1以上系统,不允许root用户使用DYLD_INSERT_LIBRARIER方式插入动态库,需要切换成mobile用户

frida-ios-dump

  • 利用frida加载脚本砸壳
  • 安装fridaMaciPhone都需要安装
  • 下载frida-ios-dump脚本工具
  • 执行dump.py,参数是应用名称或BundleID

iOS终端支持中文

  • 创建.inputrc隐藏文件,写入代码
  • 拷贝到手机的/var/root目录下