攻击者思维:再现 dispatch_async 在 Voice Control 崩溃问题
Posted 程序员大咖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了攻击者思维:再现 dispatch_async 在 Voice Control 崩溃问题相关的知识,希望对你有一定的参考价值。
👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇
文章来自 zecOps
https://blog.zecops.com/research/use-after-free-in-voice-control-cve-2021-30902/
语音控制是 Apple 在 ios 13 和 macOS Catalina 中引入的一项强大功能。它可以替代屏幕上的所有触摸手势,让您可以使用语音进行点击、滑动、键入等操作,从而与设备进行交互。
com.apple.SpeechRecognitionCore.speechrecognitiond 崩溃
com.apple.SpeechRecognitionCore.speechrecognitiond
是一个处理语音控制的系统 XPCService 进程。
在对 Mobile XDR / Mobile DFIR 的调查期间,我们发现了一系列看起来很有趣的崩溃:
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Subtype: EXC_ARM_DA_ALIGN at 0x0074616f6c460003
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x2000002400000000 -> 0x0000002400000000
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x00000000100c02d8
移动设备调查分析
并非所有崩溃都相同,但它们都有相似的模式。所有崩溃都发生在一些 libdispatch.dylib
调用之后。
有了这个线索,我们继续调查这次事故的原因。
我们将解释两个最典型的案例。当用户在不同的时间切换语音控制开关时,都会发生这两种情况。
我们将附上一个演示意外多线程问题的 POC,证明即使开发人员使用优化的线程管理库(如 Grand Central Dispatch (GCD) 调度队列,从多线程的角度来看,这已经被认为是安全的)竞争条件的可能性仍然存在,能够导致内存损坏并导致代码执行。
下面是两个最典型的案例:
案例1:当用户关闭 VoiceControl 时
当设备正在主动处理音频数据时,会创建调度队列“RDAudioBufferQueue”。一个 AVSoundInput 类实例已被传递给该线程,以通过上下文数据提供输入数据。由于线程安全考虑不够,当用户决定关闭语音控制功能时,上下文数据可能会在另一个队列“RDMainQueue”中提前释放,从而导致Use-After-Free(UAF)。
实际上有一个函数处理_dispatch_call_block_and_release
和<PC Corruption>
之间执行的音频格式转换。它没有显示在回溯中,因为它使用了不将返回地址保存在堆栈中的“br”指令。
下面是该函数的伪代码:
(1) 在 _addRecordedSpeechSampleData:length:
方法内部,它试图调用存储在*( *(context_data + 48) + 16)
中的函数指针,通常它会执行EARCSpeechRecognitionAudioBufferAddAudioSamples。但是,如果用户决定关闭语音控制,context_data 将在另一个线程中释放,如下所示:
问题是缺少一个锁来确保 RDAudioBufferQueue 会在 context_data 被释放之前退出。 *(context_data + 48)
中的堆内存可能会提前释放并被其他数据重新占用,从而导致程序计数器 (PC) 损坏。
案例2:当用户打开语音控制时
RDMainQueue 可能会随机发生在不同对象上的内存损坏。上面的例子是XPC连接对象在使用前被释放,Use-After-Free导致线程崩溃。
RDMainQueue 用作多用途的通用队列。各种回调将任务扔到这个队列中,包括接受和处理xpc请求,上报音频数据反馈和采取行动,经常涉及嵌套调用..所有这些任务都是通过dispatch_async
提交到RDMainQueue的,它们的顺序似乎是正确的 打电话。
如果 XPC 连接对象的使用和释放都被分配到同一个队列中以正确的顺序处理,Use-After-Free 如何发生?
答案是 dispatch_async 不保证块按照调用顺序执行!
以下 POC 演示了即使在同一队列上使用 dispatch_async
的潜在威胁:
dispatch_sync
更安全,就像将所有 dispatch_async
替换为 dispatch_sync 一样,上面的代码将完美运行。
dispatch_async 带来了支持嵌套调用的便利。但是,为了线程安全,开发人员最好实施额外的检查,以确保块按要求的顺序执行。
当用户频繁打开和关闭声控开关时,添加队列的繁忙操作会弄乱顺序,释放后可能仍然使用对象。
再现崩溃
您可以在锁定屏幕上触发此 Use-After-Free,执行以下步骤:
按住侧边按钮激活 Siri。
说“关闭语音控制”,会出现一个语音控制开关窗口。
反复开启/关闭语音控制。有一些技巧可以更可靠地触发崩溃。
除了使用 Siri,您还可以转到设置 -> 辅助功能 -> 语音控制
开启语音控制后,左上角会出现一个图标,先显示为灰色,然后变成蓝色。找到最佳时机的诀窍是在图标变为蓝色之前关闭语音控制。
-End-
最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!
点击👆卡片,关注后回复【面试题
】即可获取
在看点这里好文分享给更多人↓↓
以上是关于攻击者思维:再现 dispatch_async 在 Voice Control 崩溃问题的主要内容,如果未能解决你的问题,请参考以下文章