Pwn2Own 高通 DSP

robots

 

简介

Snapdragon是由高通技术公司设计和销售的一套用于移动终端的系统芯片(SoC)半导体产品。单个SoC可能包括多个CPU内核、Adreno图形处理单元(GPU)、Snapdragon无线调制解调器、Hexagon数字信号处理器(DSP)、Qualcomm Spectra图像信号处理器(ISP)和其他硬件。

Snapdragon产品层按CPU、GPU和DSP处理器的可扩展计算资源进行区分。最低级别的产品可能只包含一个Hexagon DSP,而高级别的产品则包含多达四个Hexagon DSP处理器,专门用于特定的使用情况。例如,嵌入Pixel 4、三星S10、小米9、LG G8和OnePlus 7等手机的骁龙855(SM8150)SoC包括一个Kryo CPU、一个Adreno 640和四个独立的DSP,每个都专门用于特定的应用空间:传感器(sDSP)、调制解调器(mDSP)、音频(aDSP)和计算(cDSP)。

在此博客中,我们研究了两种DSP:

  1. cDSP,旨在执行计算密集型任务,例如图像处理,计算机视觉,与神经网络相关的计算以及摄像机流。
  • aDSP,旨在用于音频和语音数据的低功耗处理。

就现在的研究而言,我们将cDSP和aDSP视为一个处理单元(DSP)。我们发现的安全性问题对两者都适用。

 

CPU与DSP之间的通信

FastRPC是高通公司专有的远程程序调用(RPC)机制,用于实现CPU和DSP之间的远程功能调用。FastRPC框架是一种典型的代理模式。

【图片1:FastRPC流程】

图1中显示了FastRPC组件之间的交互:

  1. 用户模式进程(客户端)启动远程调用。例如,Android应用程序在其本地代码中调用其中一个存根函数。
  2. 存根是一个自动生成的代码,它将函数调用转换为RPC消息。一般来说,存根代码被编译为一个单独的本地库,然后与客户端链接。存根代码使用libadsprpc.solibcdsprpc.so库,通过相关的ioctls调用应用处理器(AP)上的DSP RPC驱动程序(/dev/adsprpc-smd/dev/cdsprpc-smd)。
  3. DSP RPC内核驱动接收远程消息调用,通过共享内存驱动(SMD)通道将排队的消息发送到DSP上的DSP RPC框架,然后等待响应。
  4. DSP RPC框架将消息从队列中移除,并将其分配给一个skeleton动态库进行处理。
  5. skel是一个自动生成的库,用于解组参数并调用目标方法的实现
  6. 目标方法(对象)是由高通公司或OEM提供的逻辑,旨在运行在DSP上。

谁可以在DSP上运行自己的代码?

出于安全考虑,DSP被授权给OEM和数量有限的第三方软件供应商进行编程。在DSP上运行的代码是由高通公司签署的。普通的安卓应用没有权限在DSP上执行自己的代码。骁龙855和865 SoC是个例外,高通公司被允许在cDSP上执行低权限的无签名动态共享对象。

应该注意的是,谷歌通过SELinux策略防止第三方应用程序和adb shell访问DSP RPC驱动程序,对Pixel设备实施保护。

公开的Hexagon SDK负责将DSP对象的C/C++源代码编译成适用于DSP上执行的Hexagon(QDSP6)字节码。 存根和skel代码是根据开发人员准备的接口定义语言(IDL)模块自动生成的。高通公司IDL用于定义跨内存保护和处理器边界的接口。IDL只暴露了该对象的作用,但没有暴露它的位置或实现它的编程语言。

一个安卓应用开发者能够实现其自定义的DSP库,但不能完全执行。只有预先构建的DSP库可以被一个Android应用自由调用。

 

谁来管理 DSP?

QuRT是一个高通公司专有的多线程实时操作系统(RTOS),管理Hexagon DSP。QuRT的完整性得到了高通公司安全可执行环境(QSEE)的信任。QuRT的可执行二进制文件(aDSP和cDSP是分开的)被签署并分割成几个文件,其方式与高通公司设备上任何其他受信任的应用程序相同。其默认位置是/vendor/firmware目录。

对于每个发起远程调用的安卓进程,QuRT在DSP上创建一个单独的进程。当用户进程被生成时,特殊的shell进程(/vendor/dsp/fastrpc_shell_0用于aDSP,/vendor/dsp/fastrpc_shell_3用于cDSP)被加载到DSP上。shell负责调用skeleton库和对象库。此外,它还实现了DSP的RPC框架,提供可能需要的skeleton和对象库的API。

