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本地提权的更多相关文章

  1. 给深度学习入门者的Python快速教程 - 番外篇之Python-OpenCV

    这次博客园的排版彻底残了..高清版请移步: https://zhuanlan.zhihu.com/p/24425116 本篇是前面两篇教程: 给深度学习入门者的Python快速教程 - 基础篇 给深度 ...

  2. [置顶] think in java interview番外篇-谈程序员如何修练英语

    一.程序员对英语能力的重视度和能力要求应该是在各行各业中排在比较靠前的 这样说吧,英语程度的好坏直接影响着一个程序员的编程.开发.创新能力. 道理很简单: 1. 计算机和软件是用英语创造出来的 2. ...

  3. 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  4. 可视化(番外篇)——在Eclipse RCP中玩转OpenGL

    最近在看有关Eclipse RCP方面的东西,鉴于Gephi是使用opengl作为绘图引擎,所以,萌生了在Eclipse RCP下添加画布,使用opengl绘图的想法,网上有博文详细介绍这方面的内容, ...

  5. 可视化(番外篇)——SWT总结

    本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物.有何用,SWT中的常用组件.面板容器以及事件模型等. 1.可 ...

  6. 【重走Android之路】【番外篇】关于==和equals

    [重走Android之路][番外篇]关于==和equals   在实际的编程当中,经常会使用==和equals来判断变量是否相同.但是这两种比较方式也常常让人搞得云里雾里摸不着头脑.下面是我个人做的总 ...

  7. 【重走Android之路】【番外篇】有关于null的一些知识点

    [重走Android之路][番外篇]有关于null的一些知识点   1.首先,到底什么是null? null是Java中的一个关键字,用于表示一个空对象引用,但其本身并不是任何类型也不是属于任何对象. ...

  8. 番外篇 之 C#委托

    对于上一节 番外篇之C#多线程的反思 反思一:   Thread th = new Thread(参数); ////参数的总结 ////首先,第一情况,对于 Thread th = new Threa ...

  9. python自动化测试应用-番外篇--接口测试1

    篇1                 book-python-auto-test-番外篇--接口测试1 --lamecho辣么丑 1.1概要 大家好! 我是lamecho(辣么丑),至今<安卓a ...

随机推荐

  1. Visual Studio 2013 Web开发

    cnbeta新闻:微软正式发布Visual Studio 2013 RTM版,微软还发布了Visual Studio 2013的最终版本..NET 4.5.1以及Team Foundation Ser ...

  2. C++学习笔记 四种新式类型转换

    static_cast ,dynamic_cast,const_cast,reinterpret_cast static_cast 定义:通俗的说就是静态显式转换,用于基本的数据类型转换,及指针之间的 ...

  3. 机器人操作臂运动学入门一--D-H参数标定

    最近重新学习机器人方面的知识,想到一年以前在学校选修<机器人学技术基础>这门课的时候,老师虽然讲机器人的各个方面的知识都讲到了,但只是浮光绿影的的提到,并没有真正讲到深处,我的理解也没有更 ...

  4. io.sort.spill.percent调整

    引言 MapReduce作出保证:进入每个Reducer的数据行都是有序的(根据数据行的键值进行排序).MapReduce将Mapper的输出进行排序并传递给Reducer作为输入的过程称为Shuff ...

  5. hosts立即生效的方法

     做web开发和测试的,难免需要经常修改hosts来指定某个域名访问某个特定的IP:在windows中,每次修改了C:\windows\system32\drivers\etc\hosts,都需要重启 ...

  6. Sring控制反转(Inversion of Control,Ioc)也被称为依赖注入(Dependency Injection,DI)原理用反射和代理实现

    首先我有一个数据访问层接口: public interface StudentDao { void save(Student stu); } 和实现类: 1.mysql实现类 public class ...

  7. Line Search and Quasi-Newton Methods 线性搜索与拟牛顿法

    Gradient Descent 机器学习中很多模型的参数估计都要用到优化算法,梯度下降是其中最简单也用得最多的优化算法之一.梯度下降(Gradient Descent)[3]也被称之为最快梯度(St ...

  8. Asp.net MVC 3实例学习之ExtShop(四)——完成产品列表页

    在完成产品列表页前要做一些准备功夫.首先是去下载MvcPager用了为产品列表分页.下载的可能是基于MVC 2的,没关系,可以用在MVC 3上.如果有担心,下载源代码重新编译一次好了.下载后将DLL添 ...

  9. C# 多线程参数的使用

    一个参数: Thread.Start方法可以带一个参数: public static void Main() { Thread t = new Thread(new ParameterizedThre ...

  10. CP=&quot;CAO PSA OUR&quot; 用P3P header解决iframe跨域访问cookie

    1.IE浏览器iframe跨域丢失Session问题 在开发中,我们经常会遇到使用Frame来工作,而且有时是为了跟其他网站集成,应用到多域的情况下,而Iframe是不能保存Session的因此,网上 ...