二、应用脱壳

前言

iOS端App在上线之前会由苹果商店进行FairPlayDRM数字版权加密保护(简称“加壳”)。要对应用进行分析,就必须先解密(成为“脱壳”),从而得到原始未加密的二进制文件。本节将讨论各种各样的脱壳技术。

一、检测是否脱壳

如何检测应用是否加壳了呢?我们采用两种常规的方式检测

1.1 使用otool检测

otool可以看到二进制文件的信息里面有一个cryptid字段,cryptid=1表示已加壳,cryptid=0表示未加壳。在终端使用命令行查看,具体如下:

$ otool -l xxtx| grep crypt
     cryptoff 16384
    cryptsize 41582592
      cryptid 0

1.2 使用MachOView检测

如果不想输入命令行,则可以使用MachOView来查看,将目标文件拖入MachOView,展开Load Commands节点,选择LC_ENCRYPTION_INFO_64选项,右边可以看到Crypt ID

二、Clutch

Clutch是一款全自动脱壳工具,其原理是把应用运行时的内存数据按照一定格式导出,并重新打包成ipa文件。

2.1 安装Clutch

官网直接下载最新版,复制到iOS设备的/usr/bin/目录,然后添加执行权限,操作如下:

# mac执行
scp -p 2222 -r ./Clutch root@localhost:/usr/bin

# iOS执行
$ chmod +x /usr/bin/Clutch

在iOS设备上输入Clutch命令,如果输出了帮助信息则表示安装配置成功,具体如下:

$ 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

2.2 Clutch脱壳实战

使用-i参数打印从App Store安装的所有应用列表:

$ Clutch -i
Installed apps:
1:  WhatsApp Messenger <net.whatsapp.WhatsApp>
...

这里用序号为1WhatsApp Messenger进行脱壳演示:

$ Clutch -d net.whatsapp.WhatsApp
Zipping WhatsApp.app
ASLR slids:0x100010000
Dumping <WhatsApp> (arm64)
Patched cryptid (64bit segment)
Writing new checksum
...
DONE:/private/var/mobile/Documents/Dumped/net.whatsapp.WhatsApp-iOS7.0-(Clutch-2.0.4).ipa
Finished dumping net.whatsapp.WhatsApp in 32.9 seconds

上述信息提示脱壳完成,重新打包后的文件为/private/var/mobile/Documents/Dumped/net.whatsapp.WhatsApp-iOS7.0-(Clutch-2.0.4).ipa
值得一提的是,最终脱壳出的文件架构和使用的iOS设备有关,如笔者的设备脱壳出来的是ARM64架构,如果放到ARMv7架构的设备上是不能正常运行的。如果需要多架构可用,则需要再准备一台ARMv7架构的设备进行脱壳,然后用lipo命令将两个架构进行合并。

三、dumpdecrypted

上面提到的Clutch使用过程是“傻瓜式”的,但是很多应用使用它脱壳会失败,这里介绍另外一款脱壳工具dumpdecrypted,它在使用上比Clutch会稍微麻烦一些,但是非常灵活,效果也不错。

3.1 编译dumpdecrypted

dumpdecrypted是开源的,需要先编译、签名,再将其复制到iOS设备中,从官网可下载最新源代码。

  • 编译dumpdecrypted

    读者们自行找相关文章进行编译吧。

  • dumpdecrypted.dylib签名

    下面提供两种签名方式,读者自行选择

    • 使用ldid签名

      # 跳转到dumpdecrypted的路径下
      $ ldid -S dumpdecrypted.dylib
      
    • 使用codesign签名

      # 跳转到dumpdecrypted的路径下
      $ codesign -f -s - ./dumpdecrypted.dylib
      ./dumpdecrypted.dylib: replacing existing signature
      
  • 复制dumpdecrypted.dylib到设备

    scp命令将dumpdecrypted.dylib复制到iOS设备的/usr/bin目录:

    $ scp -p2222 ./dumpdecrypted.dylib root@localhost:/usr/bin
    

到此为止,准备工作就完成了。

3.2 dumpdecrypted脱壳实战

为了操作方便,笔者选择先进入tmp目录(如果脱壳失败,请进入沙盒的Documents再进行),脱壳后的文件就会保存与此。接口用ps命令查看目标文件的完整路径,最后使用DYLD_INSERT_LIBRARIES环境变量将dumpdecrypted.dylib注入就可以脱壳了。操作如下:

