iOS冰与火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权
iOS冰与火之歌(番外篇)
基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权
蒸米@阿里移动安全
0x00 序
这段时间最火的漏洞当属阿联酋的人权活动人士被apt攻击所使用的iOS PEGASUS(又称Trident三叉戟)0day漏洞了。为了修复该漏洞,苹果专门发布了一个iOS 9.3.5版本。这个漏洞的厉害之处在于可以直接从沙盒内对内核进行攻击(无需沙盒逃逸),并且同时影响iOS(9.3.4)和OS X (10.11.6)。因此,本篇文章将会从PEGASUS漏洞形成的原因开始分析,然后一步一步教大家写出OS X上利用PEGASUS提权的攻击代码。
《iOS冰与火之歌》这一系列文章的目录如下:
1. Objective-C Pwn and iOS arm64 ROP
2. 在非越狱的iOS上进行App Hook(番外篇)
3. App Hook答疑以及iOS 9砸壳(番外篇)
4. 利用XPC过App沙盒
5. UAF and Kernel PWN
6. 基于PEGASUS(三叉戟)的OS X 10.11.6本地提权 (番外篇)
另外文中涉及代码可在我的github下载: https://github.com/zhengmin1989/iOS_ICE_AND_FIRE
0x01 漏洞分析
PEGASUS(三叉戟)实际上是由三个漏洞组成,分别是:
CVE-2016-4657:Safari的Webkit内核上的内存破坏漏洞。
CVE-2016-4655:内核信息泄露漏洞,可用于绕过KASLR。
CVE-2016-4656:内核UAF漏洞,可用于控制内核并执行任意代码。
关于CVE-2016-4657目前还没有公开的资料,但Stefan Esser和Pangu分别爆出了另外两个漏洞CVE-2016-4655和CVE-2016-4656的细节。利用已经曝光的这两个漏洞,其实已经可以做到iOS非完美越狱和OS X本地提权了。下面我们就来讲解一下这两个漏洞形成的原因以及如何利用。
0x02 CVE-2016-4655 内核信息泄露
CVE-2016-4655这个漏洞形成的原因是内核在序列化和反序列化OSNumber的时候没有验证长度的正确性。因此,如果我们将number的长度设置的非常长,并用io_registry_entry_get_property()去获取number数据的话,就会造成内核的信息泄露。

我们知道内核栈中会保存函数的返回地址,因此我们可以利用这个返回地址去计算出内核的kslide,从而攻破kaslr的保护。
那么如何编写利用代码呢?我们先创建一个序列化后的dictionary。对内核来说,这个dictionary应该是这样的:
<dict> <key>min</key> <number>0x4141414141414141</number> </dict>
但是我们对OSNumber的长度进行了修改,变成了0x200:
uint32_t data[] = {
0x000000d3,
0x81000001,
0x08000004, 0x006e696d,
0x84000200, //change the length of OSNumber
0x41414141, 0x41414141
};
发送这个给内核后,内核在反序列化的时候就会出现错误。随后我们使用io_registry_entry_get_property_bytes()这个用户态函数就可以获取到内核返回的数据了。

因为我们修改了OS number的长度,所以返回的数据不光有我们发送给内核的number,还有栈上数据,比如函数ret时候的返回地址-0xFFFFFF80003934BF。

通过这个地址我们就可以计算出来kslide了。
0x03 CVE-2016-4656 内核代码执行
CVE-2016-4656这个漏洞其实有两种触发UAF的方法,我们这里先讲比较简单的那一种(两种方法在Stefan Esser的文章中都有介绍)。简单UAF漏洞形成的原因是OSUnserializeBinary支持用OSString和OSSymbol来作为key,并且支持用OSObject去引用之前的key。但是OSString和OSSymbol不一样的地方在于,OSString key转换为OSSymbol的过程中OSString已经被free掉了,但这个OSString却被加入了对象列表里。

因此当我们OSObject类型去引用一个已经被释放了的OSString的时候,就会产生UAF崩溃:

通过汇编崩溃的位置我们可以找到源码对应的位置是在341行创建OSObject对象的时候:

