Disassembling Apple Exclaves

7 min readApr 6, 2025

Corrections to prior posts

  • Much of the functionality of Exclaves I covered previously (eg. Conclaves, Services etc) references the “XnuProxy”. This is a component running in user mode in the secure world.
  • In my first post on Exclaves, I suggested that the Secure Kernel may be based on seL4 because it contained strings referencing capabilities and other seL4 type objects. Posting on Bluesky, none other than Gernot Heiser himself (should that be “Himself”? 😊) said that SK almost certainly wouldn’t be seL4 (which would have been a GPL violation) but perhaps a clone. After further thought, I’ve realised that Apple could have simply taken some ideas from seL4 but developed their own flavour of L4, modified to suit their needs - perhaps even through modifications to their original cL4 kernel.
  • As already mentioned in a previous update post, Exclaves are implemented using the existing guarded execution privilege levels (GL0/1/2) rather than ARM TrustZone. More on this below, now that I have started disassembling it!

New Disassembly Discoveries!!

This section bought to you by … Microsoft! My [yes, old] PC running Windows 10 was going to be replaced by a Mac once Win10 support ended later this year. However the power supply died a few weeks ago and I’m now a happy Mac Mini owner 6 months early. I have a unix shell, and vi as an editor and am in heaven ;)

I’m new to this, but I have been slowly doing some small areas of disassembly related to Exclaves. It has very much helped to follow the prior work of other people on this. I’m doing this out of personal curiosity and impatience ;)

SPTM “Subsystems”

  • Dataflow forensics previously identified “subsystems” within SPTM. In iOS 18 there is now a new subsystem #9, which is identified as the CPUTRACE subsystem containing five calls.
  • Dataflow forensics also found two un-identified subsystems, #2 (with three calls) and #4 which was unimplemented in iOS17. Now in iOS 18, I have found that both of these are subsystems used by the Secure Kernel! Subsystem #4 contains two calls.
  • Like XNU, the Secure Kernel also has individual calls to SPTM subsystems #253, #254, and #255. The instruction following these calls is a HALT so I expect these are shutdown or panic type calls.
Components and Privilege Levels

XNU and SPTM

As we already know:

  • XNU runs in EL1/2
  • XNU uses GENTER to switch to SPTM in GL2
  • SPTM uses GEXIT to return to EL2

Secure Kernel / cL4

  • Secure Kernel runs in GL1 due to its ability to modify GL1/2 system registers.
  • Secure Kernel calls “up” to SPTM (GL2) via a hypervisor HVC #0 instruction, with the subsystem&call parameter in register X16 (remember from the above, this will be one of three calls from subsystem #2, or two calls from subsystem #4). This is a mirror of XNU except it uses HVC instead of GENTER, as SK is already running in the guarded execution world.
  • Secure Kernel contains ERET calls, which indicate it receives system calls to return (from GL0 rather than EL0 I assume). And indeed, examining many of the binaries that run in Exclaves, they do make system calls.

SK userspace— Exclaves and TXM

  • These system calls from Exclaves to SK come in the form of SVC #0 through to SVC #5. The system call numbers do not match up with either XNU’s Mach Trap or BSD syscall numbers. At this point, I think this indicates six different SVC calls are available within Exclaves (running in GL0), to call into the Secure Kernel (in GL1).
  • I haven’t delved too deep yet, but I saw SVC #4 and SVC #5 called by the exclaves “roottask”, in a very tight loop waiting until X0 != 1.
  • TXM still uses SVC #37, #38, and #0. Dataflow forensics identified these as going to SPTM in iOS 17. I haven’t checked (yet), but these must now be intercepted by SK, even if it is just forwarding #37 and #38 onwards. I do wonder if one of SK’s two SPTM subsystems is for TXM, and the other is for Exclaves.

Domains and Resources in the Root table

