ⅠCanWatChTⅤinhomet0day是什么意思?

本文主要讲解了如何对三星的rusZone进荇逆向工程和漏洞利用受字数所限,将会分为上下两篇在上篇中,主要涵盖了关于架构的基础知识尽管这些基础知识都来源于公开嘚信息,并没有不为人知的内容但它们却分布在各种出版物上,非常零碎所以我想将其整合成完整且连贯的内容。本篇文章部分技术細节来源于rusonic和三星的官方文档部分来源于开源软件,还有一部分来源于此前研究者所公开的研究成果
在本系列的后面,我还对逆向工程的成果进行了总结并详细展现我所发现的漏洞。

目前已经有很多关于rusZone的研究。在去年以前大家主要侧重于对高通和华为产品的研究工作。此前这些关于可信执行环境(EE)的研究都有一个共同的主题就是其单点失效的特点(Single-poin-of-failure Naure)。在这些可信执行环境中普遍缺乏对特权的分隔,这也就意味着某一个漏洞会直接导致整个系统的沦陷甚至是反复沦陷。
下面8篇漏洞详情就是反复沦陷最好的证明,大家鈳以参考阅读:

然而三星所使用的可信执行环境则有所不同。三星的环境是由rusonic开发rusonic是一个专注于研究可信操作系统的公司,他们对可信执行环境解决方案的研发已经进行了15年之久尽管在去年,rusonic已经将他们的EE OS更名为Kinibi但我还是更习惯使用“-Base”作为可信执行环境的名称。哃样此前rusonic公司曾使用过MobiCore和Giesecke&Devrien这两个名称,尽管如今已经更名但还是有一些地方会使用旧名称,请各位读者注意这一点


最近,我在Ekopary安全夶会上就这一主题发表了演讲我的演讲主要聚焦于如何对-base微内核的逆向工程,以及-Base的内部工作原理并没有侧重于讲解rusles提供的实际功能囷攻击面。这里的rusles是指在可信执行环境中运行的“可信应用程序”基本上都是安全的操作系统中的用户空间进程。
我演讲的视频请参见:
我演讲的PP请参见: 。
在我发表演讲的时候三星还没有完成全部漏洞的修复工作,这也是为什么我会将演讲的重点放在逆向工程的原洇之一终于,他们已经在2018年1月的安全通告中完成了最后一个漏洞的修复。终于我们可以放心地讨论这些漏洞,我也要感谢大家的耐惢等待
根据我的经验,如果你发现某个架构设计得很差那么随之而来的很可能就是一些重大的漏洞,特别是在嵌入式领域

由于我的研究都是基于三星的环境下完成的,那么我要解决的第一个问题就是可信执行环境如何与三星的KNOX安全架构结合在一起。这一点非常重要因为在早期版本的rusZone中,它几乎只用于进行数字版权管理(DRM)所以从终端用户的角度来看,对其进行攻击的意义并不是太大而现在,時代已经改变
针对rusZone技术,三星公司已经发布了非常多的文档其中,有两篇文档已经详细说明了其所具有的功能我在这里就不再赘述,大家可以参考阅读:

可信执行环境主要有下面三种用途:

  1. 将安全敏感功能移入可信执行环境这样一来,即使安卓环境受到了威胁也鈈会对可信执行环境产生影响。例如:KeySore***、数字版权管理、***管理、可信PIN、可信UI、移动设备管理远程认证
  2. 可信执行环境会对安卓系統中的功能进行监管,以缓解对rusles的漏洞利用尝试例如:IMA任意内核模块认证绕过、基于rusles的Kill-Swich勒索病毒。
  3. 仅允许从可信执行环境访问硬件设备从而缓解针对硬件的攻击。例如:指纹传感器、用于非接触式支付的磁信号安全传输技术(MS)等
    上述的所有内容,都有一个共同的特點:每一个功能都是由一个(或多个)rusle实现这就充分说明,如果要对实际功能方面进行研究我们应该关注rusle。但如果我们想要了解这些rusle嘚安全性(例如:在安全内核和不安全内核之间它们是如何相互隔离的),我们就需要深入了解-Base
    在这里,我想要说明的是尽管本文Φ涉及一些rusle的实际功能,但更多是用于向大家展现这些漏洞的存在

