iOS越狱开发指南

1. 前言

若干年前,大家看到iPhone互相问好的第一件事是“你越狱了吗”。据不完全统计,早期有80%左右的iPhone用户会选择越狱。但是随着iOS系统的逐步完善,这个比例已经在慢慢降低,甚至很多人已经不知道越狱为何物,是美剧吗?那么作为iOS开发者,有没必要了解越狱,越狱完之后我们能干嘛?答案显然是肯定的,那么这篇文章将带你进入越狱的世界里。

2. 什么是越狱

越狱(jailbreaking)在汉语词典里面的指的是监狱中的囚犯非法地离开或逃离监狱的行为。众说周知,iOS是相对比较封闭的操作系统,用户和开发者所拥有的权限(自由)只能局限在特定的沙盒之中。那么iOS 越狱则指的是通过系统漏洞,打破这种限制的过程。使得用户最终能够以root权限访问文件系统和管理器,随心所欲的驾驭我们自己的iOS设备。


3. 越狱的意义

3.1. 用户

大概可以分为这么几个方面:

3.1.1. 任意安装第三方应用,包括免费和收费的,不需要繁琐的注册和输入Apple ID

第三方应用市场:91助手,百度助手,PP助手,360助手等

3.1.2 . 扩展定制系统应用和服务

比如快捷设置,来电归属地,一键清理,更换界面主题,动态壁纸,苹果公司近几年的iOS系统更新所添加的新功能有很多都是从越狱插件中借鉴的;
代表:91桌面,SBSettings


91桌面

SBSettings

3.1.3. 解除运营商限制

可以非正式地解开运营商对iPhone的锁定,使得能够使用其它运营商提供的服务,比如一些定制机或者其他地区版本限制了移动4G服务

3.1.4. 修复漏洞

可在苹果漏洞未修复前,提前进行修复

3.2. 开发者

以上总结的是越狱之后的对于用户来说大致几个方面的意义,但是随着苹果对iOS的逐步完善和免费App(下载免费)成为趋势,不可否认的是越狱的人群正逐步减少,作为iOS开发者还有哪些更重要的意义呢?
主要包括以下几个方面:

3.2.1. 了解整个iOS系统和架构,能够站在更高的维度看问题

包括iOS整体框架,比如私有API,能够更好的扩展App功能,也意味着苹果未来可能开放这部分接口,更早的掌握核心技术;
常用的私有API特性:
a. 实现更丰富的UI效果,比如CAAnimation未公开的API
b. 打开受限制的硬件特性,比如iOS7上实现视频硬解码
c. 获取已安装App列表以及App信息
d. 获取特殊的设备信息,比如IMEI,UDID等
e. 应用内安装卸载IPA软件包


私有库列表

3.2.2. 学习优秀的设计和实现方法

作为开发者,总是惊叹于很多优秀的App能够做的如此之好,tableview可以如丝般顺滑;那么在赞叹之余,我们能够动起手来了解这些App的设计思想,算法,以及实现方式,弄清楚程序运行的本来面目。


3.2.3. 提高开发效率

a. 远程调试,远离找数据线烦恼;
b. app,bundle,framwork等可动态替换和加载,不需要重复安装加载;
c. 文件目录自由访问,动态修改替换配置文件,特别是iOS8.4之后限制了App的文件目录读取,显得尤为重要;
iOS系统目录:

Applications            // 存放所有系统的App和Cydia安装的App
Library                 // 存放提供系统支持的数据,其中系统插件一般存放在/Library/MobileSubstrate
System                  // 系统组件目录,如SpringBoard桌面管理器,Fonts字体等
User -> /var/mobile     // 用户目录,如用户安装的程序相册照片等都在这里
Developer               // Xcode调试设备自动生成的目录
 
bin                     // "binary"的缩写,存放用户级基础功能的二进制文件,如cp,ls等
dev                     // "device"的缩写,存放BSD设备文件
sbin                    // "system binary"的缩写,存放系统级基础功能的二进制文件,如fsck,reboot等
usr                     // 包含了大多数用户的工具和程序
private                 // 主要链接的目标目录
etc -> private/etc/     // "Et Cetera"的缩写,存放系统脚步及配置文件
tmp -> private/var/tmp/ // 临时文件存放目录
var -> private/var/     // 存放经常变化的文件,如日志文件
 
