2023 SDC 议题回顾 | 从探索到利用:揭示安卓模拟器漏洞
2023-11-14 17:52:51 Author: mp.weixin.qq.com(查看原文) 阅读量:12 收藏

02

演讲内容

以下为速记全文:

大家上午好,很高兴有机会跟大家分享一下我之前对安卓模拟器的一些研究。我现在是在华为RO0T实验室,做一些二进制漏洞挖掘相关的工作。今天主要会以这三个部分来进行介绍:首先我们会进行一些背景介绍,然后讲几个具体的案例,最后做一些总结,给出一些增强安卓模拟器的安全能力的建议。
首先讲一下为什么要去研究安卓模拟器。本身我自己也经常用安卓模拟器来做一些 Apk的分析以及一些游戏的使用,还有我想通过这个去研究一下模拟器的实现,还有虚拟机逃逸的一些方式。
下面两张图是分析机构对安卓模拟器市场的一些统计:
模拟器的一些攻击场景主要有三类:
  • 第一个是普通的用户,可能会去跑一些不可信的应用,比如破解应用、外挂。
  • 第二个话就是恶意软件分析人员分析恶意apk的时候,会用到模拟器。
  • 第三个比较严重一些,可能是云手机这样的场景。其实云手机的实现也基本上是基于模拟器做的。
危害其实有两块:
  • 一是如果说我们拿到一个模拟器内部的os的提权的话,可能会窃取到其他APP的一些数据,和普通的手机的一些攻防是差不多的。
  • 二是如果我们能够实现虚拟机逃逸的话,它就可以去危害到宿主机。
目前模拟器的实现方案大概有这么几种:
  • 一个是基于Docker的,就是开源的Anbox;
  • windows的安卓子系统,它是基于他们自己的Hyper-V虚拟机;
  • QEMU,QEMU是谷歌的官方模拟器,我了解到有一部分的云手机厂商,他们其实也是基于QEMU去做了一些定制;
  • 第四大块的话基于VirtualBox,个人用户用的这种桌面级的虚拟机其实都是基于VirtualBox做的。