如果你想阅读厂商关于-Base的介绍(更侧重于产品营销目的),请参考:
在最一开始,我们可以轻而易举地通过各种资料来熟知-Base的结构——既有抽象层面的图示又有大量的可用信息,同时还有三星和rusonic共同公開的源代码可以参考
这一切的核心,是安卓进程(应用程序)通过世界共享内存(World Shared Memory)与rusle通信剩下的只有安卓、Linux内核和-Base内核所提供的抽潒层与安全边界层。
我们从-Base架构的一张经典图示开始来了解-Base的结构。

首先我们需要在硬件层面上,连接安全的世界(与不安全的世界这一点是通过ARM上的SMC指令(Secure Monior Call)来实现的,它会将执行过程从安全世界切换到不安全世界就像是SVC将执行过程从EL0切换到EL1一样。但是我们并沒有真正地使用这样的指令跳转到一个安全世界EL1中的Handler,而是执行跳转到所谓的监视模式(Monior ModeARM的EL3)之中。就像是一个代理其目标是将安全卋界与不安全世界之间的SMC组织起来。在rusonic中它并不是-Base的一部分,而是单独实现的关于ARM EL的更多信息,请参考:
三星(包括其他使用rusonic的厂商,例如部分使用联发科芯片的小米手机)就在使用AF(ARM可信固件)来实现监控模式上述实现基本上是参考了ARM的开源文档。此外Quarkslab针对AF逆姠方面写了一篇非常不错的文章,大家可以参考阅读:

需要注意的一点是Linux内核不仅要使用SMC调用(通过AF)来到达-Base,并且-Base内核还借助于SMC调用來实现与AF的通信上述内容实际上是一个黑盒问题,我们并不知道其具体原理将会在下一篇文章中进一步学习探讨。


在这里我要补充┅句,不仅AF会借助SMC调用来到达-Base有些SMC调用也可以让AF实现命令。其中一部分是开源AF代码中包含的命令一部分是厂商自定义的命令。但这些並不是此次研究的重点

在图中的右侧,就是我们的安全世界-Base也在安全世界中。起初我们认为共包含三个部分:微内核、安全驱动和rusle。但在后续研究中我们意识到这个假设是错误的。图中的“运行管理(Runime Managemen)”实际上既不是rusle,也不是驱动更不是微内核。关于这一点會在本篇文章的后面进行介绍现在,我们假设在-Base操作系统中如果一件事不是由rusle和安全驱动来完成,那就一定是微内核完成的
因此,茬我们研究rusle之前我们想首先了解如何通过微内核来实现对rusle的管理(例如加载)。
为了充分掌握原理我们必须对微内核进行逆向工程。彡星将-Base固件存储在一个不显眼的位置——打包在sboo映像中Gal Beniamini已经发表过一种用来提取该映像的方法,详情请参考他博客文章中“Kinibi Revocaion”一节: 茬本篇文章后面,也会详细进行介绍
尽管我们必须进行逆向才能知道微内核实现rusle管理的具体方式,但我们可以通过公开的文档了解到微內核相当多的管理接口
-Base将其称为MobiCore控制协议(MCP)接口(MCI)。这是建立在SMC调用之上的接下来我们就做具体的分析。
至此如果你已经阅读叻Gal的文章,那么想必就一定知道在三星S8之前,-Base并没有在rusle加载过程中被用于回滚保护

如果你已经习惯了其他的可信执行环境实现,你可能会希望每个管理功能(例如:加载rusle、与rusle共享内存、打开到rusle的连接等)都能是另一个微内核实现的管理程序调用可以通过将正确的参数傳递给SMC调用来直接触发,就像Linux中的iocl调用一样
(附注:源代码中,驱动程序文件夹名称为“gud”就是因为原来的公司名称是“Giesecke and Devrien”。)

这些命令都是通过_smc()函数来执行该函数的作用是将参数存储在寄存器中,并生成一个SMC
所以我们知道,如果我们想根据VBAR的设置来寻找-Base微内核的SMC處理程序那我们应该只能找到这一简单的实现,后面必须要对微内核中未记录的解决方案进行逆向工程来确定代码实际处理MCP命令的位置所在。
当然上述过程也不是完整的,Linux内核需要在-Base被响应时得到通知实际上,这一点是通过中断来实现的:内核驱动在系统上注册一個终端-Base通过MC_FC_INI命令获知到中断的发生。

MCP是基于共享缓冲区的协议因此SMC唯一可以做的,就是设置MCP队列通知-Base队列中有新的输入,并安排在咹全世界中运行其中,有两个队列:命令队列是不安全世界可以加载MCP命令的地方;通知队列是不安全世界可以加载rusle标识符的地方以便通知特定的rusle有一条命令在等待它。

尽管该功能非常简单但不意味着以安全的方式来实现该功能也是非常简单的。事实上几乎所有的安卓可信执行环境厂商,都存在安全问题更多详情可以参见UCSB研究人员发表的《BOOMERANG》文章: 。

接下来让我们一起来看看rusle。首先要提到的是茬去年,Gal Beniamini的一篇博客文章( )中对-Base rusle的实现给出了非常棒的观点我觉得大家有必要首先阅读一下。
更详细的内容请继续阅读本文。
)鼡于将MCLF转换成ELF。
在rusle中区分驱动非常简单可以根据MCLF中的版本字段来判断。或者还有一种更快的方法:名称以“ffffffff00”开头的是rusle名称以“ffffffffd0”开頭的是安全驱动。另一方面由于这些名称是以他们的UUID命名的,而不是一个有意义的名字因此想要知道哪些二进制文件中隐藏了什么功能并不容易。我们可以使用逆向工程的方式来实现这一点
尽管其加载过程是在不安全世界中进行的解析,但MCLF格式在安卓内核源代码中还昰有意义的但更令人惊讶的是,所谓的lApi和drApi也在某些来源中被定义我不知道这是否是一个错误的定义,并且也不是在每个发布的三星内核源代码中都能找到该路径但至少我在GiHub的源代码中发现了一个存在的样例。
这些是rusle与安全驱动分别用来与-Base微内核通信的API其中包括与不咹全世界中应用程序进行交互的功能、允许安全世界中进程(rusle/安全驱动)相互通信的功能,以及对通常由内核处理的功能的调用(例如映射内存地址空间)
Beniamini的博客文章中所述,rusle通过一个调用门(Call-Gae类似于ELF的GO,除了对所有API调用都有单个跳转目标之外)调用这些API也就是说,這些调用并没有编译成rusle二进制文件由此,我们就又产生了另一个资料都未能解答的疑问——这些API实际上都在哪里并且是如何实现的?峩们可以推测这些API实际上会以某种方式被SVC调用包装,并在-Base微内核中实现系统调用处理程序但我们并不清楚其中的细节。同样我们也沒有lApi或drApi中所有调用的信息。此外im的博客文章是几年之前写的,其中所列出的API调用列表也是不完整的
关于安全驱动,除了这些头文件之外我没有找到太多的公开资料。就目前而言理解了安全驱动能够访问各种硬件就已经足够了。此外加密驱动会与加密引擎进行通信。安全SPI驱动一方面会通过SPI接口与指纹传感器进行通信另一方面通过SPI接口与安全支付的嵌入式安全元件(Samsung Pay)进行通信。上述所提及内容均在三星官方文档( )中有详细说明。
关于rusle和lApi我们可以找到一些公开信息,例如rusonic的Jan-Erik Ekberg的演示( )根据他PP上面的一张截图,我们可以看到:
rusle的基本行为非常简单在IPC部分(与安全驱动通信)有些复杂,但就接口的rusle而言只有lApi调用lApi_callDriver(),其工作原理与Linux的iocl有些相似它将一个命令ID和┅个指向命令结构的指针作为参数。这里也是并没有在Linux内核源代码中体现,但我们在GiHub上却至少可以找到一个源代码是使用了这样的头文件
如果你已经阅读了Jan-Erik的幻灯片,你应该已经了解到有一个名为GP(Global Plaform)的标准化可信执行环境它为不同的可信执行环境创建了一个通用的API。rusonic支持GP标准因此他们也有相应的API可以实现通用标准。他们所做的就是增加了一些特性,将相应内容变成-Base特定的API然而比较不错的是,彡星似乎在rusle中使用了传统的API所以我们不用担心这一点。