boot                    // 存放系统启动文件,iOS此目录为空
cores                   // 内核转储文件存放目录,iOS此目录为空
lib                     // 存放系统库文件,内核模块及设备驱动等,iOS此目录为空
mnt                     // "mount"的缩写,存放临时的文件挂载点,iOS此目录为空

d. 更好的进行性能测试和监控
一个top命令就可以了解整体的一个运行情况, 一个简单的ping即可调试当前设备的网络情况。还有更高级的用法,我们平时开发中经常使用Instruments监测我们的应用程序,但是功能往往比较局限,这时候通过越狱插件的形式能够更好的监测我们应用程序的整体运行情况;



3.2.4. 了解越狱技术之后,更好的保障自身安全

a. 核心代码保护,反逆向,进行代码混淆
b. 保证信息安全,本地数据加密,内存数据保护
c. 防劫持,防注入,阻止GDB等动态调试工具依附

// 未混淆的被逆向的登录接口
- (void)login:(id)arg1 password:(id)arg2;
// 混淆后的登录接口
- (void)lSjsBDmteIagjEhG:(id)arg1 chnIVERjpXdqYbbp:(id)arg2;

综上所述,作为开发者,虽然面对的用户(利益)可能越来越少,学习和应用越狱知识依然意义重大,使得技术更加纯粹;

4. 越狱开发的软硬件环境

桌面操作系统: Mac OS X
iOS设备: iPhone,iPod touch,iPad
设备越狱:
(1). 确定对应设备系统版本是否能够完美越狱,寻找对应的越狱工具
目前完美越狱的iOS系统版本:
iOS 1.0 ~ iOS 10.2.1(个别小版本不支持,比如iOS 9.3.5)
(2). 使用iTunes进行数据备份,越狱有风险,一定要谨慎,记得备份,备份,备份
(3). 各个越狱工具,步骤可能略有不同,随着越狱技术的成熟,目前基本上支持一键越狱
Cydia:
越狱环境下的App Store,一般越狱工具会自动安装

5. 实现流程以及通用技术

5.1. 砸壳,脱去App保护的外衣

5.1.1 自给自足

从App Store官方途径下载的ipa包是经过加壳的,也就是做了一层加密处理。所以我们第一步就需要通过一定的技术手段剥开这层保护壳,才能深入内部去探寻我们感兴趣的东西。
相关技术:
a. AppCrackr: 早期使用的工具,简便好用,但是目前已被和谐
b. dump decrypted: 流程稍微复杂一些,需要在iOS设备上进行
详细教程:http://wiki.sankuai.com/pages/viewpage.action?pageId=500734074

5.1.2 嗟来之食

最方便快捷的途径是去第三方的应用分发平台,比如91,PP助手等直接下载相应的ipa包,但是一些国外或者冷门的App在上述平台可能没有,那就必须自己动手了。

5.2. 静态分析

5.2.1. 查看可执行文件(Mach-O)

什么是Mach-O?它是一种用于可执行文件,目标代码,动态库,内核转储的文件格式,目前Mac OS X,iOS的可执行文件都是采用的这种文件格式。所以,无论基于何种目的,我们的入口基本都是从这里入手
可视化查看工具:
MachOView,免费开源的项目,能够可视化查看Mach-O的文件信息
dmg:http://sourceforge.net/projects/machoview/
GitHub:https://github.com/gdbinit/MachOView

5.2.2. 解析可执行程序(Mach-O)的头文件信息

逆向解析出目标程序所有的头文件信息,把盘子铺开
原理:
在Mach-O结构中主要通过以下几个Section段,“__objc_classname” Section段保存有Objective-C所有的类名信息,“__objc_methname”的Section段则保存了所有的方法列表,而"__objc_classlist"的Section段则具有所有类的信息,包括类名,变量,函数等关联信息。所以通过以上几点,从而能够针对App,bundle,framwork,static library等的可执行程序导出所有Objective-C的头文件信息;
Class-dump
class dump是一个命令行工具,它可以dump出破解之后的iOS二进制文件的头文件信息
教程:http://wiki.sankuai.com/display/~zhangzifeng02/Class-dump
官网:http://stevenygard.com/