DSP的软件架构提供了不同的保护域(PD)以确保内核软件的稳定性。在DSP中,有三个保护域:

  • 内核 – 可以访问所有PD的所有内存。
  • Guest OS – 可以访问自己PD的内存,用户PD的内存,以及一些系统寄存器。
  • 用户 – 只能访问它自己的PD的内存。

无签名的动态共享对象在无签名PD内运行,无签名PD是用户PD,其对底层DSP驱动和线程优先级的访问受到限制。无符号PD被设计成只支持一般的计算应用。

对象库以及FastRPC Shell在User PD中运行。

 

跳过FastRPC流程中的存根代码

libadsprpc.so和libcdsprpc.so库负责与DSP RPC驱动进行通信。这些库导出了两个对研究来说很有意思的函数。

  • int remote_handle_open(const char* name, remote_handle *ph). 这个函数在AP上的调用者进程和DSP上一个新的FastRPC shell进程之间打开一个远程会话。这个会话用于与作为第一个参数的skeleton库的通信。
  • int remote_handle_invoke(remote_handle h, uint32_t scalars, remote_arg *pra). 这个函数能够调用skeleton库的导出方法。一个会话处理程序应该作为第一个参数被指明。

【图片2:直接调用DSP】

让我们看一下该remote_handle_invoke函数的第二个和第三个参数,它们对目标方法及其参数进行了编码。

scalars是一个包含以下元数据信息的词:

  • 方法索引和属性(最高字节,0xFF000000掩码)。
  • 输入参数的数量(0x00FF0000掩码)。
  • 输出参数的数量(0x0000FF00掩码)。
  • 输入和输出句柄的数量(0x000000FF掩码,输入的四位和输出的四位)。在现代手机上,如果这个字节不等于零,则DSP调用失败。

pra是指向remote_arg目标方法的参数(条目)数组的指针。参数的顺序如下:输入参数,输出参数,输入句柄和输出句柄。

如图所示,每个输入和输出参数都被转换为一个通用的remote_buf条目。

应该注意的是,如果我们准备的remote_arg数组条目多于目标方法的要求,那么额外的参数就会被skeleton库忽略。

scalarspra参数传送“原样”通过DSP RPC驱动程序和DSP RPC框架,以及被用作在第一和特殊的第二参数invoke由每个skeleton库提供的功能。例如,libfastcvadsp_skel.so库提供了fastcvadsp_skel_invokeinvoke函数。invoke函数仅负责按索引调用适当的skel方法。每个skel方法本身都会验证收到的远程参数,将其解组remote_bufs为常规类型,然后调用object方法。

如你所见,要从skel库中调用方法,只需要知道其索引并通过remote_buf结构包装每个参数即可。我们不必提供调用函数的名称,其参数的类型和数量来执行调用的事实,使得skeleton库成为非常方便的fuzz的目标。

 

降级漏洞

高通公司已经在Android手机上预先安装了许多skeleton库。它们中的绝大多数是专有的。但是,有一些开源示例,例如libdspCV_skel.solibhexagon_nn_skel.so

几乎可以在所有Android设备上找到许多skeleton库,例如libfastcvadsp_skel.solibscveBlobDescriptor_skel.so。但是像libVC1DecDsp_skel.solibsysmon_cdsp_skel.so这样的库仅在现代Snapdragon SoC上提供。

有一些库是由OEM实现的,只在特定供应商的设备上使用。例如,libedge_smooth_skel.so可以在三星S7 Edge上找到,而libdepthmap_skel.so则在OnePlus 6T设备上。

一般来说,所有的skel库位于无论是在/dsp/vendor/dsp/vendor/lib/rfsa/adsp目录。默认情况下,该remote_handle_open函数将精确扫描这些路径。此外,还有一个环境变量ADSP_LIBRARY_PATH,可以在其中添加新的搜索路径。

如前所述,所有的DSP库都有签名,不能打补丁。然而,任何Android应用程序都可以在其资源中带来一个由高通公司签署的skeleton库,将其提取到应用程序的数据目录,将路径添加到ADSP_LIBRARY_PATH的开头,然后打开一个远程会话。因为库签名正确,所以库已成功加载到DSP上。

