iOS逆向实战--029:应用砸壳

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

砸壳原理

应用加壳(加密)

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

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

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

应用砸壳(解密)

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

iOS应用运行原理

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

Clutch

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

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

Clutch安装

官网地址:https://github.com/KJCracks/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架构的设备

Clutch使用

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

scp -P 12345 ./Clutch-2.0.4 [email protected]:/var/root/Clutch
-------------------------
Clutch-2.0.4                                  100% 1204KB  28.2MB/s   00:00
  • 使用-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包的路径

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

otool -l WeChat | grep crypt
-------------------------
    cryptoff 16384
   cryptsize 107446272
     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

编译项目,生成Inject.framework

Inject.framework拷贝到手机的/var/root目录下

scp -r -P 12345 ./Inject.framework [email protected]:/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
  • Inject.framework是文件夹,所以需要加上-r参数,让其循环拷贝

USB连接手机

usb-5s.sh

查看WeCath进程

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

使用DYLD_INSERT_LIBRARIES,将Inject.framework插入到WeCath进程

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

注入的代码在WeChat进程中执行成功

iOS 9.1以上系统的兼容问题

上述案例,使用iOS 9.1系统进行演示

iOS 9.1以上系统,使用DYLD_INSERT_LIBRARIES插入动态库,会提示以下错误:

Killed:9
  • 问题产生:在9.1以上系统,不允许root用户插入动态库
  • 解决办法:需要切换成mobile用户,才可执行成功

dumpdecrypted安装

官网地址:https://github.com/stefanesser/dumpdecrypted

克隆dumpdecrypted

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

进入dumpdecrypted目录,执行make命令

make

编译生成动态库:dumpdecrypted.dylib

dumpdecrypted使用

dumpdecrypted.dylib拷贝到手机的/var/root目录下

scp -P 12345 ./dumpdecrypted.dylib [email protected]:/var/root
-------------------------
dumpdecrypted.dylib                                                                              100%  209KB  13.3MB/s   00:00

使用DYLD_INSERT_LIBRARIES,将dumpdecrypted.dylib插入到WeCath进程

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

在当前目录下,导出WeChat.decrypted文件,是砸壳后的MachO文件

WeChat.decrypted文件,导出到Mac电脑

otool -l WeChat.decrypted | grep crypt
-------------------------
WeChat.decrypted:
    cryptoff 16384
   cryptsize 107446272
     cryptid 0

cryptid0,处于未加密状态,证明导出的WeChat.decrypted砸壳成功

使用dumpdecrypted工具,要求Xcode SDK与越狱设备iOS SDK版本一致

例如:对iOS 9.1的设备插入dumpdecrypted.dylib,就要使用老版本的Xcodedumpdecrypted进行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提供的强大功能,通过注入js实现内存dump,然后通过python自动拷贝到电脑生成ipa文件。

frida-ios-dump支持众多版本的系统,非完美越狱的环境也可使用,是目前最常用、最稳定的砸壳工具

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的方式,我没有安装成功。pippip3都尝试过,安装后一直提示版本问题,无法使用

这里介绍另一种方式,使用get-pip

克隆get-pip

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

来到public目录下

使用python3执行get-pip.py脚本,安装pip3

python3 get-pip.py

frida安装

iOS设备,安装frida

打开Cydia,添加源:https://build.frida.re

安装Frida

Mac电脑,安装frida

sudo pip3 install frida-tools

可能会出现警告:you may want sudo's -H flag

  • 目录不归当前用户所有。请检查该目录的权限和所有者,需要sudo-H标志

sudo -Hset-homeHOME变量设为目标用户的主目录

sudo -H pip3 install frida-tools

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

sudo pip3 install frida --upgrade --ignore-installed six

frida使用

查看Mac电脑的进程

frida-ps
-------------------------
 PID  Name
17799  360压缩大师
5668  AccessibilityVisualsAgent
 602  AirPlayUIAgent
 381  AppSSOAgent
13006  Code
...

USB连接设备,查看手机上的进程

frida-ps -U
-------------------------
PID  Name
5574  Cydia
5480  iTunes
5569  老司机汽车
6318  邮件
...

进入WeChat进程

frida -U 微信

输出WeChat内存中的对象

[iPhone::微信]-> ObjC
-------------------------
       "_SFPBSearchSuggestion": {
           "handle": "0x1db5319f8"
       },
       "_SFPBSectionHeaderCardSection": {
           "handle": "0x1db49d2b8"
       },
...

frida更多语法,可查看:官方文档

frida擅长将jspython脚本,注入到目标程序并执行,它并不适合作为动态分析的工具使用

frida-ios-dump就是将dump.py,通过frida注入目标程序,从而实现应用砸壳

Mac电脑,配置frida-ios-dump

官网地址:https://github.com/AloneMonkey/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

安装过程中,可能出现的错误

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

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目录的读写权限

右键frida-ios-dump目录,选择“显示简介”,添加“本用户”的读写权限,并选择“应用到包含的项目...”

打开dump.py文件,需要将python修改为python3

执行dump.py脚本

./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文件中的UserPasswordHostPort,是否和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
-------------------------
.inputrc                                      100%   75     8.2KB/s   00:00

iOS终端,输入中文

总结

砸壳原理

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

你可能感兴趣的:(iOS逆向实战--029:应用砸壳)