联发科芯片Rootkit缝隙分析(CVE-2020-0069)
颁布功夫 2020-06-24一、缝隙布景
2020年3月,谷歌建补了一个存在于联发科芯片中的安全缝隙(CVE-2020-0069),缝隙影响20余款联发科芯片和数百万Android设备。该缝隙存在于MediaTek Command Queue驱动(CMDQ号令队列驱动),允许本地攻击者实现对物理内存地址的肆意读写,从而导致权限提升。
二、受影响国产手机型号
Huawei GR3 TAG-L21
Huawei Y5II
Huawei Y6II MT6735 series
Lenovo A5
Lenovo C2 series
Lenovo Tab E7
Lenovo Tab E8
Lenovo Tab2 A10-70F
Meizu M5c
Meizu M6
Meizu Pro 7 Plus
Oppo A59 series
Oppo A5s
Oppo A7x -- up to Android 8.x
Oppo F5 series/A73 -- up to A.39
Oppo F7 series -- Android 8.x only
Oppo F9 series -- Android 8.x only
Oppo R9xm series
Xiaomi Redmi 6/6A series
ZTE Blade A530
ZTE Blade D6/V6
ZTE Quest 5 Z3351S
三、CMDQ驱动简析
DMA(直接内存接见)是允许专用硬件直接从主存储器(RAM)发送或接管数据的一种个性。其主张是通过允许大内存接见而不外多占用CPU来加快系统。MediaTek Command Queue驱动(CMDQ号令队列驱动)允许从用户层与DMA节造器通讯,以实现媒体或显示有关的工作。
基于Redmi 6/6A 源代码分析,在cmdq_driver.h头文件中,申明cmdq驱动的IOCTL挪用如下:
CMDQ_IOCTL_ALLOC_WRITE_ADDRESS指令为分配一个DMA缓冲区。
CMDQ_IOCTL_FREE_WRITE_ADDRESS指令为开释一个DMA缓冲区。
CMDQ_IOCTL_READ_WRITE_ADDRESS指令为读取一个DMA缓冲区中的数据。
CMDQ_IOCTL_EXEC_COMMAND指令运行发送其他号令。
1、分配过程
通过CMDQ_IOCTL_ALLOC_WRITE_ADDRESS挪用cmdqCoreAllocWriteAddress ()函数,分配一个DMA缓冲区,该函数关键代码实现如下:
而后,挪用cmdq_core_alloc_hw_buffer()函数分配DMA缓冲区,pWriteAddr->va是虚构地址,pWriteAddr->pa为物理地址,两者逐一对应。并算帐缓冲区。
最后,将物理地址赋值到*paStart,并将pWriteAddr结构体增长到gCmdqContext.writeAddrList链表中。
2、执行号令过程
在CMDQ_IOCTL_EXEC_COMMAND挪用中,选取cmdqCommandStruct结构体作为参数,结构体界说如下:
pVABase指向用户层存放号令的缓冲区,缓冲区大幼放在blockSize中。其中cmdqReadAddressStruct结构体界说如下:
DmaAddresses是要读取的物理地址,读取的值存放在values中。在CMDQ_IOCTL_EXEC_COMMAND号令的执行过程,实现代码如下:
函数挪用蹊径如下:
Cmdq_core_acquire_task()函数会将command绑定到task中执行。具体实现如下:
挪用cmdq_core_find_free_task()函数获取一个空闲task。拿到空闲task并进行一些初始化设置,而后起头挪用cmdq_core_insert_read_reg_command()函数执行号令。
该函数实现分析,先拷贝用户层传入的号令到DMA缓冲区中。
pCommandDesc->pVABase是存放号令的内存肇始地址�?奖赐旰帕詈�,后面分几种方式结尾。
这里不做深究,最后拷贝EOC和JUMP指令结尾。这里也是将用户层传入的号令拷贝过来。
从cmdq_core_acquire_task()函数中返回后,如下:
挪用cmdq_core_consume_waiting_list()函数执行task。先从期待队列中获取task。
而后,获取空闲内核线程。
最后,将task绑定到thread中去执行。
四、读写号令分析
以cmdq_test.c测试代码为例,分析理解一个齐全的读写号令机关。cmdq驱动中界说了两类寄放器,一类是地址寄放器用于存放地址,一类是数值寄放器用于存放读取或写入的数值。
regResults是虚构地址,挪用cmdq_core_alloc_hw_buffer()函数分配一个dma地址,regResultsMVA与之对应,而后设置regResults中的数据�F鹜菲唇佣寥『托慈牒帕睿�
将regResults[0]的地址写入CMDQ_DATA_REG_DEBUG_DST类型的地址寄放器中。
而后,从CMDQ_DATA_REG_DEBUG_DST地址寄放器中读取数据并写入到CMDQ_DATA_REG_DEBUG数值寄放器中。这时辰,CMDQ_DATA_REG_DEBUG数值寄放器中的值应该为0xdeaddead。
接着,将regResults[1]的地址转存到CMDQ_DATA_REG_DEBUG_DST地址寄放器中。
最后,将CMDQ_DATA_REG_DEBUG数值寄放器中的0xdeaddead写入到CMDQ_DATA_REG_DEBUG_DST地址寄放器中保留的regResults[1]的地址中,即regResults[1]=0xdeaddead。判断regResults[0]和regResults[1]是否相称。
若是相称,注明读写成功。
五、PoC分析与测试
(1)PoC代码中,执行写操作的关键代码如下:
写入过程中,先将value[count]移动到CMDQ_DATA_REG_DEBUG数值寄放器中,而后将pa_address+offset地址移动到CMDQ_DATA_REG_DEBUG_DST地址寄放器中,最后将CMDQ_DATA_REG_DEBUG数值寄放器中的value写入到CMDQ_DATA_REG_DEBUG_DST地址寄放器中保留的pa_address+offset地址中,即*(pa_address+offset)= value[count]。
(2)PoC代码中,执行读操作的关键代码如下:
读取过程中,第一步先将pa_address+offset地址移动到CMDQ_DATA_REG_DEBUG_DST地址寄放器中,而后从CMDQ_DATA__REG_DEBUG_DST地址寄放器中存储的地址pa_address+offset中读取数据放到CMDQ_DATA_REG_DEBUG数据寄放器中,再将dma_address+offset地址移动到CMDQ_DATA_REG_DEBUG_DST地址寄放器中,最后将CMDQ_DATA_REG_DEBUG数值寄放器中保留的数据写入到CMDQ_DATA_REG_DEBUG_DST地址寄放器中存储的dma_address+offset地址中,即*(dma_address+ offset) = *(pa_address + offset)。
(3)在Reami6测试机中,执行PoC测试,成功将Linux批改成minix。
参考链接:
[1]https://github.com/MiCode/Xiaomi_Kernel_OpenSource/tree/cactus-p-oss/drivers/misc/mediatek/cmdq
[2]https://github.com/quarkslab/CVE-2020-0069_poc/blob/master/jni/kernel_rw.c
[3]https://blog.quarkslab.com/cve-2020-0069-autopsy-of-the-most-stable-mediatek-rootkit.html
[4]https://forum.xda-developers.com/android/development/amazing-temp-root-mediatek-armv8-t3922213
[5]https://source.android.com/security/bulletin/2020-03-01
宝运莱官方网站积极防御尝试室(ADLab)
ADLab成立于1999年,是中国安全行业最早成立的攻防技术钻研尝试室之一,微软MAPP打算主题成员,“黑雀攻击”概想首推者。截止目前,ADLab已通过CVE累计颁布安全缝隙1000余个,通过 CNVD/CNNVD累计颁布安全缝隙800余个,持续维持国际网络安全领域一流水准。尝试室钻研方向涵盖操作系统与利用系统安全钻延注移动智能终端安全钻延注物联网智能设备安全钻延注Web安全钻延注工控系统安全钻延注云安全钻研。钻研成就利用于产品主题技术钻延注国度沉点科技项目攻关、专业安全服务等。


京公网安备11010802024551号