由于没有对加载skeleton库进行版本检查,因此有可能在DSP上运行一个非常老的具有已知1 day漏洞的skeleton库。即使更新的skeleton库已经存在于设备上,只要在原始文件的路径之前指出它在ADSP_LIBRARY_PATH中的位置,就有可能加载这个库的旧版本。通过这种方式,任何DSP补丁都可以被攻击者简单地绕过。此外,通过分析DSP软件补丁,攻击者可以发现一个库中的内部修复的漏洞,然后通过加载未打补丁的版本来利用它。

由于缺乏设备允许的批准/拒绝的skeleton库列表,有可能在任何其他设备(例如,索尼Xperia)上运行为一个设备准备的库(例如,三星)。这意味着,在某个OEM库中发现的漏洞会危及所有基于高通的安卓设备。

 

基于反馈的Hexagon库模糊测试

DSP库是专有的Hexagon ELFs。检测Hexagon可执行文件的最简单方法是使用开源的Quick仿真器(QEMU)。2019年底才在QEMU中加入Hexagon指令集支持。我们修复了很多bug,以便能够在模拟器的用户模式下运行真正的DSP库。

与QEMU相结合的美国Fuzz工具(AFL)被用来fuzz Ubuntu上的skeleton库和对象DSP库。

为了在模拟器上执行库的代码,我们准备了一个简单的程序(Hexagon ELF二进制文件),负责以下工作:

  1. 把作为第一个命令行参数收到的数据文件解析为标量字和远程参数数组。
  2. dlopen一个在第二个命令行参数中指定的skeleton库。该库可能依赖于其他skeleton库和对象库。例如,libfastcvadsp_skel.so依赖于libapps_mem_heap.solibdspCV_skel.solibfastcvadsp.so库。所有这些库都可以从固件中提取或从真实设备中拉出。
  3. 通过提供标量和一个指向remote_arg数组的指针作为参数,以其地址调用调用函数。例如,fastcvadsp_skel_invoke是对libfastcvadsp_skel.so库进行模糊测试的起始点。

我们在程序中使用了以下输入文件格式:

  1. 标量值(4字节)。在图3的例子中,标量值等于0x08020200,这意味着通过提供两个输入参数和两个输出参数来调用8号方法。
  2. 输入参数的大小(每个参数为4字节):0x10和0x20。
  3. 输出参数的大小(每个参数4个字节):0x80200和0x1000。
  4. 输入参数的值。在这个例子中,第一个参数的值是0x10字节的0x11,第二个参数的值是0x20字节的0x22。

【图3 用于Fuzz DSP库的输入数据文件】

对于每个输出参数,我们分配指定大小的内存,并用值0x1F填充它。

大多数skeleton库广泛使用DSP框架和系统调用。我们的简单程序不能处理这种请求。因此,我们必须在执行其余代码之前在模拟器上加载QuRT。最简单的方法不是使用真正的QuRT操作系统,而是使用其 “精简 “版本runelf.pbn,该版本被高通公司采用,用于在Hexagon模拟器上执行,并包含在Hexagon SDK中。

AFL模糊器改变了数据文件的内容,并在模拟器上触发了runelf.pbn的执行。QuRT加载准备好的ELF二进制文件,然后调用一个目标skeleton库。QEMU在执行测试用例后向AFL返回代码覆盖矩阵。

【图4: DSP库模糊测试方案】

我们对模糊处理的结果感到惊讶。在我们选择的所有 DSP 库中都发现了崩溃现象。仅在libfastcvadsp_skel.so库中就发现了数百个独特的崩溃。

有趣的是,大多数问题正是在skeleton库中发现的,而不是在对象库中。这意味着Hexagon SDK产生了脆弱的代码。

 

自动生成的代码

让我们来看看开源库hexagon_nn,它是Hexagon SDK 3.5.1的一部分。这个库导出了很多旨在进行神经网络相关计算的函数。

Hexagon SDK在库的编译时自动生成hexagon_nn_stub.c stub和hexagon_nn_skel.c skel模型。一些安全问题可以通过手动审查模块轻松发现。我们将只展示其中的两个。

装入一个字符串(char *)的参数

int hexagon_nn_op_name_to_id(const char* name, unsigned int* node_id)函数需要一个输入(name)和一个输出(node_id)参数。SDK生成以下存根代码来封送这两个参数:

我们可以看到,除了现有的两个参数外,第三个remote_arg条目是在_pra数组的开头创建的。此特殊_pra[0]参数保存name字符串的长度。