因此,如果我们能够在OSString被free的时候,立刻申请一段和OSString一样大小的内存并且构造好对应的vtable数据,当程序执行到OSObject创建的时候,内核就能成功的被我们控制。
那么如何编写利用代码呢?我们还是先创建一个序列化后的dictionary。对内核来说,这个dictionary应该是这样的:
<dict> <string>A</string> <bool>true</bool> <key>B</key> <data>vtable data...</data> <object>1</object> </dict>
内核随后会解析这个dictionary,正如我们之前分析的,OSString-”A”在创建完后就被free掉了,这时候,我们立刻创建OSSymbol-”B”以及和OSString-”A”大小相同的OSData,就可以在OSString-”A” free后重新控制这块内存,随后当内核使用OSObject引用OSString-”A”,并调用retain()函数的时候,其实就是在调用我们已经控制的vtable了。
0x04 利用ROP提权
首先我们先申请一块内存来放vtable和ROP chain,在OS X上有一种取巧的方法,如果我们是32位的程序的话,可以使用NULL page。因此,我们先用vm_allocate()申请到NULL Page,然后将vtable和ROP chain都保存在NULL page里:

随后在OS X上用rop提权的代码我们可以直接使用tpwn的:首先获得当前进程的ucred,然后将cr_svuid设置为0,最后用thread_exception_return退出进程。

0x05 测试EXP
编写完代码后,我们来尝试执行一下我们的exp。
首先说一下测试环境:Mac OS X EI Capitan 10.11.6 (15G31),在没有安装2016-01的security update的情况下(这时候内核相当于iOS 9.3.4,如果安装完2016-01 update就相当于iOS 9.3.5)。

接下来我们编译一下我们的exp:
clang -framework IOKit -framework Foundation -framework CoreFoundation -m32 -Wl,-pagezero_size,0 -O3 exp.m lsym.m -o exp
然后运行:

