攻击者思维:再现 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 时

d16f51d9e5db738d8504bc5a6f22ac07.png

当设备正在主动处理音频数据时,会创建调度队列“RDAudioBufferQueue”。一个 AVSoundInput 类实例已被传递给该线程,以通过上下文数据提供输入数据。由于线程安全考虑不够,当用户决定关闭语音控制功能时,上下文数据可能会在另一个队列“RDMainQueue”中提前释放,从而导致Use-After-Free(UAF)。

实际上有一个函数处理_dispatch_call_block_and_release<PC Corruption>之间执行的音频格式转换。它没有显示在回溯中,因为它使用了不将返回地址保存在堆栈中的“br”指令。

下面是该函数的伪代码:

de081afeb7da892b9fee16cf653207b8.png

(1) 在 _addRecordedSpeechSampleData:length: 方法内部,它试图调用存储在*( *(context_data + 48) + 16) 中的函数指针,通常它会执行EARCSpeechRecognitionAudioBufferAddAudioSamples。但是,如果用户决定关闭语音控制,context_data 将在另一个线程中释放,如下所示:

8af42cf808f5f59250018abf8bb0ecf6.png

问题是缺少一个锁来确保 RDAudioBufferQueue 会在 context_data 被释放之前退出。 *(context_data + 48) 中的堆内存可能会提前释放并被其他数据重新占用,从而导致程序计数器 (PC) 损坏。

案例2:当用户打开语音控制时

4b1b0f23923057b61c2550ea62b553c2.png

RDMainQueue 可能会随机发生在不同对象上的内存损坏。上面的例子是XPC连接对象在使用前被释放,Use-After-Free导致线程崩溃。

RDMainQueue 用作多用途的通用队列。各种回调将任务扔到这个队列中,包括接受和处理xpc请求,上报音频数据反馈和采取行动,经常涉及嵌套调用..所有这些任务都是通过dispatch_async提交到RDMainQueue的,它们的顺序似乎是正确的 打电话。

如果 XPC 连接对象的使用和释放都被分配到同一个队列中以正确的顺序处理,Use-After-Free 如何发生?

答案是 dispatch_async 不保证块按照调用顺序执行!

以下 POC 演示了即使在同一队列上使用 dispatch_async 的潜在威胁:

bf25768f4463642bbc909ea2c405ec29.png

dispatch_sync 更安全,就像将所有 dispatch_async 替换为 dispatch_sync 一样,上面的代码将完美运行。

dispatch_async 带来了支持嵌套调用的便利。但是,为了线程安全,开发人员最好实施额外的检查,以确保块按要求的顺序执行。

当用户频繁打开和关闭声控开关时,添加队列的繁忙操作会弄乱顺序,释放后可能仍然使用对象。

再现崩溃

您可以在锁定屏幕上触发此 Use-After-Free,执行以下步骤:

  1. 按住侧边按钮激活 Siri。

  2. 说“关闭语音控制”,会出现一个语音控制开关窗口。

6513a540b37ad1d624f7b3af3a059d15.png

  1. 反复开启/关闭语音控制。有一些技巧可以更可靠地触发崩溃。

除了使用 Siri,您还可以转到设置 -> 辅助功能 -> 语音控制

开启语音控制后,左上角会出现一个图标,先显示为灰色,然后变成蓝色。找到最佳时机的诀窍是在图标变为蓝色之前关闭语音控制。

aa5dc891789ce3e515e1c79b8e72d469.png

eab40a79455a35186286d352935416ec.png

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

c899823d3751905de54c5aa8ceb59175.png

点击👆卡片,关注后回复【面试题】即可获取

在看点这里e86b67eac3cbd3d68fd2910eede10c8d.gif好文分享给更多人↓↓

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值