5.2.3. 反汇编可执行程序(Mach-O)

对于逆向出的各个头文件信息,可能有几百上千个文件,就像一幅图上众多的点,你很难有效的组织起来,从而能够看穿一切。这就需要更加深入的分析,利用反汇编反编译的手段,将点连成线,深入了解目标程序的整体逻辑关系
原理:
反汇编(Disassembly),是把目标代码转换为更加便于易读的汇编代码的过程,对于任何的计算机程序都可以实施反汇编,并且对于有些强大的反汇编工具,甚至能够转换为高级语言的代码;
反汇编反编译工具:
IDA
逆向工程界的神器,功能强大,支持Windows,Mac OS X和Linux等平台。正式版需要收费,价格不菲,有免费试用版本,但是功能受限,对于初学者来说其实功能也够用,但是不支持64位的CPU,对于目前iOS设备普遍都是64位的CPU来说有点尴尬;
官网:https://www.hex-rays.com/products/ida/index.shtml


Hopper Disassembler
后起之秀,主要针对Mac OS X平台,能够逆向32位和64位可执行程序,功能也相当强大。有免费和收费版本,对比于IDA收费版本价格更加亲民,个人版本700左右人民币即可收入囊中。
官网:https://www.hopperapp.com/

5.3. 动态调试

对目标程序进行静态分析之后,我们能够窥探程序的整个逻辑结构。正如我们了解了一个工具的基本构造之后,它是如何使用的呢?所以我们还必须通过动态调试的手段探测程序的运行时情况。
动态调试指的是利用调试器在软件运行时,动态的调试跟踪软件的运行情况。作为iOS开发人员,我们应该都会用Xcode的在Debug模式下调试我们的程序,那么对于已发布的Release程序,我们能否进行动态调试呢,答案是肯定的。

5.3.1. 远程连接

OpenSSH是使用SSH协议进行远程登录的首选连接工具, 可以安全方便的远程调试iOS设备。首次越狱后需要单独安装,也可进入Cydia搜索"openssh"进行在线安装。安装成功之后,默认密码为"alpine",为了避免安全隐患,记得及时修改root和mobile账户的默认密码。

// 修改密码
passwd root
// 连接iOS设备
ssh root@192.168.x.xxx(mobile账户 ssh mobile@192.168.x.xxx)
// 退出连接
exit(或者热键Ctrl+D)

官网:http://www.openssh.com/

11.gif

5.3.2 动态代码调试

a. GDB
GDB是GNU开源组织发布的,功能强大的命令行调试器,支持C, C++, Objective-C, Pascal等多种流行的程序语言。
支持的功能:
♦ 启动程序,指定可影响程序运行的任何内容
♦ 可以让程序在指定的断点条件下停止
♦ 在程序停止时(断点处),检查程序运行的情况
♦ 可以动态修改程序运行时的内容
GDB的基本调试步骤:

ps –ax                    // 输出所有进程的信息,找到输出信息中目标进程的pid
gdb –p pid                // 从上面的输出信息得到进程pid,启动相应进程
info sh                   // 查看目标的基地址,记为base
// GDB常用调试技巧
break *(0X00ABCD+base)    // 一般通过IDA来静态查找想断点的地址,比如0X00ABCD加上基地址即为需要断点的地址
display                   // 设置程序中断后欲显示的数据及其格式
p                         // 打印指定变量的值
ni                        // 执行一行源程序代码,此行代码中的函数调用也一并执行
si                        // 执行一行源程序代码,如果此行代码中有函数调用,则进入该函数
bt                        // 显示堆栈信息
c                         // Continuing,继续运行
q                         // Quit的简写,退出GDB调试环境。

官网:https://www.gnu.org/software/gdb/

b. LLDB
从Xcode5开始LLDB取代了GDB成为了Xcode新的默认调试器,它是具有REPL(read-eval-print-loop,交互式解释器)特征的开源调试器,其可以安装C++或者Python插件。它与LLVM编译器一起,带给我们更丰富的流程控制和数据检测的调试功能。所以随着官方GDB被取代的趋势,在iOS动态调试使用LLDB也就比用GDB来得更加靠谱。
LLDB的基本调试步骤:
(1). LLDB只能运行在Mac上,在iOS上调试需要安装debugserver,从而能够进行远程调试,首先需要装载Mac上的DeveloperDiskImage,注意要选择对应设备系统版本下的DeveloperDiskImage