$ cd /tmp
$ ps -ax | grep WhatsApp
1108 ??  0:00.99 /var/contaniners/Bundle/Applications/8A9F2580-5919-1ACF11CD8/WhatsApp.app/WhatsApp
$ DYLD_INSERT_LIBRARIES=/usr/lib/dumpdecrypted.dylib /var/contaniners/Bundle/Applications/8A9F2580-5919-1ACF11CD8/WhatsApp.app/WhatsApp
mach-o decryption dumper

...
...
[+] Closing original file
[+] Closing dump file

$ ls -al
-rw-r--r-- 1 root wheel 23927 May 12 20:26 WhatsApp.descryped

WhatsApp.descryped为脱壳后的文件,使用scp命令或者pp助手导出到mac上即可。

四、bfinject

如果当前的设备系统是iOS11及以上版本,那么Clutchdumpdecrypted不进行改造的,目前都无法正常使用,这时候可以选择bfinject工具包,它集成了脱壳工具及Cycript等。

4.1 安装bfinject

github上有两个版本的bfinject官网中是原始版本,只能支持iOS11iOS11.1.2,[官网](https://github.com/MJavad/bfinject)中是修改版本,已经完成支持iOS11iOS11.4.1。

  • 将修改版clone到mac上

    $ git clone https://github.com/MJavad/bfinject
    
  • 连接iOS设备并在根目录创建bfinject文件夹

    $ ssh -p 2222 root@localhost
    $ cd /
    $ mkdir bfinject
    
  • 另外开启一个终端,将bfinject.tar上传到iOS设备

    $ cd bfinject
    $ ls | grep *.tar
    bfinject.tar
    $ scp -p2222 ./bfinject.tar root@localhost:/bfinject
    
  • 进入iOS设备的/bfinject目录并解压

    $ cd /bfinject
    $ tar xvf bfinject.tar
    

至此,bfinject就已经安装好了。

4.2 bfinject脱壳实战

依然使用WhatsApp来做实验,先确保目标App已经运行,并进入bfinject目录,终端进入iOS设备使用如下命令进行脱壳。

$ ./bfinject -P WhatsApp -L decrypt
[+] Electra detected.
[+] Injecting into '/var/containers/Bundle/Application/8A9F2580-5919-1ACF11CD8/WhatsApp.app/WhatsApp'
...
[bfinject4realz] Success! Library was loaded at 0x1c43e0000
[+] So long and thanks for all the fish.

如果顺利完成,界面会弹出Decryption Complete对话框。脱壳完成的文件存放在应用沙盒的Documents目录下,名为decrypted-app.ipa,如果打开了控制台就能更加快捷地从日志进行定位,使用scp命令将decrypted-app.ipa复制到mac,利用PP助手或者Xcode安装decrypted-app.ipa,如果能正常运行则到此结束,否则看下面。

4.3 修复闪退

如果脱壳后的ipa包安装后运行闪退,则需要稍微处理一下,具体如下:

  • 解压ipa包

    # 跳转到电脑上decrypted-app所在目录
    $ unzip decrypted-app.ipa
    
  • 导出ent.xml

    $ codesign -d --entitlements - ./Payload/WhatsApp.app > ent.xml
    
  • 使用codesign重签名

    $ codesign -s - --entitlements ent.xml -f ./Payload/WhatsApp.app/WhatsApp
    
  • 压缩成新的ipa

    $ zip -r WhatsApp_ok.ipa Payload
    

重新安装处理后的WhatsApp_ok.ipa即可解决闪退问题。至此,bfinject的脱壳过程全部完成。

五、CrackerXI(iOS11~iOS13)

CrackerXI是脱壳工具的后起之秀,专为iOS11~iOS13量身打造,是目前为止最为傻瓜式的脱壳工具。
CrackerXI的安装比较简单,直接在Cydia中添加源(网址为:http://cydia.iphonecake.com/),然后搜索安装即可。
安装完成后,会在桌面出现CrackerXI图标,打开后会呈现已安装的App列表。在脱壳之前,进入Settings页面进行一些必要的设置,将CrackerXI HookRemove UISupportedDevicesSet Minimum iOS version 10.0Remove Watch App都打开。如果安装后没有出现相应图标,则进入终端执行uicache-a即可。
现在进入“AppList”页面,单击需要脱壳的App,在随后弹出的对话框中单击YES,Full IPA按钮,即会自动进行脱壳并重新打包成ipa文件,完成后会弹出一个成功的提示框。
至此,脱壳就很简单的完成了。

六、Frida-ios-dump

Frida-ios-dump基于Frida(一个跨平台的轻量级Hook框架)提供的强大功能,通过注入JS实现内存dump,然后利用Python自动复制到mac生成最终的ipa文件

6.1 一键快速脱壳

Frida-ios-dump的原理和dumpdecrypted一样,都是通过把内存中已解密的数据dump再修复Mach-O,但是dumpdecrypted仅能dump主程序,对于框架需要自行修改源代码才能完成,而且操作上比较麻烦。而Frida提供的强大功能,使得Frida-ios-dump只需一键即可快速完成脱壳。
首先从github下载Frida-ios-dump,并查看帮助:

$ git clone https://github.com/AloneMonkey/frida-ios-dump
$ cd frida-ios-dump
$ ./dump.py -h
usage: dump.py [-h] [-l] [-o OUTPUT_IPA] [-target]

frida-ios-dump (by AloneMonkey v2.0)

positional arguments:
target      Bundle identifier or display name of the target app

optional arguments:
-h, --help      show this help message and exit
-l, --list      List the insstalled apps
-o OUTPUT_IPA, --output OUTPUT_IPA  Specify name of the decrypted IPA

Frida-ios-dump支持直接填写应用名或者Bundle ID进行脱壳,参数-o指定ipa文件输出路径,参数-l显示所有已安装的应用。
以微信脱壳为例,命令如下:

$ ./dump.py 微信 -o ./Wechat_Decrypted.ipa

6.2 完美修复闪退

笔者发现由当前Frida-ios-dump版本脱壳后的Wechat_Decrypted.ipa仅能在iOS8上运行,其他系统上会出现Service exited due to signal:Killed 9错误(闪退)。
使用dumpdecrtyptedbfinject脱壳后同样会发生闪退情况,之前都是用codesign重签处理,既然重签能够运行,就说明闪退是由于签名校验失败后导致的,下面将从根源上解决这个问题。

Clutch脱壳的程序是能正常运行的,对其源代码研究后发现它进行了hash(散列,由叫“哈希”)值的修正处理。在学习Mach-O文件格式时讲过,LC_CODE_SIGNATURE加载命令存放的是一些与签名有关的数据,而里面最重要的是CSSLOT_CODEDIRECTORYCSSLOG_ALTERNATE_CODEDIRECTORIES,它们包含了代码段的SHA-1SHA-256校验信息。Clutch源码里面有一个步骤修正了SHA-1hash值,所以在iOS9上运行没有问题,但是iOS11校验了SHA-256hash值,而该值又没有修正,所以仍然会闪退。
所以我们需要根据校验原理编写一个mac端工具,它能自动修正签名段的hash值,然后修改dump.py文件,让脚本在生成ipa文件之前先调用我们编写的工具。

6.3 ipa文件安装失败处理

如果将脱壳后的ipa文件安装到不同类型的设备,有可能会出现DeviceNotSupported错误。这是因为设备支持列表中没有目标设备的类型。将ipa文件解压,找到Info.plist文件,在UISupportedDevices项添加自己的设备类型(或者直接删除UISupportedDevices项)。将处理后的Info.plist文件重新打包放入ipa文件再安装即可。

七、使用lipo分离架构

前文已经说过了,最终脱壳出的文件架构和使用的iOS设备有关。Mach-O是胖文件格式,可能存在多种架构,那些没被脱壳的架构已经没有存在的意义,将其剔除还可以节省不少空间。mac自带的lipo工具就是负责这项工作的。

lipo的功能非常强大,不但能合并多个Mach-O文件到一个胖文件格式,也能从一个胖文件格式中分离指定架构的Mach-O文件,下面的例子使用lipo工具的-info参数查看目标文件的架构,然后使用-thin参数分离ARMv7ARM64架构:

$ lipo -info WeChat
Architectures in the fat file:WeChat are: arm7  arm64

$ lipo WeChat -thin armv7 -output WeChat_armv7
$ lipo WeChat -thin arm64 -output WeChat_arm64

另外,如果想在64位设备上运行32位程序,只需要提取ARMv7架构即可,因为在iOS11系统之前,指令集都是向下兼容的,但是到了iOS11及以后的系统,就只保留了ARM64架构。

posted @ 2022-05-12 01:21  Scott_Mr  阅读(582)  评论(0编辑  收藏  举报