我们今天就是对基于VirtualBox的模拟器进行安全分析。
下面这张图其实是之前长亭的一个专家分享过的一个VirtualBox的一些架构图,VirtualBox它在 Guest和host的用户态和内核都会放一些东西来完成这些虚拟化的过程以及它的一些交互。
之前的一些研究主要集中在host 侧的一些外设,我们今天也是针对这些外设进行一些分析,主要专注在各个厂商为了提升他们模拟器的用户体验方面,所实现这种自定的外设这方面的一些安全漏洞。
我分析了市面上6款这种安卓模拟器,这几款其实都是会有一些漏洞。至于效果,其实5款我们可以做到用普通apk提到root权限,然后其中的三款是做了虚拟机逃逸的一个exp,漏洞类型的话主要就是一些比较常见的内存漏洞,像这种溢出、数组越界、条件竞争以及一些逻辑漏洞。
由于时间限制,我主要介绍4个厂商。
A 厂商是没有实现虚拟机逃逸的,以它为例来介绍一下整个的分析流程。
首先我介绍一下分析使用的一些工具和思路,工具的话其实就是用了Ida做一些逆向分析,然后用了调试器以及Frida做一些程序运行时的分析。
下面的procexp以及tcpview用来从宏观的角度上看一下目标的进程情况以及一些端口情况,能够方便我们去定位关键的进程。
最后面 dadb库的话,它是用Java实现了一个APP的客户端,它的作用是可以通过apk使用Java代码去连接,以TCP模式起的abdadb的服务,后面会讲到。
然后我们分析的思路的话,其实有以下几部分:
首先我们需要去定位模拟器进程,因为目标的一个模拟器它会有很多的进程,它其实只有某一个进程,它是专门做虚拟机仿真以及外设的一些模拟的进程。
我们定位进程之后,我们要定位到它这个设备起来之后,它到底有哪些外设是加载进来给 guest用的,之后我们需要去恢复一些关键的结构体,再去定位这种ml以及破了io这种 guess的测和后侧的交互的函数,用来做攻击的一些入口。
后面我们再基于这个入口开始去做一些分析,就能够发现一些漏洞。
我们分析之前需要被绕过反调式,VirtualBox非调试版是有反调式的,绕过方式:随便找一个dll,把它第一条指令改成一个死循环,那么它在进程起来之后,会处于一个死循环的状态,然后我们再用调试attach上去就可以进行调试了。
然后我们需要去恢复一些关键的结构体。在VirtualBox里面的话,其实每一个外设它都有一个 devIns 这样一个结构体来管理它里面的一些状态以及一些信息。
devIns 中有一个函数表指针,通过逆向以及调试去恢复这样一个结构体的函数表
之后,我们再根据这些函数的作用,可以进一步反推它外设的一些逻辑。
这边是一个我们恢复之后的情况,我们恢复之前它是会有很多那种交指针加引用,然后我们通过调试恢复右侧那种标红的那几个函数之后,我们通过这个函数的使用,可以进一步的去把剩下的一些结构体给它恢复出来,大概恢复完之后就是一个可以人工分析的状态了。
然后介绍一下对厂商A 的分析思路。
首先我们介绍guess侧提权的 bug。在安卓系统启动之后,他会在5555端口监听一个 adb server,然后我们去连接5555端口就可以获取一个root权限。
然后我们通过反复的开启和关闭模拟器进程,去对比进程情况,其实可以找到这么几个进程是和目标模拟器相关的,然后我们再去通过一些调试以及一些字符串的查看的话,其实是可以定位到进程大概是叫做VendorVmHandle.exe。
我们找到目标进程之后,需要去定位到它有哪些外设被启用。VirtualBox的pdmR3DevInit 函数的作用是调每个外设的构造函数,初始化外设。
它初始化的过程中,它后面会有一个字符串,我们可以通过这个字符串找这个函数,然后我们在这个地方下一个日志断点,就可以把模拟器启动过程中的所有的外设都给它打印出来。
这个设备其实是只有一个外设AAAptdevice 。它位于 VENDORa.dl 里面,然后这去分析DLL 的入口函数叫做VboxDevicesRegister,它里面会去注册gDevStruct,这个结构体定义的外设的名字和构造函数。
ptR3Construct 会注册IO Port, guest写这些IO Port 与 host 通信,这边是它设备比较高层次的结构的一个交互图,它左边是guest,右边是 host。
Host里面会有很多线程,主要就是IO 线程,IO PORT注册的回调函数就在该线程处理,还有一个GL 线程用于 GPU渲染加速。
外设的主要逻辑是通过 port io以及共享内存,实现了一个virtio的通信通道,然后这两个guest的侧通过这些通过 virtio 和 GL 线程 进行交互,主要就是guest的侧会把一些图像解析、图像渲染的东西扔给GL 线程 去完成图形的渲染。
ptR3Construct会去构造初始化8个 virtio队列,然后注册 IO Port的区域,在通过调试可以知道它的起始地址为d240,Guest读写这个区域就会进到 vendor_pmio_xxx 函数中。
漏洞位于ptR3QueueTrans,它的关键代码如下:
漏洞在于read_size 大于 hdr->length 时会导致堆溢出。
我们进入下一个目标。它其实也是一样的一些逻辑,通过连接5555 端口,可以拿到 root 权限。
然后分析启动日志,可以知道它有6个自定义外设,均都位于 VendorDD.dll。
今天我们只看VendorPipeCommand 外设,它会注册一些 virtio队列,Guest 通过写io port 选择回调函数进行通信。
简化的交互图如下:
它的漏洞位于SHELL-TX 队列的回调函数中,它的一个漏洞成因其实也是非常简单粗暴的,aSegsOut.CB没有检查会导致栈溢出:
经过分析目标进程没有开启栈保护且存在一个DLL 的基地址固定,利用思路如下:
我们会遇到一个问题,在尝试用户态去写这种IO PORT的时候,Guest 内核会崩溃,经过一些排查,可能的原因是他用了 x86CPU寄存器的一个特性,禁止了在用户态写 IO PORT。
那么解决思路也很直接,我们可以写ko模块在内核去写IO PORT,接着遇到第二个问题,我们如何在没有源码的情况下编一个可运行的ko 模块,解决方案如下:
然后进入厂商D,经过尝试发现开启和关闭 root 权限,虚拟机不需要重启,猜想想它应该内部有些进程会再去处理GUI请求。然后我在日志里面搜一下字符串,发现了左边这一块代码,它好像是在设置 root 相关的属性,我尝试去把属性给设成 1 ,发现系统会挂载 /system/xbin/su,通过执行 su 可以拿到 ROOT 权限。
然后通过一样的方式去找到目标的自定义外设,它总共有5个自定义外设:
今天我们主要讲其中4个外设,这4个外设它的构造函数都是 VmmgrPciConstruct,该函数主要就是注册共享内存、MMIO。
启动之后,我们使用root权限去目标系统里面看一下io内存。