hdiutil attach /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/8.4/DeveloperDiskImage.dmg

(2). 拷贝debugserver到本地目录

cp /Volumes/DeveloperDiskImage/usr/bin/debugserver ~/Desktop/debugserver/debugserver
cd ~/Desktop/debugserver/debugserver

(3). 对debugserver进行瘦身,只取对应的设备的架构包(这边我的是iPhone5S对应的是arm64)

lipo -thin arm64 debugserver -output ~/Desktop/debugserver/debugserver

(4). 创建一个名为entitlements.plist的文件,并且输入相应的签名文件内容,保存到当前目录

vim
// 文本内容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.springboard.debugapplications</key>
    <true/>
    <key>run-unsigned-code</key>
    <true/>
    <key>get-task-allow</key>
    <true/>
    <key>task_for_pid-allow</key>
    <true/>
</dict>
</plist>
// 保存
wq entitlements.plist

(5). 对debugserver进行签名

codesign -s - --entitlements entitlements.plist -f debugserver

(5). 将debugserver远程拷贝到对应设备的usr/bin/目录,注意@后面为局域网内设备的IP地址

scp debugserver root@192.168.1.xxx:/usr/bin/debugserver

(6). SSH连接iOS端开启监听端口,注意后面跟的是进程名字,比如"Elephant"

debugserver *:8888 -a "Elephant"

(7). Mac端远程连接iOS,进行远程调试

// 打开LLDB
lldb
platform select remote-ios
process connect connect://192.168.1.xxx:8888
// 查看ASLR偏移地址
image list -o -f
// 打印对象
po [[UIApplication sharedApplication] delegate]

注意:由于各种网络原因,有可能会导致连接会比较久,不知道还以为程序死了,其实等等还是会有的,这时可考虑采用USB连接方式
a. 下载usbmuxd,地址为https://cgit.sukimashita.com/usbmuxd.git/snapshot/usbmuxd-1.0.8.tar.gz
b. 解压到相应目录,终端进入usbmuxd-1.0.8/python-client/目录
c. 开启端口转发,python tcprelay.py -t 8888:8888

(8). 连接成功之后,即可在iOS上对应的App进行LLDB动态调试,其调试技巧与GDB有些差别,但是基本上大同小异
LLDB与GDB命令的对照表:http://lldb.llvm.org/lldb-gdb.html
官网:http://lldb.llvm.org/

c. Cycript
这是由越狱大神saurik开发的一门脚本语言,能够允许开发者对Objective-C++ 和 JavaScript混合使用,实现探测和修改运行中的应用程序,主要用于注入目标进程或者链接库中进行动态调试,它的好处是对原生程序或者代码完全无副作用