将name本身保存在第二remote_arg条目(_praIn[0]),在它的长度会再次存储,但这次是在_praIn[0].buf.nLen域中。

skel代码会提取这两个长度,并将它们作为signed int值进行比较。这就是错误所在。攻击者可以忽略存根代码,将一个负值(大于或等于0x80000000)写入第一个remote_arg条目中,绕过这个验证。这个假的长度然后被用作内存偏移,并导致崩溃(从堆的边界读出)。

为所有需要字符串参数的对象函数生成相同的代码.

对一个进出缓冲区进行管理

让我们看看int hexagon_nn_snpprint(hexagon_nn_id, unsigned char* buf, int bufLen)函数,它需要一个缓冲区和其长度作为参数。缓冲区同时用于输入和输出数据。因此,在存根代码中,它被分成两个独立的缓冲区(输入和输出缓冲区)。再一次,两个缓冲区的长度(_in1Len_rout1Len)都存储在额外的remote_arg条目(_pra[0])中。

skel函数在调用对象函数之前将输入缓冲区复制(使用_MEMMOVEIF宏)到输出缓冲区。要复制的数据大小是在特殊的remote_arg条目(_pra[0])中持有的输入缓冲区的长度。

攻击者控制这个值。所有的验证检查都可以通过使用一个负的输入缓冲区的长度简单地绕过。

在检查缓冲区边界时将类型转换为signed int类型是一个导致堆溢出的错误。

总而言之,自动生成的代码将漏洞注入高通公司、OEM和所有其他使用Hexagon SDK的第三方开发者的库中。由于SDK中存在严重的漏洞,预装在安卓智能手机上的几十个DSP skeleton库存在漏洞。

 

利用DSP漏洞

让我们来看看在专有DSP skeleton库中发现的众多漏洞之一,并尝试准备 “读什么 “和 “写什么 “的原语。

libfastcvadsp_skel.so库可以在大多数Android设备上找到。在下面的例子中,我们使用的是版本为1.7.1的库,从索尼Xperia XZ Premium设备中提取。恶意的安卓应用程序可以通过向remote_handle_invoke函数提供特制的参数,导致libfastcvadsp_skel.so库崩溃。图5中的数据文件显示了这种特制参数的一个例子。

【图5:导致libfastcvadsp_skel.so崩溃的数据文件】

如图所示,0x3F方法被调用并提供了一个输入参数和三个输出参数。输入参数的内容以字节0x14开始,包含以下主要字段。

  • 红色0x02显示要读多少个半字(大小)。
  • 黄色0x44332211显示要读取的内容(源)。这个值是相对于DSP堆中第一个输出参数的开始的偏移。使用这个偏移量,我们可以控制读取的起始地址。这个偏移量可以是我们想要的长度,甚至可以是负数。
  • 青色的0x04显示了要读的地方(目的地)。这个值也是偏移量。

崩溃是由于源地址不正确引起的。

【图6:故障转储】

下面显示了用于读取原语的缩写POC代码。

输入参数在DSP堆中总是位于输出参数之后。因此,在写入原语中,我们需要根据第一个输出参数的长度来转移源地址(所有其他参数都是空的)。

攻击者可以在DSP进程(User PD)的地址空间中操纵源和目的偏移量进行读写。第一个输出参数和内存中的libfastcvadsp_skel.so库之间的偏移量是一个常量值。在skel或对象库的数据段中找到一个指针来触发调用是很容易的。出于安全原因,我们将不公布DSP进程中代码执行的其余POC。

 

DSP用户领域研究的总结

在这次对属于高通DSP用户域的 skeleton 库和对象库的安全研究中,我们发现了两个全局性的安全问题。

缺少DSP库的版本控制。这使得恶意的Android应用程序可以进行降级攻击,并在DSP上运行有漏洞的库。

Hexagon SDK中的漏洞导致高通公司拥有的和移动供应商的代码中出现了数百个隐藏的漏洞。由于Hexagon SDK的问题,几乎所有嵌入基于Snapdragon的智能手机中的DSP skeleton 库都容易受到攻击。