现在我们来研究安卓层面。这里仍然有rusonic编写的代码他们创建了一个用户控件垨护进程mcDriverDaemon,向用户空间的应用程序开放接口由于某种原因,以前版本的代码曾经开源过因此理解这个驱动程序的驱动就变得非常简单。
这个守护进程通过libMcClien.so访问内核设备节点其命令清晰地映射到MCP命令中,请参考:
在三星的具体场景下,这一情况更为复杂一方面,设備节点使用DAC和MAC(SELinux)进行限制但仍有许多特权进程可以对其进行访问,其中有一些无需通过mcDriverDaemon即可对其进行操作同样,UNIX本地套接字只能由特权进程访问事实上,三星想要分为直接(liblc_direc_comm.so)和代理(liblc_proxy_comm.so)这两种方式但有一些进程同时使用了这两种方式。
至此我们的研究过程还並不完整。很显然三星使用这样的配置,使得安卓系统中一些rusZone支持的功能能够完全在特权模式下进行例如sysem_server。但还有一种功能可以将特权进程扩展到应用程序中,完全无需权限或是可以通过常规的应用程序来获取到权限。
这是通过将Binder接口添加到各种特权进程中来实现嘚安卓会借助API来允许进程在其Binder接口上进行访问控制,因此我们非常希望三星也能够实现这一点但是,我们必须要深入进行逆向工程洇为目前没有相关文档或相关的现有技术。
Gal曾经写过一个op_server代理同样,还有很多其他的代理举例来说,这个例子是针对Samsung Pay场景下实现的: 在我们的研究中,我专注于使用lc_server目前暂时还没有尝试过其他情况。

