How iOS malware can spy on users silently

In this blog, we’ll demonstrate how mobile threat actors bypass the recently added camera & microphone green/orange indicators.

November 4 2021 by

Jamf Threat Labs

Bad actor spying on victims

Starting in iOS 14, there are a couple of new indicators: a green dot, and an orange dot. These indicators signal when the camera or the microphone are accessed.

We are less worried about the phone listening to us when there’s no green/orange dot, shown below on this image from Apple's website.

Image of orange and green dot on iOS device indicating microphone or camera is being accessed

We know that malware like NSO/Pegasus is capable of listening to the microphone. Can NSO Group and hundreds of other threat actors that target mobile devices can take videos of us while the visual indicator is off?

Let’s examine if this feature poses any challenge to attackers.

Logical issues

Let’s first think about it. Is the indicator really on everytime the camera or microphone are accessed? We quickly think about Siri. How does the phone know when we say “Hey Siri” if the microphone indicator is not on all the time? The phone must be listening somehow right.

“Hey Siri”

/System/Library/PrivateFrameworks/CoreSpeech.framework/corespeechd relies on VoiceTrigger.framework to continuously monitor the user’s voice, and then activate Siri when a keyword is heard.

Accessibility -> VoiceControl

Voice Control setting toggle on iOS device

Voice control allows you to interact with the device using voice commands.

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

is responsible for accessing the microphone.

Accessiblility -> Switch Control

Switch settings on iOS device

Part of the SwitchControl function is to detect the movement of the user’s head to interact with the device. Very cool feature! It’s handled by:

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

and

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

These features must access the microphone or camera to function. However, these features do not trigger the green/orange visual indicators. This means that mobile malware can do the same.

This means that by injecting a malicious thread into com.apple.accessibility.AccessibilityUIServer / com.apple.SpeechRecognitionCore.speechrecognitiond daemons attackers can enable silent access to the microphone. Camera access requires additional patch which we will talk about it later

Bypass TCC Prompt

TCC stands for “Transparency, Consent, and Control”. iOS users often experience this prompt:

iOS prompt from Audio Recorder asking permission to access the microphone

The core of TCC is a system daemon called tccd, and it manages access to sensitive databases and the permission to collect sensitive data from input devices, including but not limited to microphone and camera.

Did you know? TCC prompt only applies to applications with UI interface. Anything running in the background requires special entitlement to operate. The entitlement looks like the picture below. Just kTCCServiceMicrophone is enough for microphone access.

com.apple.private.tcc.allow key

Camera access is a little more complicated. In addition to tccd, there is another system daemon called mediaserverd ensures that no process with background running state can access the camera.

System daemon mediaserverd with bg:0

So far, it looks like an extra step (e.g. patching mediaserverd) is needed to access the camera in the background while the user is interacting with another foreground application.

Disable visual indicators for microphone, camera access

First method is rough, using Cycript to inject code into SpringBoard, causing the indicator to disappear abruptly.

Terminal session using Cycript to inject code into SpringBoard to make microphone and camera access indicators disappear

Inspired by com.apple.SpeechRecognitionCore.speechrecognitiond and com.apple.accessibility.AccessibilityUIServer, a private entitlement (com.apple.private.mediaexperience.suppressrecordingstatetosystemstatus) that fits perfectly for our purpose! Unfortunately, this method does not work for camera access.

com.apple.private.mediaexperience.suppressrecordingstatetosystemstatus private entitlement

Accessing camera in the background by patching ‘mediaserverd’

mediaserverd is a daemon that monitors media capture sessions. Processes that want to access the camera must be approved by tccd as well as mediaserverd. It is an extra layer of security after tccd. It also terminates the camera access when it detects an application is no longer running in the foreground.

Noteworthy, mediaserverd is equipped with a special entitlement (get-task-allow) to prevent code injection.

get-task-allow entitlement

As a result of “get-task-allow” entitlement, dynamic debugger relies on obtaining task ports like cycript, frida do not work on the mediaserverd daemon. mediaserverd also gets killed by the system frequently when it’s not responding, even for a short time. It’s not common: these signs are telling us that mediaserverd is in-charge of something important.

When a process switches to the background, mediaserverd will get notified and revoke camera access for that particular process. We need to find a way to make mediaserverd do nothing when it detects that the process is running in the background.

Following a brief research we found that it is possible to prevent mediaserverd from revoking camera access by hooking into an Objective-C method -[FigCaptureClientSessionMonitor _updateClientStateCondition:newValue:], so no code overwriting is required.

To inject into mediaserverd, we used lldb. Lldb does not rely on task-port, instead it calls the kernel for code-injection. In reality, threat-actors that already have kernel code execution capabilities can replace the “entitlements” of mediaserverd to perform such injection.

View the POC source code.

And on Mac…

From previous experiments back in 2015, the green light next to the front camera on a Mac, cannot be turned off using software only. Modifying the AppleCameraInterface driver and uploading a custom webcam firmware did not do the trick.The green light cannot be turned off since it lights when the camera is powered on. The light remains on as long as there’s power. Hardware-based indicators are ideal from a privacy perspective. We have not validated this on recent Mac versions / HW.

Demo

We made a demonstration, accessing the camera/microphone from the background process, and streaming video/audio using the RTMP protocol, steps:

  1. Set up RTMP server
  2. Compile mediaserver_patch, inject the code into mediaserverd
  3. Compile ios_streaming_cam, re-sign the binary with following entitlements and run it in the background

Demo written by 08Tc3wBB.

Subscribe to the Jamf Blog

Have market trends, Apple updates and Jamf news delivered directly to your inbox.

To learn more about how we collect, use, disclose, transfer, and store your information, please visit our Privacy Policy.