My first post listed some of the contents of the exclaves root table that had been discovered from the XNU side, however I have now extracted a much more complete list of domains and resources. Remember, a conclave can contain many resources of various types (such as services or buffers), and every conclave must have a conclave manager in the com.apple.kernel domain. This gives a fairly complete picture of everything that Apple is currently using Exclaves for!


com.apple.audiomxd.conclave:
com.apple.audio.lpmic
com.apple.audio.mic
com.apple.audiomxd.AudioCaptureServer
com.apple.audiomxd.MTDAudioDSPControl
com.apple.audiomxd.PerceptionAudioDSPControl
com.apple.audiomxd.SharedAudioDSPControl
com.apple.audiomxd.SiriAudioDSPControl
com.apple.audiomxd.SoundAnalysisAudioDSPControl
com.apple.inbound_buffer.hpmic_injection
com.apple.inbound_buffer.hpmic16_injection
com.apple.inbound_buffer.muted_talker_detection_ref_stream
com.apple.inbound_buffer.perception_ref_stream
com.apple.inbound_buffer.shared_audiodsp_ref_stream
com.apple.inbound_buffer.siri_ref_stream
com.apple.inbound_buffer.sound_analysis_ref_stream
com.apple.notification.audiocapture
com.apple.notification.audiodsp
com.apple.notification.audiodsp.analysis
com.apple.sensors.mic


com.apple.backboardd.conclave:
com.apple.backboardd.ExclaveFDRDecodeRawDataStoreKitService
com.apple.backboardd.AppleProxExclaveService
com.apple.backboardd.SILManager

com.apple.cameracaptured.conclave:
com.apple.cameracaptured.ISPIRManager
com.apple.cameracaptured.ISPRGBManager
com.apple.cameracaptured.ISPIRService
com.apple.cameracaptured.ISPRGBService

com.apple.conclave.mediaserverd:
com.apple.mediaserverd.ISPIRManager
com.apple.mediaserverd.ISPRGBManager
com.apple.mediaserverd.ISPIRService
com.apple.mediaserverd.ISPRGBService

com.apple.conclave.test1:
com.apple.service.ExclavesCHelloServer

com.apple.corespeechd.conclave:
com.apple.corespeechd.SiriVoiceTriggerService
com.apple.isolatedcoreaudioclient.service
com.apple.audio.siri_history
com.apple.sensors.mic

com.apple.darwin:
com.apple.service.ANEEngine
com.apple.service.ANEExclave
com.apple.service.ANEExclave_EDK
com.apple.service.ANEExclaveTestClient
com.apple.service.AudioDriver
com.apple.service.AudioDriver_EDK
com.apple.service.AudioDriverLPMic
com.apple.service.AudioDriverLPMic_EDK
com.apple.service.AudioDriverVT
com.apple.service.AudioDriverVT_EDK
com.apple.service.AudioSharedDARTMapper
com.apple.service.AudioSharedDARTMapper_EDK
com.apple.service.EXBrightCore
com.apple.service.EXBrightCore_EDK
com.apple.service.ExclaveDriverKit
com.apple.service.ExclaveFDRDecodeTestClientExclave
com.apple.service.ExclaveSEPManager
com.apple.service.ExclaveSEPManager_EDK
com.apple.service.ExclaveSEPTestClient
com.apple.service.ExclaveTestService
com.apple.service.EXDisplayPipeDriver_EDK_xnuproxy
com.apple.service.EXDisplayPipeDriver_xnuproxy
com.apple.service.HelloDrivers
com.apple.service.HelloExclaveCxx
com.apple.service.HelloExclaveKit
com.apple.service.HelloStorage
com.apple.service.HPMic16Device
com.apple.service.HPMic16Device_EDK
com.apple.service.HPMic16DMA
com.apple.service.HPMic16DMA_EDK
com.apple.service.HPMicAudioDriver
com.apple.service.HPMicAudioDriver_EDK
com.apple.service.SecureRTBuddyAOP
com.apple.service.SecureRTBuddyAOP_EDK
com.apple.service.SecureRTBuddyAOP_IOReporting
com.apple.service.SecureRTBuddyDCP
com.apple.service.SecureRTBuddyDCP_EDK
com.apple.service.SecureRTBuddyDCP_IOReporting
com.apple.service.TightbeamTestsServer
com.apple.service.user_app
com.apple.service.user_app2
com.apple.service.user_app3