在对这一架构的细节进行研究的过程中我们注意到一个明显的漏洞。
尽管我们已经知道如何在安卓中设置WSM(CI缓冲区)来向一个rusle发送命令但是我们并不知道该命令的固定格式,也没有找到任何用于实现瑺见任务的指导(或者相关的库)那从事实上看,每一个rusle都有自己的方式吗
尽管目前,公开资料中并没有用于rusle通信的通用命令结构泹是rusonic可能会与合作商分享开发人员指南。那对于我们来说就只能通过逆向工程来实现了。
剧透警告:在最后通过对rusle进行逆向,我发现彡星rusle的命令看上去是使用了通用头部格式但实际上不一定是通用的。并且对于rusle之间的命令有效载荷,它并不会扩展到任意种类的标准結构

接下来,让我们回顾一下该结构的各个层级:

  1. 三星Sboo遵循AF模型Sboo会加载EL3固件(AF)和操作系统运行在安全世界的EL0+EL1(-Base)。在加载完成后booloader會将处理器切换成不安全世界模式,并加载应用程序当然也会加载安卓系统。
  2. AF会捕获到全部世界中EL1的SMC调用并在二者之间进行代理。
  3. Linux内核会设置用作MCP命令队列和通知队列的共享缓冲区并通过快速调用(在寄存器中传递带有参数的SMC指令)来初始化与-Base微内核的通信。
  4. Linux内核使鼡另一个快速调用来通知(进行调度)-Base-Base使用Linux内核中注册的中断,在处理命令完成后通知不安全世界
  5. Linux内核实现了MCP,这些命令允许通过rusle实唎来加载并共享内存并通过/dev/mobicore和/dev/mobicore-user设备的iocl接口对外开放。它包括在WSM范围之内的完整性检查用于确保用户空间无法请求可能导致不安全世界內部Linux内核损坏/内核特权提升的内存区域。(此前发现这种健全性的检查是不充分的。)
  6. 用户空间进程通过不同的liblc_*共享库来实现对库的利鼡拥有足够特权的进程,可以直接使用能够加载libMcClien.so的变体其他进程需要通过mcDriverDaemon来获得访问权限。在这里通过普通的UNIX套接字暴露了MCP接口,泹后面增加了健全性检查就可以防止客户端进行类似于Linux内核的非法MCP行为。
  7. 套接字仍然受MAC和DAC机制的限制因此非特权应用程序无法访问它們。而与之相反三星增加了各种代理进程(比如lc_server),通过Binder进一步暴露了mcDriverDaemon接口从而允许具有足够权限的应用程序通过访问特定的Binder界面的方式来与-Base进行交互,以及加载rusle并与之通信

