1. 为什么要逆向工程
iOS 逆向工程主要有两个作用:
1,分析目标程序,拿到关键信息,可以归类于安全相关的逆向工程;
2,借鉴他人的程序功能来开发自己的软件,即开发相关的逆向工程。
其中,安全相关的iOS逆向工程主要有如下几个场景:
- 评定安全等级
- 逆向恶意软件
- 检查软件后门
- 去除软件使用限制
而开发相关的iOS逆向工程有如下两个场景:
1、逆向系统API
可逆向系统API后,扩展iOS系统的功能,众所周知,能在 AppStore 上架的 App 的功能十分有限,在苹果公司严格的审核制度下,绝大多数 App 的实现都源于公开的开发文 ,而不能使用例如发短信、打电话等文档中不涉及的功能。
2、借鉴别人的软件
比如通过逆向那些软件,可以从 App 中把它们的设计思路抽象出来为我所用,从而提高自己 App 的精致程度。
2. iOS应用逆向工具
1,监测工具Reveal:能够辅助定位 App 中我们感兴趣的部分,让我们能够迅速从 UI 层面切入代码层面。
2,反汇编工具:IDA和Hopper
3,调试工具:LLDB调试器
4,Theos 和iOSOpenDev
3. iOS系统相关知识
3.1 iOS 系统结构
1,对于未越狱的 iOS设备,苹果官方开放给第三方直接访问 iOS文件系统的接口非常有限。
2,越狱后能够访问 iOS 全系统文件,这是开展 iOS 逆向工程的首要前提。
3.2 iOS 目录结构简介
/:根目录,以斜杠表示,其他所有文件和目录在根目录下展开。
/bin:“binary”的简写,存放提供用户级基础功能的二进制文件,如 ls、ps 等。
/boot:存放能使系统成功启动的所有文件。iOS 中此目录为空。
/dev:“device”的简写,存放BSD设备文件。每个文件代表系统的一个块设备或字符设备,一般来说,“ 设备”以块为单位传 数据,如硬盘;而“字符设备”以字符为单位传输数据,如调制解调器。
/sbin :“ system binaries”的简写,存放提供系统级基础功能的二进制文件,如 netstat、reboot 等。
/etc :“Et Cetera”的简写,存放系统脚本及配置文件,如 passwd、hosts 等。在 iOS中,/etc 是一个符号链接,实际指向 /private/etc。
/lib:存放系统库文件、内核模块及设备驱动等。iOS 中此目录为空。
/mnt:“mount”的简写,存放临时的文件系统挂载点。iOS 中此目录为空。
/tmp:临时目录。在 iOS 中,/tmp 是一个符号链接,实际指向 /private/var/tmp。
/usr:包含了大多数用户工具和程序。/usr/bin包含那些/bin和/sbin中未出现的基础功能,如 nm、killall 等;/usr/include 包含所有的标准C 头文件;
/usr/lib 存放系统库文件。
/var :“ variable”的简写,存放一些经常更改的文件,比如日志、用户数据、临时文件等。
/var/mobile和 /var/root 分别存放了 mobile 用户和 root 用户的文件,是重点关注的目录。
3.3 iOS 的独有目录
/Applications:存放所有的系统App和来自于Cydia的App,不包括 StoreApp。
/Developer:如果一台设备连接Xcode后被指定为调试要的工具和数据,
/Library:存放一些提供系统支持的数据,其中/Library/MobileSubstrate 下存放了所有基于 CydiaSubstrate(原名 MobileSubstrate)的插件。
/System/Library :iOS 文件系统中最重要的目录之一,存放大量系统组件,其目录结构
/System/Library/Frameworks和/System/Library/PrivateFrameworks:存放iOS中的各种 framework,其中出现在 SDK 文档里的只是冰山一角,还有数不清的未公开功能等待我们去挖 。
/System/Library/CoreServices里的SpringBoard.app:iOS 面管理器(类似于Windows里的explorer),是用户与系统交流的最重要中介。
/User:用户目录,实际指向/var/mobile,这个目录里存放大量用户数据,比如:
~/var/mobile/Media/DCIM下存放照片;
~/var/mobile/Media/Recordings下存放录音文件;
~/var/mobile/Library/SMS下存放短信数据 ;
~/var/mobile/Library/Mail下存放邮件数据。
4. iOS 二进制文件类型
在iOS逆向工程初学阶段,我们的目标主要是Application、Dynamic Library(以下 dylib)和 Daemon 这三类二进制文件。
4.1 Application相关概念
bundle:是一个按某种标准结构来组织的目录,其中包含了二进制文件及运行所需的资源。正向开发中常见的 App 和 framework都是以bundle的形式存在的;在越狱iOS中常见的PreferenceBundle,可以看成是一种依附于Settings 的 App。Settings 的 App,结构与 App 类似,本质也是 bundle。
Framework 也是 bundle,但 framework 的 bundle 中存放的是一个 dylib,而不是可执行文件。相对来说,framework的地位比 App 更高,因为一个 App 的绝大多数功能都是通过调用 framework 提供的接口来实现的。将某个 bundle 确立为逆向目标后,绝大多数逆向线索都可以在 bundle 内找到,这大大 低了逆向工程的复杂度。
App 目录 :
Info.plist 文件记录了App的基本信息,如bundle identifier、可执行文件名、图标文件名等。
可以通过 Xcode 自带的命 行工具 plutil 查看bundle identifier的值,如下:
plutil -p /Users/snakeninny/Code/iOSSystemBinaries/8.1_iPhone5/SiriViewService.app/Info.plist | grep CFBundleIdentifier
安装包格式与权限:
Cydia App 的安装包格式一般是 deb,StoreApp 的安装包格式一般是 ipa。其中 deb 是来自 Debian 的安装包格式,由 Cydia 作者 saurik 移 到 iOS 中,它的 主用户和 主组一般是 root 和 admin,能够以 root权限运行;而 ipa 是苹果为 iOS 推出的专用App安装包格式, 主用户和 主组都是 mobile,只能以 mobile权限运行。
Dynamic Library:
1,在 Xcode 工程里导入的各种 framework,链接的各种 lib,其实本质都是 dylib。
2,Cydia 里的各种 tweak 无一不是以 dylib 的形式工作的,正是这些 tweak 的存在让我们能够随意定制自己的 iOS。
3,在iOS中,lib分为static和dynamic两种,其中static lib在编译阶段成为App可执行文件的一部分,会增加可执行文件的大小。
4,dylib 则相对“智能”一些,它不会改变可执行文件的大小,只有当 App 需要用到这个 dylib 时,iOS 才会把它加载进内存,成为 App 进程的一部分。
5,dylib 的权限是由它寄生的那个 App 决定的,同一个 dylib 寄生在系统 App 和 StoreApp 里时的权限是不同的。
5. 手动hook一个自己编写的APP
5.1 使用Xcode创建自己的一个用于测试的App。
目的:拦截一个自己写的方法,然后进行重写。APP大家可以自己创建,我这边已经创建好了。
Bundle identifier:ZZ.ForDemo
APP Name : ForDemo
拦截一个按钮的点击方法:
- (void)buttonClick {
UIAlertController *alerView = [UIAlertController alertControllerWithTitle:@"提示"
message:@"未被HOOK"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction =[UIAlertAction actionWithTitle:@"取消"
style:UIAlertActionStyleCancel
handler:nil];
[alerView addAction:cancelAction];
[self presentViewController:alerView animated:YES completion:nil];
}
5.2 下载和配置theos
大家可自己手动下载官方theos然后放入ldid、CydiaSubstrate、dpkg-deb等等到目录中,或者使用脚本下载网上一位大神已经封装好的theos。脚本下载地址:https://github.com/DaSens/Theos-Script
5.3 创建theos项目
1,首先我们配置和准备好theos后,我们进入终端,然后cd进入你要放工程的文件夹目录比如桌面上我新建好的一个文件夹iosDev,然后执行启动 NIC(New Instance Creator),如下:
然后我们进入工程目录会发现生成四个文件:
这四个文件的配置如下:
Makefile
THEOS_DEVICE_IP = 10.10.243.124
ARCHS = armv7 arm64
TARGET = iphone:latest:8.0
include $(THEOS)/makefiles/common.mk
TWEAK_NAME = ForDemo
ForDemo_FILES = Tweak.xm
ForDemo_FRAMEWORKS = UIKit
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
install.exec "killall -9 SpringBoard"
Tweak.xm
%hook ViewController
- (void)buttonClick
{
UIAlertController *alerView = [UIAlertController alertControllerWithTitle:@"提示"
message:@"已经被HOOK了"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction =[UIAlertAction actionWithTitle:@"取消"
style:UIAlertActionStyleCancel
handler:nil];
[alerView addAction:cancelAction];
[self presentViewController:alerView animated:YES completion:nil];
}
%end
其它两个文件 control 和 ForDemo.plist 可以保持原样
5.3 打包并安装dylib到设备中
OK,走到这一步,必须保证iOS设备一定要已经安装了Open ssh。
按照所查到资料,除了Open ssh的安装外,还需满足一下两个条件:
- 设备和电脑保持在同一局域网下。
- 保证你的theos配置文件没有问题。
然后可以把自己写的APP运行到设备上,运行之后点击测试下未HOOK之前的按钮点击方法:
接下来我们利用终端cd进入你创建的tweak项目目录,然后执行make package install,然后输入两次ssh的连接密码(ssh 默认密码alpine),然后设备就会重启SpringBoard,然后我们再次打开HOOK的APP发现按钮的点击方法已经被替换了。
如果提示_Prefix/NullabilityCompat.h 说明你是自己clone 的官方的theos,里面没放入这些头文件,可手动clone header头文件到目录中:
sudo git clone https://github.com/theos/headers /opt/theos/include
这个时候输入成功后这个时候SpringBoard已经开始重启了,这时候再点击hook按钮应该就能hook成功了。
奈何,手中的5s是10.2.1的系统暂时无法越狱,后续亲测hook成功与否,尽请期待~