com.apple.exclavetestrunnerd.conclave:
com.apple.exclavetestrunnerd.service

com.apple.facekittestd.conclave:
com.apple.facekittestd.service

com.apple.isolatedaudiometerclientd.conclave:
com.apple.isolatedaudiometerclientd.service
com.apple.isolatedcoreaudioclient.service

com.apple.kernel:
com.apple.audio.lpmic
com.apple.audio.mic
com.apple.audio.siri_history
com.apple.audio.test
com.apple.audiomxd.conclave
com.apple.backboardd.conclave
com.apple.cameracaptured.conclave
com.apple.conclave.mediaserverd
com.apple.conclave.test1
com.apple.corespeechd.conclave
com.apple.exclavetestrunnerd.conclave
com.apple.facekittestd.conclave
com.apple.inbound_buffer.exfiltration
com.apple.inbound_buffer.hpmic_injection
com.apple.inbound_buffer.hpmic16_injection
com.apple.inbound_buffer.muted_talker_detection_ref_stream
com.apple.inbound_buffer.siri_ref_stream
com.apple.inbound_buffer.sound_analysis_ref_stream
com.apple.isolatedaudiometerclientd.conclave
com.apple.mobileassetd.conclave
com.apple.named_buffer.1
com.apple.named_buffer.10
com.apple.named_buffer.112
com.apple.named_buffer.113
com.apple.named_buffer.16
com.apple.named_buffer.2
com.apple.named_buffer.3
com.apple.named_buffer.32
com.apple.named_buffer.36
com.apple.named_buffer.4
com.apple.named_buffer.41
com.apple.named_buffer.6
com.apple.named_buffer.7
com.apple.notification.audiocapture
com.apple.notification.audiodsp
com.apple.notification.audiodsp.analysis
com.apple.notification.hello
com.apple.outbound_buffer.exfiltration
com.apple.perceptiond.conclave
com.apple.securdled.conclave
com.apple.sensors.cam
com.apple.sensors.cam_alt_faceid
com.apple.sensors.cam_alt_faceid_delayed
com.apple.sensors.mic
com.apple.service.ConclaveLauncherControl
com.apple.service.ConclaveLauncherDebug
com.apple.service.ExclaveIndicatorController
com.apple.service.ExclaveKeyStoreTestClient
com.apple.service.ExclavesCHelloServer
com.apple.service.Exfiltration_xnuproxy
com.apple.service.FrameMint
com.apple.service.HelloDriverInterrupts
com.apple.service.ISPCamEngine
com.apple.service.ISPCamEngine_EDK
com.apple.service.ISPEngine
com.apple.service.ISPEngine_EDK
com.apple.service.LogServer_xnuproxy
com.apple.service.PanicInit
com.apple.service.Stackshot
com.apple.shareddspd.conclave
com.apple.sharedmem.stackshotserver
com.apple.soundanalysisd.conclave
com.apple.storage.backend

com.apple.mobileassetd.conclave:
com.apple.mobileassetd.service

com.apple.perceptiond.conclave:
com.apple.perceptiond.services
com.apple.isolatedcoreaudioclient.service

com.apple.securdled.conclave:
com.apple.securdled.service

com.apple.shareddspd.conclave:
com.apple.isolatedcoreaudioclient.service

com.apple.soundanalysisd.conclave:
com.apple.soundanalysisd.service
com.apple.isolatedcoreaudioclient.service

I noticed that some resources have duplicates — they appear both in a conclave domain and also in com.apple.kernel. These are all buffers, notifications and sensors. It appears these types of resources can be in more than one domain.

ExclaveCore