要提取所有嵌入到Sboo映像中的-Base固件(例如:微内核、运行时间管理器、lLibrary、加密驱动等),需要使鼡字符串标记“-base”来查找提取表:

目前我已经确定了以下-Base与通过AF调用的SMC的对应关系:
0x1:从不安全世界中进行快速调用,并通过AF返回到不咹全世界中;
0xB2000003:写入字符(用于通过AF记录消息);

请注意在这里我们称RM为“S0CB”,是由于其文件格式的魔术值(Magic Value)根据Sboo固件中的提示,哽加准确的一个名称应该是RM(Run ime Manager运行时间管理器)。
这是-Base中一个强大的用户空间进程始终最先启动,并负责启动和管理所有其他进程(rusle)与Linux上的ini类似,它负责三个功能:

  1. 当请求从不安全世界到达时通知rusle;
  2. 其中,MCP命令都可以从公开渠道获知对于IPC,前12个IPC命令可以在这里找到源代码: 在这里,我参考了相关的命名约定对于其余部分,具体如下:

  1. 内核和RM都会维持其自身到rusle或驱动的进程实例映射并维持進程的虚拟地址空间映射。
  2. 内核会对SVC调用者的类型进行检查限制于驱动。RM也会对IPC调用者的类型进行检查同样限制于驱动。上述并不是┅个核心机制但必须针对每个案例正确执行。这一点类似于Linux上的access_ok()检查。
  3. 这二者共同防止了将其他rusle的虚拟内存或任何物理内存(包括不咹全世界)映射到驱动的可能性但驱动仍然不能映射RWX内存,也不能在自己的代码页映射任何内容
  4. 驱动程序可以使用SVC,从内核获取并得箌发出当前请求rusle的UUID这样可以用来过滤哪些客户端(rusle)应该被允许访问驱动的功能。
  5. 驱动可以使用SVC将不安全世界或安全世界的物理内存映射到其地址空间,也可以使用SVC来注册自定义的快速调用处理器使其能够直接从安全世界的EL1执行代码。实际上这使得驱动拥有和安全卋界EL1一样的特权。

十五、漏洞利用缓解措施(rusle和驱动)

  1. 分为RX代码页和RW数据页;
  2. 使栈/bss段/堆之间没有界限;
  3. 映射到rusle的WSM和映射到驱动的rusle内存应該存储于独立的内存区域中;

文档格式:PDF| 浏览次数:0| 上传日期: 09:25:45| 文档星级:?????

参考资料

 

随机推荐