我们向高通公司报告了几十个DSP库中约400个独特的崩溃,包括以下内容:

  • libfastcvadsp_skel.so
  • libdepthmap_skel.so
  • libscveT2T_skel.so
  • libscveBlobDescriptor_skel.so
  • libVC1DecDsp_skel.so
  • libcamera_nn_skel.so
  • libscveCleverCapture_skel.so
  • libscveTextReco_skel.so
  • libhexagon_nn_skel.so
  • libadsp_fd_skel.so
  • libqvr_adsp_driver_skel.so
  • libscveFaceRecognition_skel.so
  • libthread_blur_skel.so

为了证明这一点,我们利用其中一个已发现的漏洞,获得了在基于骁龙处理器的设备上执行无符号代码的能力,包括三星、Pixel、LG、小米、OnePlus、HTC和索尼手机。

一个能够访问DSP的用户域的安卓应用获得了以下可能性。

  • 触发DSP内核恐慌并重启移动设备。
  • 隐藏恶意代码。反病毒软件不扫描Hexagon指令集。
  • cDSP负责对来自摄像头传感器的流媒体视频进行预处理。攻击者可以接管这个流程。
  • 访问DSP内核驱动程序。驱动程序中的漏洞可以将应用程序的权限扩大到客户操作系统或DSP内核的权限。

 

DSP驱动器

QuRT操作系统实现了自己的设备驱动模型,称为QuRT驱动调用(QDI)。QDI是无法从Android API中访问的。像POSIX一样,QDI设备驱动的操作权限高于请求驱动服务的用户代码。QDI提供了一个简单的驱动程序调用API,隐藏了所有与特权模式相关的实现细节。

libqurt.a库是Hexagon SDK的一部分,它包含QDI基础设施。FastRPC外壳与该库静态链接。

在QuRT的可执行二进制文件中可以找到几十个QDI驱动程序。它们通常被命名为/dev/.../qdi/.../power/.../drv/.../adsp/.../qos/...int qurt_qdi_open(const char* drv)函数可以用来获得对QDI驱动的访问。一个小的整数设备句柄会被返回。这是与POSIX文件描述符的直接平行。

QDI只提供了一个宏,是必要的用户可见的API。这个qurt_qdi_handle_invoke宏负责所有的通用驱动操作。事实上,qurt_qdi_open只是这个宏的一个特例。这些是宏的参数:

  1. QDI句柄或预定义的常量值之一。
  2. 定义所请求动作的方法编号。在SDK的头文件中,我们看到。
    • 方法1和2被保留用于名称注册和名称查询。
    • 3-31保留用于对开放句柄的POSIX类型的操作。
    • 32-127保留给QDI基础设施。
    • 128-255保留给自动生成的方法使用,比如可能由IDL生成的方法。
    • 256和更高的是私有方法号。驱动程序可以按照自己的意愿使用这些方法。
  3. 0到9个可选的32位参数。

qurt_qdi_handle_invoke宏调用相关的设备驱动调用函数,该函数实现了主要的驱动逻辑,并提供了一个指定的方法号和可选的参数。

这是一个从用户PD代码中调用QDI驱动的例子。

一个QDI驱动使用int qurt_qdi_devname_register(const char *name, qurt_qdi_obj_t *opener) API函数在QuRT中注册自己。驱动程序提供它的名字和一个指向开启器对象的指针作为参数。

开启者对象的第一个字段是驱动程序调用函数。QuRT调用这个函数来处理来自用户PD或其他驱动程序的驱动请求,并提供以下参数。

  • QDI句柄,代表发送QDI请求的客户端。
  • 发出该QDI请求的开启器对象。
  • 由调用者提供的QDI方法。
  • 由调用者提供的九个可选参数。

一般来说,驱动程序的调用函数是一个由QDI方法ID组成的开关运算器。每个方法可以使用与所提供的参数数量不同的参数。参数类型是qurt_qdi_arg_t

请注意,驱动程序调用函数是基于模糊的漏洞研究的一个很好的目标,因为方法是由ID识别的,而不是由名字识别的,调用者不需要知道参数的确切数量和它们的实际类型来调用驱动程序方法。

 

基于反馈的QDI驱动程序的模糊测试

为了在Ubuntu上摸索QDI驱动,我们使用了与摸索DSP库相同的QEMU Hexagon和AFL的组合。然而,我们实现了另一个Hexagon ELF二进制文件qdi_exec,而不是skel_loader程序,它负责这些操作。

  1. 将作为第一个命令行参数收到的数据文件解析为QDI方法ID和一个由9个参数组成的数组,用于驱动调用函数。
  2. 通过第二个命令行参数中指定的地址调用驱动程序调用函数,并提供QDI方法ID和从数据文件中解码的参数。