// 注入进程
cycript -p SpringBoard
// 正常进入cycript后即可进行相应的操作,比如创建一个UIAlertView
alertView = [[UIAlertView alloc] initWithTitle:@"test" message:@"hello cycript" delegate:nil cancelButtonTitle:@"OK" otherButonTitles:nil]
#"<UIAlertView: 0x1379b40d0; frame = (0 0; 0 0); layer = <CALayer: 0x174a3e120>>"
[alertView show]
或者直接访问指针地址[#0x1379b40d0 show]
// 查找某个类对象的内存地址
choose(SBIconModel)
[#"<SBIconModel: 0x1702ae5e0>"]

官网:http://www.cycript.org/

(3) UI动态调试工具
Reveal
Reveal是iOS上强大动态UI调试工具,能够实现注入,修改,调试iOS应用程序。需要收费,第一次下载有14天的免费期限
普通集成方式:
a. CocoaPods 集成
b. 断点加载
c. 项目依赖
越狱集成方式:
a. 将Reveal目录下的Reveal.framework和libReveal.dylib拷贝到设备上的相应目录;

scp -r /Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/Reveal.framework root@192.168.1.xxx:/System/Library/Frameworks 
scp /Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/libReveal.dylib root@192.168.1.xxx:/Library/MobileSubstrate/DynamicLibraries

b. 在设备的/Library/MobileSubstrate/DynamicLibraries/目录下创建libReveal.plist,并且编辑匹配的目标程序的BundleID,内容如下;

{  
    Filter = { 
         Bundles = ("com.apple.AppStore");
         Bundles = ("com.tencent.xin");  
    };  
}

c. 保证Mac端和设备处在同一局域网内,这时Mac打开Revea,并且在iOS设备上打开目标程序,即可进行UI动态调试;
官网:https://revealapp.com/

5.4. 工程构建

MacPorts和dpkg
MacPorts一个软件包管理系统,可用于简化OS X和Darwin操作系统内软件的安装。而dpkg则是Debian软件包管理器的基础,是一个底层工具,主要用于安装,卸载和管理deb软件包,dpkg通过MacPorts来安装
https://www.macports.org/
Theos
Theos最初是一个“iphone-framework”,以简化在iOS设备(主要是越狱设备)上命令行的代码构建。后面演变为基于make的构建系统,可运行在OSX,iOS,Linux和Windows上,主要用于iOS越狱软件的开发。
(1). 安装ldid,在Theos开发中,ldid替代Xcode自带的Codesign对插件进行签名;

sudo brew install ldid

(2). 安装Theos,一般是安装在/opt/目录下

sudo git clone --recursive https://github.com/theos/theos.git /opt/theos

(3). 创建工程

export THEOS=/opt/theos
$THEOS/bin/nic.pl
// 选择工程模版
  [1.] iphone/application
  [2.] iphone/library
  [3.] iphone/preference_bundle
  [4.] iphone/tool
  [5.] iphone/tweak
Choose a Template (required):

(4). 工程代码编写,以tweak为例子

control    // 用于存储deb包管理的基本信息,包括包名,工程名,版本,作者信息等
Makefile   // 工程配置文件,用来指定工程用到的文件、框架、库、使用的SDK等
projectName.plist // 配置需要hook的Bundle ID
Tweak.xm   // 程序的入口,一般进行进程,类,函数等的hook和其他操作
// 基础语法
%hook ClassName
// Hooking a class method
+ (id)sharedInstance {
    return %orig;
}
 
// Hooking an instance method with an argument.
- (void)messageName:(int)argument {
    %log; // Write a message about this call, including its class, name and arguments, to the system log.
 
    %orig; // Call through to the original function with its original arguments.
    %orig(nil); // Call through to the original function with a custom argument.
 
    // If you use %orig(), you MUST supply all arguments (except for self and _cmd, the automatically generated ones.)
}
 
// Hooking an instance method with no arguments.
- (id)noArguments {
    %log;
    id awesome = %orig;
    [awesome doSomethingElse];
 
    return awesome;
}
 
// Always make sure you clean up after yourself; Not doing so could have grave consequences!
%end
// Logos语法:http://iphonedevwiki.net/index.php/Logos

(5). 编译,打包和安装插件

// 编译
make
// 打包,完成之后会生成一个deb的安装包
make package
// 安装到指定设备,注意需要确认Makefile文件中指定的设备IP是否正确
make install

GitHub:https://github.com/theos/theos

iOSOpenDev
可视化的iOS越狱开发工具,与Xcode深度整合,不需要通过命令行,在熟悉的Xcode上即可进行iOS越狱开发,调试也方便。与开发普通App相比,熟悉的味道,一样的配方
官网:http://iosopendev.com/
GitHub:https://github.com/kokoabim/iOSOpenDev

5.5. 可视化管理工具

iTools
国产iOS系统管理工具,界面简洁,功能全面,除了有丰富的用户端功能之外,还有针对开发者的高级功能
iFunBox
老外出品,主要功能是针对iOS系统的文件管理
91手机助手PC版
最早的iOS系统管理工具,V3版本之后功能比较臃肿,缺少了开发者工具

5.6. 技术储备

(1). 熟悉iOS基础知识,ObjC语言以及框架
(2). 汇编和编译原理
(3). 逆向工程

6. 扩展阅读

IDA Pro权威指南
iOS应用逆向工程
看雪论坛
国内逆向论坛

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容