ExclaveCore consists of the Secure Kernel plus a number of other OS binaries, in a ~43MB .img4 file. The kernel binary itself is only 229KB, with only about 68KB of this being executable text! -

Minnie 22D82__iPhone17,1/Firmware/image4/SYSTEM> disarm -l kernel
Opened companion file kernel.ARM64.3BB4444D-5A7C-3146-90B5-1A33C51C4800
0x4000-0x18000 -> 0xffffff8000000000-0xffffff8000014000 __TEXT (TEXT,READ-ONLY, 81920 bytes)
0x4000-0x41b0 -> 0xffffff8000000000-0xffffff80000001b0 __TEXT.__head (TEXT,READ-ONLY, 432 bytes)
0x4800-0x145cc -> 0xffffff8000000800-0xffffff80000105cc __TEXT.__text (TEXT,READ-ONLY, 64972 bytes)
0x145d0-0x15020 -> 0xffffff80000105d0-0xffffff8000011020 __TEXT.__const (DATA,READ-ONLY, 2640 bytes)
0x15020-0x15974 -> 0xffffff8000011020-0xffffff8000011974 __TEXT.__cstring (TEXT,READ-ONLY, 2388 bytes)
0x18000-0x1c000 -> 0xffffff8000014000-0xffffff8000018000 __DATA (DATA, 16384 bytes)
0x18000-0x18130 -> 0xffffff8000014000-0xffffff8000014130 __DATA.__data (DATA, 304 bytes)
0x1c000-0x1d9e0 (not mapped) symbol table (6624 bytes)
0x1d9e0-0x1f990 (not mapped) string table (8112 bytes)

ExclaveCore includes a small number of binaries aside from the kernel, these are all MachO arm64e 64 bit executables, like SK. They do not run in kernel mode as SK is a microkernel — all of these are found to perform SVC calls to SK.

ExclaveOS Binaries (this is all of it!)

ExclaveKit

This is where the code, resources and frameworks for Exclaves themselves live. ExclaveKit is approximate 514MB in size. The basic directory structure is:

ExclaveKit Directory Structure

A small number of dylibs (42 libraries, 17.4MB) are located within ExclaveKit under /usr/lib.

Public frameworks in ExclaveKit are:

Private Frameworks in ExclaveKit:

It should be noted that there are many Exclave related frameworks within iOS as well. These provide the necessary methods to interact with functionality walled off inside the actual Exclaves.

ExclaveOS

ExclaveOS is presumedly the combination of ExclaveCore and ExclaveKit.

XRT

I still haven’t figured out what “XRT”, which is a frequent prefix in variable and function names, stands for. Is the X for Xnu or eXclave? Is RT for “real time” or “run time”? Or something else?

Xrt even gets its own ASCI-art in the ExclaveOS sharedcache binary!

disarm -r __TEXT.__cstring /Firmware/image4/APP/sharedcache | grep -A13 0x8ad3993

0x8ad3993: exclaves_allow_unlimited_early_crashes
0x8ad39ba: panic_on_conclave_exception_triage
0x8ad39e0: [CONCLAVE LAUNCHER
0x8ad3a00: State transition:
0x8ad3a20: Not Booted, needs storage
0x8ad3a40: ConclaveLauncherEntry()
0x8ad3a60: __ _______ _______
\ \ / / __ \__ __|
\ V /| |__) | | |
> < | _ / | |
/ . \| | \ \ | |
/_/ \_\_| \_\ |_|___Conclavelauncher

0x8ad3af0: ConclaveLauncherPseudoComponent/conclave-launcher.swift
0x8ad3b30: [Conclave Launcher] could not get resource data
0x8ad3b60: could not get data from EASM server resource collection

That wraps it up for now. My next post is hopefully about this whole concept of retrofitting microkernel-like isolation onto an existing OS. There is some prior art on this which I have been looking at, but it leads to questions of where exactly Apple is heading.

This post was based on the iPhone17,1_18.3.2_22D82_Restore.ipsw image.

--

--

No responses yet