我们为qdi_exec程序使用了以下输入文件格式。

  • 头部(4字节)。它包含三个有价值的字段。
    • QDI方法ID(10个低位)。在图7的例子中,它是0x01。
    • 参数的数量(4位)。在这个例子中,只有一个参数被使用。其余八个参数被认为是零。
    • 参数类型的掩码(9位)。正如我们前面提到的,每个参数要么是一个数字,要么是一个指向缓冲区的指针。在掩码中,每个参数用一个比特表示。值为0意味着该参数是一个数字,正值意味着该参数是一个缓冲区。
  • 缓冲区参数的大小(每个参数4字节)。在这个例子中,长度为0x0A的/dev/diag字符串被用作参数。
  • 缓冲区参数的内容。

【图7:用于fuzz QDI驱动程序的输入数据文件】

QDI驱动是作为QuRT ELF的一部分实现的。高通公司没有把它们包括在runelf.pbn版本的QuRT中,我们在模拟器上与我们的程序一起运行。因此,我们不得不对runelf.pbn ELF文件进行如下修补。

  1. runelf.pbn中添加用于真实设备的QuRT ELF的程序段。我们使用了从Pixel 4设备上提取的aDSP二进制文件。
  2. 将QDI驱动使用的mallocmemcpy内核函数重定向到其用户模式实现。内核内存函数限制了用户和内核空间之间的一些传输。

【图8: QDI驱动程序模糊测试方案】

AFL模糊器对数据文件的内容进行了修改,并在模拟器上触发了经过修补的runelf.pbn的执行。runelf.pbn加载了我们的qdi_exec程序,它直接调用了QDI驱动的调用函数。

我们通过对QuRT二进制文件的逆向工程,手动找到了QDI驱动调用函数的起始地址。开启者对象位于代码中的驱动程序名称旁边。

模糊器在骁龙855 aDSP内置的十几个QDI驱动程序中发现了许多崩溃现象。其中大部分也适用于cDSP。

 

利用QDI驱动程序中的漏洞

QDI驱动中的任何故障都可以被用来引起DSP内核的恐慌,并重新启动移动设备。例如,下面的每一行代码都会引起DSP恐慌,并可用于对设备进行DoS攻击。

出于研究目的,我们成功地利用了/dev/i2c QDI驱动的几个任意内核读写漏洞和/dev/glink QDI驱动的两个代码执行漏洞。出于安全原因,我们不能公布POC代码,但我们注意到,利用方法相当简单。这是一个读取原语的例子。

恶意的Android应用程序可以利用QDI驱动中发现的漏洞和用户PD的DSP库中描述的漏洞,在DSP客户操作系统的上下文中执行自定义代码。

 

从客户操作系统PD请求安卓服务

如果我们试图从DSP客户操作系统的代码中打开一个与安卓有关的文件,会发生什么?答案是,QuRT将我们的请求重定向到一个特殊的Android守护进程。正如你在图9中看到的,在骁龙855设备上,有两个aDSP守护进程和一个cDSP守护进程,它们以不同的权限运作。

【图9: DSP Android守护程序】

在Pixel 4设备上,这些守护程序的启动命令可以在init.sm8150.rc文件中找到。

【图10:像素4init.sm8150.rc初始化文件】

这些高权限的vendor.adsprpcdvendor.cdsprpcd守护进程处理DSP客户操作系统请求。u:r:adsprpcd:s0u:r:cdsprpcd:s0上下文只可以访问与DSP相关的目录和对象,它们作为系统用户操作,但同时又受到SELinux的限制。

 

结论

aDSP和cDSP子系统是非常有前景的安全研究领域。首先,DSP可以被第三方Android应用程序调用。其次,DSP处理个人信息,如通过设备传感器的视频和语音数据。第三,正如我们在博客中介绍的那样,DSP组件中存在许多安全问题。

高通公司为披露的DSP漏洞分配了CVE-2020-11201、CVE-2020-11202、CVE-2020-11206、CVE-2020-11207、CVE-2020-11208和CVE-2020-11209。对于QDI驱动程序中发现的漏洞,高通公司决定不指定CVE。所有问题都已通过2020年11月的高通公司安全补丁成功修复。

出于研究目的,我们利用了一些已发现的漏洞,获得了在所有基于骁龙的移动终端的aDSP和cDSP上执行特权代码的能力。

(完)