我们主要讲讲这4个外设,它其实每个外设都是类似的一个东西,它有一块内存,然后有一块共享内存做一些控制,比如说 Guest 要和 Host 交互会通过写MMIO通知Host,具体的数据通过共享内存进行传递。
我们去读写内存的时候就会进到这两个函数,最关键的就是PciMmiioWrite函数。
通过交叉引用,可以找到每个外设的pciWriteFn。
然后我们看一下一些漏洞,下面是由于校验有误导致的越界写漏洞:
接着再介绍一下hcall机制:
hcallDecode 里面存在许多服务和漏洞,比如OOB:
控制QDesktopServices::openUrl 参数导致代码执行的漏洞:
虚拟机逃逸利用步骤:
下面进入最后一个厂商F,这个目标没有提供启用root权限的开关,但是它的文件系统中存在suid 的程序,可以用来提升到 ROOT 权限。
模拟器在安装之后,会在d盘一个固定路径下面建一个共享目录,这个目录会挂载到虚拟机的 /data/share目录。
我们今天讲的外设主要是VirtioVendorFPipe 外设,它也是注册了一堆 virtio 队列。
它注册了16个队列,不过16个队列的回调函数是同一个,只是参数不一样。
越界写漏洞:
第二行的时候,它会去读一个32字节的req,然后没有检查 req->payload_size,最后调用PhysRead把数据读到 req->payload里面去,控制req->payload_size 可以溢出 req->payload
越界读:
经过分析 req 位于 d11的的全局数据区,通过调试,发现它后面会有一些函数指针,我们通过读取和篡改这些函数指针,我们可以实现绕过ASLR 和实现代码执行。
漏洞利用步骤:
最后给出一些提升模拟器安全性的建议:

*峰会议题PPT及回放视频已上传至【看雪课程】https://www.kanxue.com/book-leaflet-171.htm 

PPT及回放视频【未购票者收费】;

【已购票的参会人员免费】:我方已通过短信将“兑换码”发至手机,按提示兑换即可~

《看雪2023 SDC》

看雪安全开发者峰会(Security Development Conference,简称SDC)由拥有23年悠久历史的顶尖安全技术综合网站——看雪主办,面向开发者、安全人员及高端技术从业人员,是国内开发者与安全人才的年度盛事。自2017年七月份开始举办第一届峰会以来,SDC始终秉持“技术与干货”的原则,致力于建立一个多领域、多维度的高端安全交流平台,推动互联网安全行业的快速成长。
钻石合作伙伴
黄金合作伙伴

球分享

球点赞

球在看

点击阅读原文查看更多


文章来源: https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458528496&idx=1&sn=980dcd2b79482d70a7a1c3452c481e97&chksm=b18d1a7a86fa936ccad74aed0cbadf35c6a84b09ea381e5f1f28b984e70093ae1ee4690c12b4&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh