iOS逆向与安全:基础篇
iOS逆向与安全:基础篇
镇长前言
从本篇文章开始,笔者会整理iOS逆向相关的笔记。作为一位新人,希望通过整理笔记能够更好的理解和掌握知识。能力有限,在行文时难免出现错误欢迎批评和指正。
前期准备:
- 一台越狱的iOS设备,笔者使用iPad mini2系统iOS9.2.1(推荐使用iOS9.1或者可以完美越狱的系统)
- 一台电脑,笔者使用的是MacBook Pro
- 一条数据线
如何越狱
网上有很多教程帮助你来越狱,这里推荐两个网站:
注意:在购买iOS设备时直接购买对应版本的系统,由于苹果官方关闭降级通道所以无法刷固件降级。
越狱成功后,桌面上会出现一个叫做Cydia
的应用,它是越狱后的App Store
可以安装各种第三方的软件,比如:插件、补丁、APP等。该应用的作者Jay Freeman(saurik)
,一位骨灰级大神。
必装插件或补丁
Apple File Conduit 2
:可以访问整个iOS设备的文件系统。作者是Jay Freeman
。AppSync unified
: 可以绕过系统验证,随意安装、运行破解的IPA安装包。PP助手
: 一个应用商店,可以自由安装海量APP。OpenSSH
: 用于远程登录iOS设备。
Mac 必备
iFunBox
: 管理文件系统。PP助手
:一个应用商店。iTerm2
: 一款优秀的命令行工具Alfred
: 便捷搜索,自定义工作流,调高效率的工具
配置远程登录
SSH:Secure Shell的缩写,安全外壳协议,是一种可以为远程登录提供安全保障的协议。使用SSH可以把所有传输的数据进行加密,防止中间人攻击、DNS欺骗和IP欺骗。
OpenSSH: 是SSH协议的免费开源实现。通过它让Mac登录iOS设备,在Cycript
中搜索安装。
使用密码登录
如果iOS设备上已经安装了OpenSSH
,此时就可以通过Mac终端登录iOS设备。前提,iOS设备和Mac需要处于相同WiFi环境下。在设置中查看iOS设备的IP地址。打开终端输入:
1 | ssh root@iOS设备IP地址 |
iOS设备上有两个默认账号:root,mobile。
- root:最高权限账户,$HOME是
/var/root
。或者通过终端输入pwd
查看。 - mobile:普通权限账户,只能操作一些普通文件,$HOME是
/var/mobile
。 mobile
登录方式:ssh mobile@服务器地址
。初始密码alpine
。- 修改root密码:
passwd
,修改mobile
用户密码:passwd mobile
。
公钥登录
上面的密码登录方式比较麻烦,在每次登录时都需要输入密码。SSH提供了公钥登录,以省去密码的步骤。下面来看看公钥登录流程:
将电脑端的SSH公钥保存在iOS设备中,登录时iOS设备端会向电脑端发送一个随机字符串,登录用户通过自己的私钥加密后发送给iOS端,iOS端通过事先存储好的公钥解密,如果解密成功,证明用户是可信的。
查看$HOME/.ssh/
目录,是否有id_rsa
私钥和id_rsa.pub
公钥,如果没有使用ssh-keygen
生成。
上传公钥到远程设备,通过ssh-copy-id
命令。
1 | ssh-copy-id -i $HOME/.ssh/id_rsa.pub root@地址 |
该条命令的作用是将id_rsa.pub
公钥追加到iOS设备的$HOME/.ssh/authorized_keys
文件中。
1 | cat $HOME/.ssh/authorized_keys //查看文件内容 |
通过USB登录设备
在WiFi不稳定的情况下,通过WiFi登录会非常的卡顿。可以通过接口转发的方法,使用USB SSH登录,保证连接的稳定性。
方法很简单,首先安装libimobiledevice
,然后使用里面提供iproxy
把本地端口(例如:2222)映射到设备的TCP端口22,就可以通过本地的2222端口建立连接了。
1 | brew install libimobiledevice |
如果,每次输入iproxy 2222 22
进行接口转换比较麻烦,可以将其配置到电脑的开机启动项中。创建~/Library/LaunchAgents/com.usbmux.iproxy.plist
,填入一下:
运行命令launchctl load ~/Library/LaunchAgents/com.usbmux.iproxy.plist
使之生效。
每次输入ssh root@localhost -p 2222
也很麻烦,可以通过指定一个名称进行SSH连接,打开$HOME/.ssh/config
文件,没有创建一个,写入一下内容。
1 | Host ipad |
通过以上配置,在终端输入ssh ipad
即可登录iOS设备了。
砸壳
在App Store
下载应用都会进行加密,破解加密称为砸壳。本节记录在学习砸壳中遇到的问题和解决方法。
三种砸壳方案:
这三种方案网上很多教程,下面整理的是第三种方案简单高效。
配置环境
iOS设备和电脑都需安装Frida
,
iOS设备安装Frida
,打开Cydia
添加软件源 https://build.frida.re
,之后搜索Frida
安装。电脑端通过pip
命令sudo pip install frida
安装。
接下来,克隆**frida-ios-dump**库到本地。仓库有两个分支分别对应python2.x
和python3.x
,需要根据本地Python
版本来判断。
1 | // Mac终端 |
由于笔者配置的Python 3.x
,切换到3.x分支安装firda-ios-dump
依赖。在frida-ios-dump
仓库目录下运行下面命令。
1 | sudo pip install -r requirements.txt --upgrade |
安装结束后,将越狱设备通过USB连上电脑进行端口映射:
1 | iproxy 2222 22 |
到此配置结束,如果一切顺利就可以进行砸壳了。
进行砸壳
在frida-ios-dump
目录下,使用命令./dump.py -l
查看应用名称和Bundle ID
,通过命令./dump.py + 程序名字 or BundleID
即可砸壳。当程序执行完,在当前目录中会出现一个xxx.ipa
。
不过,通往成功的道路永远不是一帆风顺的,在运行./dump.py
命令是出现了错误Waiting for USB device…。在这个issue
中给出了解决方案。
推荐文章一条命令完成砸壳
Reveal配置
Reveal是一款用于查看程序界面结构和调试界面的工具,可以在开发中动态修改调试代码修改程序的样式,也可以注入到第三方APP查看应用的界面结构。
本节将会学习如何在越狱设备和非越狱设备上查看应用的结构。
越狱设备集成Reveal
笔者在越狱设备集成Reveal遇到了一个问题,新版的RevealServer
是Framework
而旧版的是dylib
,两者集成方式不同,但是网上很多资料都是过时的,所以这里给出新版的集成方式。
首先在Cydia
下载Reveal2Loader
插件。插件安装后进入设置找到Reveal-->Enabled Applications
选择要查看的App。例如:简书
电脑端安装Reveal
软件,正常情况下,打开手机上的简书APP会在Reveal
中看到下图,点击进入即可查看界面结构。
有时会出现RevealServer.framework
版本问题,电脑端点击Help->Show Reveal Library in Finder
将Framework
拷贝到手机Library/Frameworks
目录下替换原来的。
非越狱设备集成Reveal
如果在开发中集成Reveal
直接使用CocoaPods
即可,在Podfile
文件加入以下内容:
1 | //只在Debug模式下开启 |
之后运行pod install
即可集成。
如果想在非越狱设备查看其它App的界面结构,需要使用**MonkeyDev**工具辅助完成。
首先安装MonkeyDev,安装在GitHub仓库有文档。
非越狱设备集成Reveal
还需要目标App的脱壳ipa
包。具体步骤查看文章:
Cycript配置
Cycript是允许开发者使用Objective-C++
和Javascript
组合语法查看及修改运行时APP内存信息的工具。
在越狱设备上安装
Cycript
是saurik
提供的工具,在Cydia
中搜索Cycript
并安装即可。
安装完成后,用SSH登录设备输入cycript
命令,就可以进入交互界面。
在越狱设备上,可以使用一些命令注入目标进程,调试目标函数。下面例子:脚本注入到SpringBoard(桌面)中,使其弹出一个提示框。
1 | iPad:~ root# cycript -p SpringBoard |
这是《iOS应用逆向与安全》中给出的一个简单的例子。
Cycript
分析应用
上面例子中使用了一条命令cycript -p SpringBoard
,通过该命令可以调试指定APP。该命令有两种使用方式,除了上面的cycript -p 程序名称
,还可以通过cycript -p 程序进程ID
。注意这里的程序的名称并不是APP的名称。
查看程序的名称和进程ID可以通过安装一个插件adv-cmds
。通过它使用ps
命令查看当前运行程序的进程ID及可执行文件的路径。
安装完成后,通过ps -A
命令查看当前设备的进程ID和可执行文件的路径。同时,支持关键词搜索ps -A | grep 关键词
。
例如,查看简书的路径和进程ID
由于程序的进程ID是会发生变换的推荐使用名称。
下面就以简书为例,学习如何使用cycript
的使用。
查看应用信息
1 | cy# NSHomeDirectory() // 沙盒路径 |
查看APP
的Application
信息,例如:查看简书的Application
对象,为自定义的HGApplication
。
1 | cy# UIApp |
查看rootViewController
。
1 | cy# UIApp.keyWindow .rootViewController |
还可以使用地址查看信息。例如:查看HGTabBarController
的view
。
1 | cy# #0x155006200.view |
另外Cycript提供了choose()
函数选择某个类的实例数组。例如:学习简书中所有的Button类的所有实例数组。
1 | cy# choose(UIButton) |
以上是cycript
的基本用法。
cycript
高级用法
每次要输入那么多的代码是在有点麻烦,能不能将常用的代码封装起来呢?答案是肯定的。
Cycript本身是支持加载自己的脚本的,可以通过@import
命令加载。例如:加载mjscript脚本。
1 | cy# @import mjcript |
关于如何将自己学的脚本添加到手机上查看【越狱-逆向】基于Cycript实现的一些实用函数文档,对如何添加,如何使用写的比较详细,这里就不再重复赘述。
Class-dump
本节学习如何使用工具导出第三方App的头文件,学习前需要补充点基础知识。
Mach-O文件
想让程序在设备上运行起来,需要将写好的代码生成可执行文件这样才能被操作系统所理解。比如,在Linux
下可执行文件的格式是ELF
,在Window
中可执行文件是PE32/PE32+
,而在MAC
和iOS
中是Mach-O
格式。
Mach-O的组成结构如下图:
可以看的出 Mach-O 主要由 3 部分组成:
- Mach-O 头(Mach Header):这里描述了 Mach-O 的 CPU 架构、文件类型以及加载命令等信息;
- 加载命令(Load Command):描述了文件中数据的具体组织结构,不同的数据类型使用不同的加载命令表示;
- 数据区(Data):Data 中每一个段(Segment)的数据都保存在此,段的概念和 ELF 文件中段的概念类似,都拥有一个或多个 Section ,用来存放数据和代码。
如何获取Mach-O文件,在App Store
中下载应用.ipa
改成.zip
格式,之后解压缩会在里面发现一个应用同名的文件。
下面是简书的Mach-O文件:
Class-dump使用
class-dump的作用就是把Mach-O
文件的class信息导出来生成头文件。
下载后将其中的class-dump
拷贝到/usr/local/bin
目录下,就可以在终端使用class-dump
命令。
终端输入class-dump
:
1 | class-dump 3.5 (64 bit) (Debug version compiled Sep 17 2017 16:24:48) |
安装成功,可以解析头文件方法很简单,常用指令。
class-dump -H mach-o路径 -o 头文件存储路径
以简书App为例,使用之前砸壳的ipa
文件,找到里面的Mach-O
文件。
1 | class-dump -H Hugo -o ./Header |
在当前目录中会生成Header文件夹,里面包含所有的头文件。
参考文章
- Mach-O 文件格式探索
- 趣探 Mach-O:文件格式分析
- 《iOS应用逆向与安全》作者:刘培庆