攻击者思维 - iOS 摄像头指示灯不亮,就真的没事了么?

11445次阅读  |  发布于3年以前

从 iOS 14 开始,系统右上角新增了两个点:一个绿点和一个橙点。当访问摄像头或麦克风时,这些指示灯会点亮发出信号。

当没有绿色/橙色圆点时,我们就不那么担心手机能听到我们说话了。

我们知道像 NSO/Pegasus 这样的恶意软件能够监听麦克风。NSO Group 和数百名其他针对移动设备的威胁软件能否在摄像头指示器关闭时拍摄我们的视频呢?

让我们来看看此功能是否对攻击者构成任何挑战。

逻辑问题

我们先想一想。每次访问摄像头或麦克风时,指示灯是否真的亮起?我们很快就会想到 Siri。如果麦克风指示灯没有一直亮起,手机如何知道我们何时说“嘿 Siri”?手机一定在监听某种正确的声音。

“嘿Siri”

/System/Library/PrivateFrameworks/CoreSpeech.framework/corespeechd 依赖 VoiceTrigger.framework 来持续监听用户的声音,然后在听到关键字时激活 Siri。

辅助功能 -> 语音控制

语音控制允许您使用语音命令与设备交互。

/System/Library/PrivateFrameworks/SpeechRecognitionCore.framework/XPCServices/com.apple.SpeechRecognitionCore.brokerd.xpc/XPCServices/com.apple.SpeechRecognitionCore.speechrecognitiond.xpc/com.apple.SpeechRecognitionCore.speechrecognition

负责访问麦克风。

辅助功能 -> 切换控制

SwitchControl 功能的一部分是检测用户头部的运动以与设备进行交互。很酷的功能!由以下模块处理:

/System/Library/PrivateFrameworks/AccessibilityUI.framework/XPCServices/com.apple.accessibility.AccessibilityUIServer.xpc/com.apple.accessibility.AccessibilityUIServer

/System/Library/CoreServices/AssistiveTouch.app/assistivetouchd

这些功能必须访问麦克风或摄像头才能运行。但是,这些功能不会触发绿色/橙色视觉指示器。这意味着移动恶意软件也可以这样做。

这意味着通过将恶意线程注入 com.apple.accessibility.AccessibilityUIServer / com.apple.SpeechRecognitionCore.speechrecognitiond 守护进程,攻击者可以启用对麦克风的静默访问。相机访问需要额外的补丁,我们稍后会讨论

绕过 TCC 提示

TCC 代表“透明度、同意和控制”。iOS 用户经常会遇到这样的提示:

TCC 的核心是一个名为 tccd 的系统守护进程,它管理对敏感数据库的访问以及从输入设备(包括但不限于麦克风和摄像头)收集敏感数据的权限。

你可知道?TCC 提示仅适用于具有 UI 界面的应用程序。在后台运行的任何东西都需要特殊的操作权限。权限如下图所示。只需 kTCCServiceMicrophone 就足以访问麦克风。

相机访问稍微复杂一些。除了 tccd 之外,还有另一个名为 mediaserverd 的系统守护进程确保没有后台运行状态的进程可以访问摄像头。

到目前为止,当用户与另一个前台应用程序交互时,似乎需要一个额外的步骤(例如修补 mediaserverd)来在后台访问相机。

禁用麦克风、摄像头访问的可视指示器

第一种方法比较粗糙,使用 Cycript 向 SpringBoard 注入代码,导致指标突然消失。

com.apple.SpeechRecognitionCore.speechrecognitiondcom.apple.accessibility.AccessibilityUIServer 的启发,这是一种非常适合我们目的的私有权限 (com.apple.private.mediaexperience.suppressrecordingstatetosystemstatus)!不幸的是,此方法不适用于相机访问。

通过修补“mediaserverd”在后台访问相机

mediaserverd 是一个监控媒体捕获会话的守护进程。想要访问摄像头的进程必须得到 tccdmediaserverd 的批准。它是 tccd 之后的额外安全层。当它检测到应用程序不再在前台运行时,它还会终止相机访问。

值得注意的是,mediaserverd 配备了一个特殊的权限(get-task-allow)来防止代码注入。

作为“get-task-allow”权限的结果,动态调试器依赖于获取任务端口,如 cycript,frida 在 mediaserverd 守护进程上不起作用。当 mediaserverd 没有响应时,它也会经常被系统杀死,即使是很短的时间。这并不常见:这些迹象告诉我们 mediaserverd 负责一些重要的事情。

当进程切换到后台时,mediaserverd 将收到通知并撤销对该特定进程的相机访问权限。我们需要想办法让mediaserverd在检测到进程在后台运行时什么都不做。

经过简短的研究,我们发现可以通过 hook 到 Objective-C 方法 -[FigCaptureClientSessionMonitor _updateClientStateCondition:newValue:] 来防止 mediaserverd 撤销相机访问权限,因此不需要代码覆盖。

为了注入 mediaserverd,我们使用了 lldblldb 不依赖于任务端口,而是调用内核进行代码注入。实际上,已经具有内核代码执行能力的操控者可以替代 mediaserverd 的“权限”来执行此类注入。

POC 源代码可在此处获得 https://github.com/ZecOps/public/tree/master/hidden_cam_mic_demo。

在 Mac 上呢?

根据 2015 年之前的实验,Mac 上前置摄像头旁边的绿灯不能仅使用软件关闭。修改 AppleCameraInterface 驱动程序并上传自定义网络摄像头固件没有解决问题。绿灯无法关闭,因为它在相机开机时亮起。只要有电,灯就会一直亮着。从隐私角度来看,基于硬件的指标是理想的选择。我们尚未在最近的 Mac 版本/硬件上对此进行验证。

演示

我们做了一个演示,从后台进程访问摄像头/麦克风,使用RTMP协议流式传输视频/音频,步骤:

  1. 设置RTMP服务器
  2. 编译 mediaserver_patch,将代码注入 mediaserverd
  3. 编译 ios_streaming_cam,使用以下权限重新签署二进制文件并在后台运行
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.private.security.container-required</key>
    <false/>
    <key>platform-application</key>
    <true/>
    <key>com.apple.private.tcc.allow</key>
    <array>
        <string>kTCCServiceMicrophone</string>
        <string>kTCCServiceCamera</string>
    </array>
    <key>com.apple.security.iokit-user-client-class</key>
    <array>
        <string>IOSurfaceRootUserClient</string>
        <string>AGXDeviceUserClient</string>
    </array>
    <key>com.apple.private.mediaexperience.suppressrecordingstatetosystemstatus</key>
    <true/>
    <key>com.apple.private.mediaexperience.startrecordinginthebackground.allow</key>
    <true/>
    <key>com.apple.private.avfoundation.capture.nonstandard-client.allow</key>
    <true/>
</dict>
</plist>

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8