可以看到我们已经成功的获取了root权限。
0x06 总结
这篇文章介绍了如何利用PEGASUS(Trident三叉戟)做到内核信息泄露以及内核代码执行,然后利用rop获取root权限。另外,因为PEGASUS(Trident三叉戟)同时存在于iOS和OS X,有兴趣的同学可以在我们发布的攻击代码的基础上,尝试一下iOS攻击代码的编写。
基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权exp的下载地址:https://github.com/zhengmin1989/OS-X-10.11.6-Exp-via-PEGASUS
0x07 参考资料
1. http://blog.pangu.io/cve-2016-4655/
2. https://sektioneins.de/en/blog/16-09-02-pegasus-ios-kernel-vulnerability-explained.html
3. https://bazad.github.io/2016/05/mac-os-x-use-after-free/
4. https://github.com/kpwn/tpwn
作者:蒸米@阿里移动安全,更多安全类技术文章,请访问阿里聚安全博客
iOS冰与火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权的更多相关文章
- 《手把手教你》系列技巧篇(三十一)-java+ selenium自动化测试- Actions的相关操作-番外篇(详解教程)
1.简介 上一篇中,宏哥说的宏哥在最后提到网站的反爬虫机制,那么宏哥在自己本地做一个网页,没有那个反爬虫的机制,谷歌浏览器是不是就可以验证成功了,宏哥就想验证一下自己想法,于是写了这一篇文章,另外也是 ...
- 《手把手教你》系列技巧篇(三十六)-java+ selenium自动化测试-单选和多选按钮操作-番外篇(详解教程)
1.简介 前边几篇文章是宏哥自己在本地弄了一个单选和多选的demo,然后又找了网上相关联的例子给小伙伴或童鞋们演示了一下如何自动化测试,这一篇宏哥在网上找了一个问卷调查,给小伙伴或童鞋们来演示一下.上 ...
- 给深度学习入门者的Python快速教程 - 番外篇之Python-OpenCV
这次博客园的排版彻底残了..高清版请移步: https://zhuanlan.zhihu.com/p/24425116 本篇是前面两篇教程: 给深度学习入门者的Python快速教程 - 基础篇 给深度 ...
- [置顶] think in java interview番外篇-谈程序员如何修练英语
一.程序员对英语能力的重视度和能力要求应该是在各行各业中排在比较靠前的 这样说吧,英语程度的好坏直接影响着一个程序员的编程.开发.创新能力. 道理很简单: 1. 计算机和软件是用英语创造出来的 2. ...
- 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- 可视化(番外篇)——在Eclipse RCP中玩转OpenGL
最近在看有关Eclipse RCP方面的东西,鉴于Gephi是使用opengl作为绘图引擎,所以,萌生了在Eclipse RCP下添加画布,使用opengl绘图的想法,网上有博文详细介绍这方面的内容, ...
- 可视化(番外篇)——SWT总结
本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物.有何用,SWT中的常用组件.面板容器以及事件模型等. 1.可 ...
- 【重走Android之路】【番外篇】关于==和equals
[重走Android之路][番外篇]关于==和equals 在实际的编程当中,经常会使用==和equals来判断变量是否相同.但是这两种比较方式也常常让人搞得云里雾里摸不着头脑.下面是我个人做的总 ...
- 【重走Android之路】【番外篇】有关于null的一些知识点
[重走Android之路][番外篇]有关于null的一些知识点 1.首先,到底什么是null? null是Java中的一个关键字,用于表示一个空对象引用,但其本身并不是任何类型也不是属于任何对象. ...
随机推荐
- Java 8五大主要功能为开发者提供了哪些便利?
两年前当Java 8发布后,立即受到了业界的欢迎,因为它大大提高了Java的性能.它独特的卖点是,顾及了编程语言的每一个方面,包括JVM(Java虚拟机)和编译器,并且改良了其它帮助系统. Java是 ...
- load和initialize方法
一.load 方法什么时候调用: 在main方法还没执行的时候 就会 加载所有类,调用所有类的load方法. load方法是线程安全的,它使用了锁,我们应该避免线程阻塞在load方法. 在项目中使 ...
- gulp详细入门教程
本文链接:http://www.ydcss.com/archives/18 gulp详细入门教程 简介: gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优 ...
- H5坦克大战之【玩家控制坦克移动2】
周一没有看圣诞大战,这几天比较忙也没有看赛后的报道,今天就先不扯NBA,随便扯扯自己.昨天在电脑里找东西的时候翻到以前兼职健身教练时的照片,思绪一下子回到学生时代,脑子久久换不过来.现在深深觉得健身和 ...
- 【NLP】十分钟快览自然语言处理学习总结
十分钟学习自然语言处理概述 作者:白宁超 2016年9月23日00:24:12 摘要:近来自然语言处理行业发展朝气蓬勃,市场应用广泛.笔者学习以来写了不少文章,文章深度层次不一,今天因为某种需要,将文 ...
- 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新3)附高效动态压缩Bitmap
一.写在前面 爱吖校推如同它的名字一样,是一款校园类信息推送交流平台,这么多的家校互动类软件,你选择了我,这是我的幸运.从第一次在博客园上写博客到现在,我一次一次地提高博文的质量和代码的可读性,都是为 ...
- FFmpeg 中AVPacket的使用
AVPacket保存的是解码前的数据,也就是压缩后的数据.该结构本身不直接包含数据,其有一个指向数据域的指针,FFmpeg中很多的数据结构都使用这种方法来管理数据. AVPacket的使用通常离不开下 ...
- 免费道路 bzoj 3624
免费道路(1s 128MB)roads [输入样例] 5 7 21 3 04 5 13 2 05 3 14 3 01 2 14 2 1 [输出样例] 3 2 04 3 05 3 11 2 1 题解: ...
- SpringMVC+Shiro权限管理【转】
1.权限的简单描述 2.实例表结构及内容及POJO 3.Shiro-pom.xml 4.Shiro-web.xml 5.Shiro-MyShiro-权限认证,登录认证层 6.Shiro-applica ...
- Oracle 列数据聚合方法汇总
网上流传众多列数据聚合方法,现将各方法整理汇总,以做备忘. wm_concat 该方法来自wmsys下的wm_concat函数,属于Oracle内部函数,返回值类型varchar2,最大字符数4000 ...