1.0 The Silicon Root of Trust: Pre-Boot & Hardware Primitives
The security of the macOS platform on Apple Silicon is not defined by the kernel; it is defined by the physics of the die. Before the first instruction of kernelcache is fetched, a complex, cryptographic ballet has already concluded within the Application Processor (AP). This section dissects the immutable hardware logic that establishes the initial link in the Chain of Trust.
1.1 The Reset Vector & Boot ROM (SecureROM)
The Apple Silicon boot process begins in a state of absolute trust, anchored by the Boot ROM (often colloquially referred to as SecureROM). This code is mask-programmed into the silicon during fabrication. It is immutable, unpatchable, and serves as the hardware root of trust for the enti…
1.0 The Silicon Root of Trust: Pre-Boot & Hardware Primitives
The security of the macOS platform on Apple Silicon is not defined by the kernel; it is defined by the physics of the die. Before the first instruction of kernelcache is fetched, a complex, cryptographic ballet has already concluded within the Application Processor (AP). This section dissects the immutable hardware logic that establishes the initial link in the Chain of Trust.
1.1 The Reset Vector & Boot ROM (SecureROM)
The Apple Silicon boot process begins in a state of absolute trust, anchored by the Boot ROM (often colloquially referred to as SecureROM). This code is mask-programmed into the silicon during fabrication. It is immutable, unpatchable, and serves as the hardware root of trust for the entire platform.
1.1.1 Execution at Exception Level 3 (EL3): Analyzing RVBAR_EL3
Upon Power-On Reset (POR), the cores of the M-series SoC (and A-series) initialize in the highest privilege state defined by the ARMv8/v9 architecture: Exception Level 3 (EL3).
While Apple does not utilize TrustZone in the traditional sense (preferring their proprietary Secure Enclave for secure world operations), the AP Boot ROM executes at EL3 to perform the necessary low-level hardware initialization that requires access to secure configuration registers that are subsequently locked or hidden from EL2/EL1.
The execution flow begins at the address defined in the Reset Vector Base Address Register (RVBAR_EL3). On recent Apple Silicon (M1/M2/M3), the memory map places the Boot ROM at a high base address, typically 0x100000000.
The Initial Instruction Stream: The very first instructions executed by the silicon are responsible for establishing a sane C execution environment from a raw hardware state. A disassembly of the entry point typically reveals the following sequence:
- Interrupt Masking:
DAIFbits are set to mask all interrupts (IRQ, FIQ, SError, Debug). The Boot ROM operates in a strictly polled mode; interrupts are nondeterministic and introduce attack surface. - Cache Invalidation: The instruction and data caches are invalidated to prevent cold-boot attacks or stale data usage.
- Stack Setup: The Stack Pointer (
SP_EL3) is initialized to point to a dedicated region of on-chip SRAM (Static RAM). Note that DRAM is not initialized at this stage. The Boot ROM runs entirely within the constraints of the SoC’s internal SRAM (often referred to as L2 cache-as-RAM in older exploits, though modern SoCs have dedicated boot SRAM). - MMU Configuration: The System Control Register (
SCTLR_EL3) is written to enable the MMU, mapping the Boot ROM text as Read-Only/Executable and the SRAM stack/heap as Read-Write/No-Execute.
RE Note: Apple’s implementation of EL3 is ephemeral. Unlike Android/Qualcomm devices where EL3 hosts a persistent Secure Monitor (QSEE), Apple Silicon demotes the exception level to EL2 (Hypervisor) or EL1 (Kernel) before handing off control to the next stage. Once the Boot ROM exits, EL3 is effectively locked out, and the
RVBAR_EL3is often locked to prevent re-entry.
1.1.2 The GID Key (Group ID): Hardware-entangled Decryption
The Boot ROM’s primary objective is to load the Low-Level Bootloader (LLB). However, the LLB stored on the NAND flash (or NOR SPI flash in some configurations) is encrypted. To decrypt it, the Boot ROM utilizes the GID Key (Group ID Key).
The GID Key is a 256-bit AES key fused into the silicon during manufacturing. It is shared across all processors of the same class (e.g., all M3 Pro chips share a GID, but it differs from the M3 Max).
The “Black Box” AES Engine: Crucially, the GID Key is not accessible via software. There is no Memory-Mapped I/O (MMIO) register that an attacker can read to dump the key. Instead, the AES engine operates as a black box:
- Input: The Boot ROM writes the encrypted ciphertext (the LLB payload) into the AES engine’s input FIFO.
- Control: The Boot ROM sets a specific control bit in the AES configuration register (e.g.,
AES_CMD_USE_GID). - Operation: The hardware AES engine loads the GID key from the fuses directly into the crypto core, performs the decryption, and flushes the key from the internal registers.
- Output: The plaintext is written to the output FIFO, which the Boot ROM then reads into SRAM.
This architecture ensures that even if an attacker gains arbitrary code execution within the Boot ROM (as seen in the checkm8 exploit on older A-series chips), they cannot extract the GID key to decrypt firmware images offline. Decryption must happen on-device.
1.1.3 The Public Key Accelerator (PKA): Hardware-Enforced Verification
Decryption provides confidentiality, but not integrity. To prevent the execution of malicious firmware, the Boot ROM enforces strict code signing using the Public Key Accelerator (PKA).
The PKA is a dedicated hardware block optimized for asymmetric cryptography (RSA and ECC). The verification flow is as follows:
- Root of Trust Hash: The SHA-384 hash of the Apple Root CA public key is burned into the device’s eFuses. This is the immutable anchor.
- Manifest Parsing: The Boot ROM parses the Image4 (img4) container of the LLB. It extracts the Image4 Manifest (IM4M), which contains the payload’s signature and the public key used to sign it.
- Key Verification: The Boot ROM hashes the public key found in the manifest and compares it against the hash in the eFuses. If they do not match, the boot halts (DRAM is never initialized, and the device enters DFU mode).
- Signature Verification: The Boot ROM offloads the signature verification to the PKA. It passes the SHA-384 hash of the payload and the RSA/ECC signature. The PKA performs the mathematical verification and returns a boolean result to a status register.
Fault Injection Hardening:
Modern Apple Boot ROMs employ glitch-resistant logic around the PKA check. Rather than a simple B.EQ (Branch if Equal) instruction following the PKA result—which could be bypassed via voltage glitching—the code often employs redundant checks, loop invariants, or specific register values that must be populated by the PKA hardware itself to allow the boot flow to proceed.
1.1.4 RE Focus: Dev vs. Prod Fused Silicon
For the reverse engineer, distinguishing between Development (Dev) and Production (Prod) fused silicon is vital. The behavior of the Boot ROM changes fundamentally based on the “Security Domain” fuse.
-
Production (CPFM 01): The standard consumer state. JTAG is physically disabled. The GID key is locked to the production value. The Boot ROM enforces the full Apple Root CA chain.
-
Development (CPFM 00/03): Used internally by Apple engineers.
-
JTAG Enablement: The
DBGENsignal is asserted, allowing hardware debuggers (like Lauterbach or Astris) to halt the core immediately after reset. -
Demotion: Dev-fused chips often allow “demotion,” enabling the device to boot unsigned or custom-signed firmware images.
-
GID Key Variance: Dev chips often use a different GID key, meaning firmware encrypted for Prod devices cannot be decrypted on Dev hardware, and vice versa.
Identifying Silicon State:
You can identify the fuse status by querying the CHIP_ID or MOJO registers via USB when the device is in DFU mode.
0x8000...usually indicates a Production fuse.0x0000...or specific bitmasks in theECIDresponse indicate Development/Debug fusing.
The “Un-dumpable” Region: Once the Boot ROM prepares to jump to the next stage (LLB), it performs a lockdown sequence. It writes to the memory controller to unmap its own address range (
0x100000000). Any subsequent attempt by the LLB or Kernel to read the Boot ROM address space will result in a bus error or read back zeros. This “hide-and-seek” mechanism is why dumping the Boot ROM requires a vulnerability present during the Boot ROM execution window (likecheckm8or a voltage glitch at reset).
1.2 Proprietary ISA Extensions (arm64e+)
While the M-series chips ostensibly implement the ARMv8.6-A (and increasingly ARMv9) specification, Apple has aggressively extended the Instruction Set Architecture (ISA) with proprietary logic. For the reverse engineer, standard ARM documentation is insufficient. Understanding the security posture of macOS Tahoe requires mastering these custom extensions, as they form the hardware enforcement layer for the new kernel isolation model.
1.2.1 Pointer Authentication (PAC): The Cryptographic Control Flow
Apple’s implementation of ARMv8.3-PAuth is the most pervasive security mitigation in the XNU kernel. It repurposes the unused high-order bits of 64-bit virtual addresses (typically bits 63–47, depending on Translation Control Register TCR_EL1 settings) to store a cryptographic signature, or Pointer Authentication Code (PAC).
The Key Hierarchy: The hardware maintains five distinct 128-bit keys in system registers, accessible only at EL1 or higher. These keys segregate pointer types to limit the utility of a signing gadget:
APIAKey/APIBKey(Instruction): Signs code pointers (function pointers, return addresses).APDAKey/APDBKey(Data): Signs data pointers. Crucial for protecting C++ vtables in IOKit (OSObject).APGAKey(Generic): Signs arbitrary data blobs, effectively a hardware-accelerated MAC.
The AUT Failure Mechanism (Canonical Non-Valid):
For the reverse engineer analyzing crash dumps, understanding the failure mode is critical. When an AUT* instruction (e.g., AUTIA) is executed on a corrupted or forged pointer, the CPU does not immediately raise an exception.
Instead, the hardware corrupts the pointer in a deterministic way to ensure it causes a translation fault upon dereference.
- Validation: The CPU recalculates the PAC.
- Mismatch: If the calculated PAC does not match the bits in the pointer, the CPU flips specific high-order bits (typically bit 62 for data pointers, or bit 61 for instruction pointers, depending on Top Byte Ignore settings).
- Result: The pointer becomes “canonical non-valid.” It looks like a kernel pointer (high address) but falls into a reserved, unmapped range.
- Crash: The subsequent
LDRorBLRtriggers a Data Abort or Prefetch Abort.
RE Tip: If you see a crash where
x0is0x007f...or0x00ff...(a pointer with high bits set but not fully canonical), you are looking at a PAC authentication failure, not a standard NULL dereference or heap corruption.
1.2.2 Branch Target Identification (BTI): The Landing Pads
Often deployed in tandem with PAC (-mbranch-protection=standard), BTI mitigates Jump-Oriented Programming (JOP). It enforces a state machine on indirect branches.
- Marking Pages: The Global Page Table (GPT) or PTE entries now include a Guarded Page (
GP) bit. - The
BTIInstruction: This is a “hint” instruction (NOP on older silicon). It acts as a valid landing pad. - Enforcement: When the CPU executes an indirect branch (
BR,BLR) targeting a Guarded Page, the very next instruction must be aBTIinstruction of the correct type (cfor call,jfor jump,jcfor both).
If the target is not a BTI instruction, the CPU raises a Branch Target Exception. In XNU, this manifests as a SIGILL with a specific subcode. For exploit development, this necessitates finding gadgets that not only perform the desired operation but are also preceded by a valid landing pad.
1.2.3 New in Tahoe: The Guarded Execution Feature (GXF)
This is the most significant architectural divergence in the Apple Silicon era. Standard ARM defines a vertical privilege stack (EL0 -> EL1 -> EL2). Apple has introduced Lateral Exception Levels, referred to as Guarded Levels (GL).
GXF allows the processor to switch between execution modes that share the same architectural Exception Level (EL1) but possess vastly different hardware permissions and system register views.
- GL0: The standard XNU Kernel context.
- GL1: The Trusted Execution Monitor (TXM) context.
- GL2: The Secure Page Table Monitor (SPTM) context.
The Proprietary Opcodes:
Transitions are not handled by HVC or SMC. Apple added custom instructions to the ISA:
GENTER(Opcode0x00201420): Synchronous entry into a Guarded Level. It behaves like a function call but atomically switches the hardware context (SPRR state, stack pointer, and system registers).GEXIT(Opcode0x00201400): Returns from GL to the caller.
Reverse Engineering the Transition:
In disassembly, GENTER takes a dispatch ID (selector) in x15 and arguments in x0-x7. The entry point for the transition is hardcoded in the proprietary system register GXF_ENTRY_EL1 (S3_6_C15_C8_2). This register is locked early in the boot process (by iBoot), preventing the kernel from hijacking the monitor’s entry vector.
1.2.4 New in Tahoe: Shadow Permission Remapping Registers (SPRR)
To enforce isolation between GL0, GL1, and GL2, Apple replaced the older APRR (Access Permission Remapping Registers) with the more robust SPRR (Shadow Permission Remapping Registers).
In standard ARM MMUs, the Page Table Entry (PTE) bits AP[2:1] directly define Read/Write permissions. In Apple Silicon with SPRR enabled, these bits are repurposed as an index into a hardware permission table.
The Indirection Layer:
- PTE Index: The PTE specifies a permission index (e.g., Index 5).
- Context Lookup: The hardware checks the current execution mode (GL0, GL1, or GL2).
- Resolution: It looks up Index 5 in the
SPRR_PERM_EL1register specific to that mode.
The Security Implication: This allows for “View-Based” memory protection.
- Index 5 in GL2 (SPTM): Resolves to Read-Write (RW).
- Index 5 in GL0 (Kernel): Resolves to Read-Only (RO).
This is how the SPTM protects page tables. The physical pages containing the translation tables are marked with a specific SPRR index. The hardware configuration for GL0 (Kernel) maps that index to Read-Only. Even if an attacker has a kernel-level arbitrary write primitive, the MMU will reject the write to the page table because the SPRR configuration for GL0 forbids it. The only way to write to that page is to execute GENTER to switch to GL2, where the SPRR configuration permits the write.
2.0 The Secure Enclave Processor (SEP): The Parallel Computer
If the Application Processor (AP) is the brain of the device, the Secure Enclave Processor (SEP) is its conscience. It is not merely a coprocessor; it is a fully independent computer-on-a-chip, sharing the same die but architecturally severed from the AP. It runs its own kernel (an Apple-customized L4 microkernel), manages its own peripherals, and holds the keys to the kingdom (UID/GID). In the Tahoe architecture, the SEP’s role has expanded from simple key management to becoming the root of authority for biometric intent and hardware attestation.
2.1 SEP Initialization & Boot
The SEP boot process is designed to be resilient against a fully compromised Application Processor. From the moment power is applied, the SEP assumes the AP is hostile.
2.1.1 The SEPROM: SRAM Execution and the Memory Protection Engine (MPE)
Like the AP, the SEP begins execution from an immutable on-die Boot ROM, the SEPROM.
The Hardware Environment: The SEP core (typically a customized ARM core, historically evolving from Cortex-A7 derivatives) initializes in a highly constrained environment. It does not initially have access to the system’s main DRAM. Instead, it executes strictly within a dedicated, on-die SRAM region. This isolation prevents early-boot DMA attacks from the AP or Thunderbolt peripherals.
The Memory Protection Engine (MPE):
As the sepOS is too large to fit entirely in SRAM, it must eventually reside in the device’s main DRAM (Unified Memory on M-series). To do this securely, the SEP utilizes a hardware Memory Protection Engine (MPE).
The MPE sits inline between the SEP core and the memory controller. It creates a cryptographic window into physical memory that is opaque to the rest of the SoC.
- Ephemeral Keys: Upon SEP reset, the MPE generates a random, ephemeral AES key. This key exists only in the MPE hardware registers and is never exposed to software (even
sepOS). - AES-XEX Encryption: Data written by the SEP to DRAM is encrypted transparently using AES in XEX (XOR-Encrypt-XOR) mode.
- Authentication: The MPE calculates a CMAC tag for every cache line. This tag is stored alongside the encrypted data.
RE Implication: If you attempt to dump the physical memory range assigned to the SEP from the AP (kernel mode), you will see high-entropy noise. Furthermore, any attempt to modify a single bit of this memory via the AP will invalidate the CMAC tag. The next time the SEP reads that line, the MPE will detect the forgery and trigger a hardware panic, locking down the Enclave until a full system reset.
2.1.2 The Boot Monitor: Hardware Enforcement of OS-Bound Keys
On modern silicon (A13/M1 and later), Apple introduced the Secure Enclave Boot Monitor to mitigate the risk of Boot ROM exploits (like checkm8) compromising the chain of trust for key derivation.
In older architectures, the SEPROM would verify the sepOS signature and then jump to it. If the SEPROM was exploited, the attacker could jump to a malicious payload while retaining access to the hardware UID key. The Boot Monitor closes this gap by enforcing System Coprocessor Integrity Protection (SCIP).
The Boot Flow:
- Payload Staging: The AP (iBoot) loads the
sep-firmware.img4payload into a region of physical memory. - Mailbox Signal: The AP signals the SEP via a hardware mailbox register.
- Verification: The SEPROM parses the Image4 container. It verifies the signature against the Apple Root CA hash fused into the SEP’s eFuses.
- The Handoff: Crucially, the SEPROM cannot simply jump to the loaded image. The SCIP hardware prevents execution of mutable memory.
- Monitor Intervention: The SEPROM invokes the Boot Monitor hardware block.
- The Monitor resets the SEP core to a known clean state.
- The Monitor calculates a cryptographic hash of the loaded
sepOSmemory range. - The Monitor updates the SCIP registers to permit execution of that specific range.
- The Monitor locks the hash into a dedicated register in the Public Key Accelerator (PKA).
OS-Bound Key Derivation:
This finalized hash is the critical component. When the sepOS later requests keys (e.g., to decrypt user data), the hardware Key Derivation Function (KDF) mixes the hardware UID with this locked hash.
$$ K_{derived} = KDF(UID, Hash_{sepOS}) $$
If an attacker modifies a single byte of the sepOS (even with a Boot ROM exploit), the Boot Monitor calculates a different hash. Consequently, the KDF derives a different key, and the encrypted user data remains mathematically inaccessible. This is “Bound Security”—the data is bound not just to the device, but to a specific, signed software version.
2.1.3 Anti-Replay Mechanisms: The Integrity Tree
A classic attack vector against secure enclaves is the Replay Attack: capturing a snapshot of the encrypted RAM (e.g., when the passcode retry counter is 0) and restoring it later after the counter has incremented.
To prevent this, the SEP implements a hardware-enforced Integrity Tree (Merkle Tree).
- The Root of Trust: The root node of the integrity tree is stored in dedicated on-chip SRAM within the Secure Enclave complex. This memory is physically distinct from the main DRAM and cannot be addressed by the AP.
- Tree Structure: The protected memory region (where
sepOSdata and the Secure Storage Manager reside) is divided into blocks. Each block’s hash is stored in a parent node, recursively up to the root. - Atomic Updates: When the SEP writes to protected memory (e.g., incrementing a failed attempt counter), the MPE updates the data, recalculates the hashes up the tree, and atomically updates the root hash in the on-chip SRAM.
- Verification: On every read, the MPE verifies the path from the data block up to the SRAM root.
If an attacker replays an old DRAM state, the hash of the replayed block will not match the current root hash stored in the internal SRAM. The MPE detects the mismatch (Anti-Replay Violation) and halts the SEP. This mechanism ensures that the SEP has a strictly monotonic view of time and state, rendering snapshot fuzzing and counter rollbacks impossible.
2.2 SEP Runtime Architecture
Once the sepOS is bootstrapped and verified, the Secure Enclave transitions into its runtime state. At this point, it functions as a fully autonomous operating system running an Apple-customized variant of the L4 microkernel. For the reverse engineer, understanding the runtime architecture is crucial for analyzing how the SEP communicates with the hostile “Rich Execution Environment” (the AP running XNU) and how it persists sensitive state.
2.2.1 The Mailbox Interface: Analyzing the Shared Memory IPC
Communication between the Application Processor (AP) and the SEP is strictly asynchronous and interrupt-driven. Unlike the tight coupling of the SPTM (which uses synchronous instruction traps), the SEP interaction is mediated by a hardware mechanism known as the Mailbox, which relies on the proprietary Apple Interrupt Controller (AIC) to manage signaling.
The Physical Transport: AIC and Ring Buffers There is no shared virtual memory space; the two processors exchange messages via physical memory ring buffers and hardware interrupts.
The Ring Buffers (Inbox/Outbox):
The system reserves two physical memory regions in DRAM, carved out by iBoot and described in the Device Tree (typically under the sep node as inbox-size and outbox-size). These function as circular buffers.
- Control Structures: Each buffer is managed by a pair of pointers (Write Head, Read Tail) stored in shared SRAM or at the start of the DRAM region.
- Coherency: Because the SEP and AP share the same Unified Memory fabric, cache coherency is critical. The
AppleSEPDrivermust ensure appropriate barriers (DMB,DSB) are used when updating the Write Head to ensure the SEP sees the payload before the interrupt fires.
The Doorbell (Apple Interrupt Controller): To signal a message, the sender cannot simply write to memory; it must trigger an exception on the receiver. On Apple Silicon, this is handled by the AIC, not a standard ARM GIC.
- AP $\rightarrow$ SEP: The kernel writes to a specific AIC “Set” register (mapped in the AP’s MMIO space). This asserts a hardware IRQ line wired to the SEP’s core.
- SEP $\rightarrow$ AP: When the SEP replies, it writes to its own AIC interface, which triggers a specific IRQ (often
IRQ 0orIRQ 1relative to the SEP driver’s view) on the AP. The kernel’s interrupt handler (AppleSEPDriver::interruptOccurred) acknowledges this by writing to the AIC “Clear” register.
The L4 IPC Protocol (A7IOP): The data payload within the ring buffers follows a serialized format, historically referred to as the Apple A7 I/O Protocol (A7IOP), though it has evolved significantly.
-
Message Header: Every message begins with a 64-bit header containing:
-
Endpoint ID(8 bits): The destination service within thesepOS(e.g.,0x10for Biometrics,0x14for Secure Storage). -
Tag(8 bits): A transaction ID used to correlate asynchronous replies. -
Length(16 bits): The size of the payload. -
The
AppleSEPDriver: On the XNU side, this kext manages the ring buffer logic. It serializes kernel requests (e.g., “Unlock Keybag”) into the mailbox format, updates the Write Head, rings the AIC doorbell, and sleeps the calling thread on a condition variable until the SEP triggers the reply interrupt.
RE Focus: Fuzzing the Boundary The mailbox is the primary attack surface for the SEP. Vulnerabilities here (parsing malformed messages) can lead to code execution within the Enclave.
-
Endpoint Fuzzing: The
sepOSkernel dispatches messages to user-mode L4 tasks based on the Endpoint ID. Fuzzing specific endpoints (especially legacy or debug endpoints left enabled in production) is a standard methodology. -
Shared Memory Hazards (DART): While the mailbox buffers are used for control messages (metadata), bulk data (like a firmware update or a large biometric template) is passed via DART-mapped shared memory. The AP maps a page, pins it, and passes the physical address to the SEP in a mailbox message. The SEP then maps this page into its own address space.
-
TOCTOU: Race conditions here are a classic target: modifying the data in the shared buffer after the SEP has validated the header/signature but before it processes the body. The SEP attempts to mitigate this by copying data to internal SRAM before processing, but large payloads may be processed in-place, exposing a window of opportunity.
2.2.2 The Secure Storage Component (xART): Encrypted Persistent Storage
The SEP has no internal non-volatile storage (NAND) of its own. It must rely on the AP’s NAND flash to store persistent data (like the user’s passcode hash, biometric templates, and credit card tokens). However, it cannot trust the AP to store this data securely.
To solve this, Apple introduced the Secure Storage Component, often referred to in firmware and kexts as xART (eXtended Anti-Replay Technology).
The Architecture:
- The Physical Chip: On modern devices, xART is backed by a dedicated, tamper-resistant EEPROM or NOR flash chip physically connected to the SEP via a private I2C or SPI bus. This chip is not accessible to the AP.
- The Logical Volume: The SEP treats the external NAND (managed by the AP) as a “dumb” block device. It encrypts its filesystem using keys derived from the hardware UID and the anti-replay counters stored in the dedicated xART chip.
The Anti-Replay Guarantee: When the SEP writes a file (e.g., updating the failed passcode attempt counter):
- It encrypts the file data.
- It generates a new random nonce or increments a counter.
- It writes the encrypted file to the AP’s filesystem (via the Mailbox).
- Crucially, it writes the hash of the file and the new counter to the dedicated xART storage chip.
When reading the file back:
- The SEP requests the file from the AP.
- It reads the expected hash/counter from the xART chip.
- It verifies the file against the xART record.
If the AP (or an attacker with physical access to the NAND) tries to revert the file to an older version (e.g., resetting the counter to 0), the hash will not match the record in the xART chip. The SEP will detect the rollback and reject the data. This mechanism ensures that the SEP’s state is strictly monotonic and immune to external storage manipulation.
2.2.3 RE Focus: Reverse Engineering the sepOS L4 Syscall Table
For the advanced reverse engineer, the holy grail is understanding the sepOS kernel itself. Since it is based on L4, it relies heavily on synchronous IPC for system calls.
Identifying the Syscall Handler:
In the disassembled sepOS binary (which can be decrypted if you have a Boot ROM exploit for the specific device class, or by analyzing unencrypted development builds if available), the exception vector table is the starting point.
- Look for the SVC (Supervisor Call) exception handler.
- This handler typically branches to a dispatch table based on the immediate value in the
SVCinstruction or a register (oftenx0orx8).
Mapping the Endpoints:
The sepOS is modular. It consists of the kernel and several user-mode “apps” or “tasks” running within the Enclave.
-
SEPOSKernel: Handles memory management, scheduling, and IPC routing. -
L4Apps: Distinct binaries for distinct functions. -
biometrickitd: Handles FaceID/TouchID processing. -
securekeyvault: Manages the Keychain and Data Protection classes. -
sigp: The Secure Enclave Signal Processor (for neural network operations).
By tracing the IPC messages dispatched from the Mailbox handler, you can map which L4 task handles which service. For example, a message with Endpoint ID 0x10 might route to the biometrickitd task. Analyzing the message parsing logic within that specific task reveals the proprietary protocol used for biometric authentication.
Tooling Note: Standard tools like IDA Pro or Ghidra require custom loaders for
sepOSbinaries. The memory layout is non-standard, and the binary format (Mach-O) often has stripped headers or non-standard segment protections that must be manually reconstructed based on the SCIP configuration found in the Boot Monitor logic.
3.0 The Chain of Trust: Firmware & Bootloaders
With the hardware root of trust established and the Secure Enclave operating as a parallel authority, the Application Processor begins the process of bootstrapping the mutable software stack. This phase is governed by the Image4 serialization format and a strict chain of cryptographic handover.
3.1 Low-Level Bootloader (LLB)
The Low-Level Bootloader (LLB) is the first piece of mutable code executed by the Application Processor. Loaded by the Boot ROM from the boot partition of the NAND (or NOR SPI on some development boards), it executes initially within the constraints of the SoC’s SRAM. Its primary directive is architectural: it must bridge the gap between the raw silicon state and the feature-rich environment required by iBoot.
3.1.1 Parsing the Image4 (img4) Container
To the reverse engineer, “firmware” on Apple Silicon is synonymous with Image4. LLB is not a raw binary; it is encapsulated in an Image4 container, a format based on ASN.1 (Abstract Syntax Notation One) and DER (Distinguished Encoding Rules). Understanding this structure is prerequisite to any firmware analysis.
The Image4 container consists of three distinct sequences:
IM4P (Payload): The actual executable code (the LLB binary).
- Encryption: The payload is encrypted using AES-256. On production devices, this is wrapped with the GID Key. This means the payload is opaque to external analysis unless decrypted on-device (or via a GID oracle).
- Compression: Once decrypted, the payload is typically compressed (LZSS or LZFSE).
- Type Tag: A 4-character code (e.g.,
ibot,illb) identifying the component.
IM4M (Manifest): The signature and constraints, commonly known as the ApTicket.
- The Signature: An RSA or ECDSA signature over the SHA-384 hash of the payload.
- The Body: A set of entitlements and constraints (tags) that dictate where and how this payload can run.
- Certificate Chain: The manifest includes the certificate chain leading back to the Apple Root CA (burned into the PKA fuses).
IM4R (Restore Info): (Optional) Contains hardware-specific personalization data used during the restore process, such as the unique nonce generated by the SEP.
The Validation Logic:
When the Boot ROM loads LLB (and when LLB subsequently loads iBoot), it performs the following image4_validate routine:
- Parse the ASN.1 structure to separate
IM4MandIM4P. - Hash the
IM4P(ciphertext). - Locate the corresponding hash in the
IM4M(under the specific tag, e.g.,illb). - Verify the
IM4Msignature using the PKA. - If valid, decrypt the
IM4Pusing the AES engine (GID context).
3.1.2 DRAM Training and Memory Controller Configuration
The most critical hardware initialization task performed by LLB is DRAM Training.
When LLB starts, the system is running on internal SRAM (a few megabytes at most). The external LPDDR4X/LPDDR5 Unified Memory is inaccessible because the Memory Controller (MCU) is uninitialized. The physical characteristics of RAM—signal timing, voltage margins, and skew—vary slightly between every physical device due to manufacturing tolerances.
The Training Sequence:
- Reading SPD/Calibration Data: LLB reads calibration data from the device tree or dedicated EEPROM areas.
- PHY Configuration: It configures the Physical Layer (PHY) interface of the memory controller.
- Training Loop: LLB executes a complex algorithm that writes patterns to DRAM and reads them back, adjusting delay lines (DLLs) and drive strengths until the signal is stable.
- Remapping: Once training is complete, the MCU is brought online. LLB then reconfigures the Memory Management Unit (MMU) to map the vast expanse of DRAM into the address space.
RE Implication: If you are attempting to exploit the Boot ROM or early LLB, you are constrained to SRAM. You cannot load large payloads or use heap spraying techniques that require gigabytes of memory until after LLB has successfully trained the DRAM. This creates a “choke point” for early-boot exploits.
3.1.3 Verifying the Exclusive Chip ID (ECID) and Board ID
Apple utilizes a mechanism called Personalization (or Taming) to prevent firmware replay attacks. You cannot simply take a valid, signed LLB from one iPhone and run it on another, nor can you downgrade to an older, vulnerable LLB version.
This enforcement happens inside the Image4 parser logic within LLB (checking the next stage) and the Boot ROM (checking LLB).
The Constraint Tags:
The IM4M manifest contains specific tags that bind the signature to the hardware:
ECID(Exclusive Chip ID): A 64-bit unique integer derived from the silicon die’s coordinates on the wafer.BORD(Board ID): Identifies the PCB model (e.g.,0x10for a specific iPhone logic board).CHIP(Chip ID): Identifies the SoC model (e.g.,0x8101for M1).SDOM(Security Domain):0x1for Production,0x0for Development.
The Check:
During boot, the executing code reads the actual values from the hardware fuses and compares them against the values present in the signed IM4M.
- If
Hardware.ECID != Manifest.ECID, the boot halts. - If
Hardware.BORD != Manifest.BORD, the boot halts.
This mechanism, combined with the Nonce (a random value generated by the SEP during updates and baked into the IM4M), ensures that the firmware is:
- Authentic: Signed by Apple.
- Targeted: Valid only for this specific device.
- Fresh: Valid only for this specific boot/update cycle (preventing downgrades).
Note: In the “Tahoe” architecture, this verification logic is hardened against fault injection. The comparison is often performed using redundant variables and bitwise checks that resist simple instruction skipping (e.g., glitching a
B.NEinstruction).
3.2 iBoot (Stage 2 Bootloader)
Once LLB has initialized the DRAM and verified the next stage, it hands off execution to iBoot. While LLB is a hardware-focused shim, iBoot is a sophisticated, single-threaded operating system in its own right. It contains a full USB stack, a display driver (for the Apple logo), a filesystem driver (APFS/HFS+), and the logic required to bootstrap the XNU kernel. In the Tahoe architecture, iBoot’s role has expanded to become the orchestrator of the new security domains.
3.2.1 Device Tree (DT) Flattening
The hardware configuration of an Apple Silicon device is not discoverable via standard buses like PCI enumeration alone. Instead, iBoot relies on a Device Tree (DT)—a hierarchical data structure (similar to OpenFirmware or Linux FDT) that describes the SoC’s topology.
The Source:
The raw Device Tree is embedded within the iBoot binary (or loaded as a separate devicetree.img4 payload). It contains nodes describing CPUs, memory maps, interrupt controllers (AIC), and peripherals.
The Flattening Process:
Before jumping to the kernel, iBoot “flattens” this tree into a binary format (FDT) and populates the /chosen node with runtime parameters.
kaslr-seed: A high-entropy random value generated by the TRNG. The kernel uses this to randomize its slide.memory-map: A critical array of structures defining physical memory regions. iBoot marks regions used by the Boot ROM, LLB, and itself as reserved, ensuring the kernel does not overwrite them.boot-args: The command-line arguments passed to the kernel (e.g.,debug=0x14e,-v). On production devices, these are strictly filtered; only specific flags are allowed unless the device is “demoted” or in a specific research state.
3.2.2 New in Tahoe: Loading the Security Monitors
In pre-Tahoe architectures (iOS 14 / macOS 11), iBoot would simply load the kernelcache and jump to it. In the Tahoe era (A15/M2+), iBoot must construct the Guarded Execution Environment before the kernel can exist.
Allocation and Reservation: iBoot parses the device tree to identify physical memory ranges reserved for the new monitors. It carves these out of the available DRAM:
- SPTM Region: Reserved for the Secure Page Table Monitor.
- TXM Region: Reserved for the Trusted Execution Monitor.
Payload Loading: iBoot locates the specific Image4 payloads within the kernelcache container:
Ap,SecurePageTableMonitor: The GL2 binary.Ap,TrustedExecutionMonitor: The GL1 binary.
It decrypts and verifies these payloads just like any other firmware component. However, instead of loading them into standard memory, it loads them into the reserved physical regions identified above.
Locking SPRR Regions: This is the critical security pivot. Before handing off control, iBoot configures the Shadow Permission Remapping Registers (SPRR) for the initial state.
- It configures the GL2 (SPTM) SPRR view to have Read/Write/Execute access to its own memory region.
- It configures the GL1 (TXM) SPRR view to have access to its region.
- Crucially, it configures the GL0 (Kernel) SPRR view to mark the SPTM and TXM regions as Inaccessible (No-Access).
This ensures that when the processor eventually drops to EL1 (GL0) to run XNU, the kernel is physically incapable of reading or modifying the monitor code, even though it resides in the same physical DRAM.
3.2.3 LocalPolicy & BAA: The Shift to Local Signing
For macOS, Apple introduced a mechanism to allow users to boot older OS versions or custom kernels (Permissive Security) without breaking the hardware chain of trust. This is managed via LocalPolicy.
The Problem: The Boot ROM and LLB enforce strict signature checks against Apple’s global signing server (TSS). If you want to boot a custom kernel, you can’t get a valid signature from Apple.
The Solution:
- LocalPolicy: A policy file stored on the Data Volume (in the
iSCPrebootvolume). It specifies the security mode (Full, Reduced, Permissive) and the hash of the custom kernel collection. - BAA (Basic Attestation Authority): When a user authorizes a downgrade (via Recovery Mode authentication), the Secure Enclave generates a Local Signing Key.
- Re-Signing: The LocalPolicy is signed by this Local Key (inside the SEP).
- Boot Time: iBoot fetches the LocalPolicy. It asks the SEP to verify the signature. If the SEP confirms the policy is valid (and matches the user’s intent), iBoot proceeds to load the custom kernel hash specified in the policy, effectively “blessing” it for this boot cycle.
This allows “Permissive Security” to exist while keeping the Boot ROM and LLB strictly locked down.
3.2.4 RE Focus: Decrypting iBoot Payloads via the AES MMIO Interface
To analyze iBoot, one must decrypt it. Since the GID key is fused into the silicon and physically disconnected from the CPU’s register file, it cannot be extracted via software. Reverse engineers must instead turn the device into a Decryption Oracle by manipulating the dedicated AES hardware peripheral.
The kbag Mechanism:
The Image4 payload (IM4P) is encrypted with a random, per-file symmetric key (the target key). This target key is wrapped (encrypted) with the GID key and stored in the IM4P header as a Keybag (kbag). To decrypt the firmware, one must unwrap this kbag.
The Hardware Distinction (ISA vs. MMIO):
It is critical to distinguish between the ARMv8 Crypto Extensions (instructions like AESE, AESD) and the Apple AES Peripheral.
- ARMv8 Crypto: Operates on keys loaded into standard NEON/SIMD registers (
v0-v31). Useful for TLS or disk encryption where the key is known to the OS. - Apple AES Peripheral: A memory-mapped I/O (MMIO) block, typically located at a base offset like
0x23D2C0000(on M1/T8103) or similar0x2...ranges on newer SoCs. This peripheral has exclusive hardware access to the GID key fuses.
The Oracle Exploit:
Using a Boot ROM exploit (like checkm8 on A-series) or a specialized iBoot exploit, researchers execute a payload that drives this MMIO interface directly:
- Reset: Reset the AES peripheral via the
AES_CTRLregister to clear internal state. - Key Selection: Write to the configuration register to select the GID Key as the decryption source. This sets an internal mux; the key itself is never exposed to the bus.
- FIFO Loading: Write the
kbag(IV + Ciphertext) into theAES_DATA_INFIFO registers. - Execution: Trigger the engine. The hardware pulls the GID key from the fuses, performs the AES-256-CBC unwrap, and pushes the result to the output buffer.
- Extraction: Read the unwrapped target key (typically formatted as
iv:key) from theAES_DATA_OUTregister.
Bit-Flipping and Timing Countermeasures: Modern Apple Silicon (A12+/M1+) implements countermeasures against this oracle usage. The AES engine may enforce a state machine that requires the output of a GID decryption to be immediately DMA’d to executable memory and jumped to, rather than read back into a general-purpose register. Bypassing this often requires Fault Injection (voltage glitching) to corrupt the state machine or precise timing attacks to race the hardware’s “sanitize on read” logic, allowing the extraction of the plaintext key before the hardware scrubs it.
4.0 The Security Monitor Layer (GL1/GL2): The New Hypervisor
In the “Tahoe” architecture, the XNU kernel has been demoted. It no longer possesses the ultimate authority to define the virtual memory layout of the system. That power has been migrated to a hardware-enforced monitor running in a proprietary execution state. This section dissects the mechanics of this new layer, which effectively functions as a lightweight, silicon-enforced hypervisor for the kernel itself.
4.1 The Secure Page Table Monitor (SPTM) - GL2
The Secure Page Table Monitor (SPTM) operates at Guarded Level 2 (GL2). While architecturally sharing the EL1 exception level with the kernel, the Guarded Execution Feature (GXF) ensures that GL2 has a strict superset of permissions compared to the kernel’s GL0. The SPTM is the sole entity permitted to write to the physical pages that constitute the translation tables (TTBR0/TTBR1).
4.1.1 The GENTER and GEXIT Instructions: Context Switching
Transitions into the SPTM are not handled by standard ARM exception vectors (VBAR_EL1). Instead, they utilize the proprietary GENTER instruction, which performs a synchronous, atomic context switch.
The GENTER ABI:
To invoke the SPTM, the kernel populates specific registers and executes the opcode.
- Opcode:
0x00201420(Little Endian). x15(Selector): The Dispatch ID. This integer identifies which SPTM primitive to execute.x0-x7(Arguments): The parameters for the call (e.g., physical addresses, permission flags).x16/x17: Often used as scratch or secondary dispatch modifiers in newer revisions.
The Hardware Transition:
Upon execution of GENTER:
- SPRR Switch: The hardware swaps the active Shadow Permission Remapping Register configuration. The memory regions containing the SPTM code and data—previously invisible to the kernel—become Read/Write/Execute. Conversely, the kernel’s own text might become Read-Only or Non-Executable depending on the monitor’s logic.
- Stack Switch: The Stack Pointer (
SP) is switched to theSP_GL2register, pointing to a dedicated secure stack within the SPTM’s private memory. - PC Jump: Execution jumps to the vector defined in
GXF_ENTRY_EL1.
The Return:
The SPTM returns control to the kernel using GEXIT (0x00201400). This restores the GL0 SPRR configuration and the kernel’s stack pointer. Crucially, GEXIT clears sensitive registers to prevent data leakage from the secure context.
4.1.2 The Frame Table (FTE): Tracking Physical Reality
To enforce security, the SPTM cannot rely on the kernel’s data structures (like vm_page_t), as they are mutable by a compromised kernel. Instead, the SPTM maintains its own “God View” of physical memory called the Frame Table.
The Frame Table is a linear array of Frame Table Entries (FTE), located in SPTM-private memory. There is one FTE for every 16KB page of physical RAM.
FTE Structure (Reconstructed): While the exact struct evolves, it generally contains:
-
Type(Bitfield): The strict classification of the page. -
XNU_DATA: Generic kernel heap/stack. -
XNU_TEXT: Immutable kernel code. -
PAGE_TABLE: A page containing translation entries (TTEs). -
USER_DATA: Memory mapped to EL0 processes. -
SPTM_PRIVATE: Internal monitor structures. -
Refcount: Tracks how many virtual mappings point to this physical page. -
OwnerID: Identifies the Trust Domain (e.g., Kernel vs. Exclave).
The Security Invariant:
The SPTM enforces that a physical page can only be mapped into a virtual address space if the mapping permissions are compatible with the page’s Type. For example, a page marked XNU_DATA in the FTE cannot be mapped as Executable. A page marked PAGE_TABLE cannot be mapped as Writable by the kernel.
4.1.3 The Dispatch Table: Reverse Engineering the Selectors
The interface between XNU and the SPTM is a strict, register-based API. However, unlike the stable syscall numbers of the BSD layer, the SPTM Dispatch IDs (Selectors) are not guaranteed to remain static across macOS versions. Apple frequently rotates these IDs between major (and occasionally minor) releases to frustrate static analysis tools and exploit chains that rely on hardcoded offsets.
The ABI:
x15: The Dispatch ID (Selector).x0-x7: Arguments (Physical Addresses, Permission Bitmasks, ASIDs).x16/x17: Scratch registers, occasionally used for secondary modifiers or sub-ops.
Heuristic Identification:
Since relying on static IDs (e.g., 0x00) is brittle, reverse engineers must fingerprint the logic of the handler functions within the Ap,SecurePageTableMonitor binary to identify the primitives.
sptm_retype(ppn, old_type, new_type) (Often ID 0x00 or 0x01):
- Fingerprint: Look for a function that accepts a Physical Page Number (PPN), reads the corresponding Frame Table Entry (FTE), and performs a Sanitization Loop. The SPTM must zero-fill (
bzero) or cache-invalidate the page before transitioning it fromXNU_DATAtoPAGE_TABLEto prevent the kernel from initializing a page table with pre-computed malicious entries. - Logic:
assert(refcount == 0); memset(pa, 0, PAGE_SIZE); fte->type = new_type;
sptm_map(asid, va, ppn, perms):
- Fingerprint: Look for a function that walks the translation tables (reading physical memory) and performs a Permission Check against the FTE. It will contain logic that explicitly compares the requested
perms(e.g., Write) against thefte->type(e.g.,XNU_TEXT). - Logic:
if (fte->type == XNU_TEXT && (perms & WRITE)) panic(); write_tte(...);
sptm_unmap(asid, va):
- Fingerprint: Look for the TLB Invalidation sequence. After clearing a TTE, the SPTM must execute
TLBIinstructions (e.g.,TLBI ASIDE1IS) to ensure the hardware translation lookaside buffer is coherent. The kernel is forbidden from executingTLBIinstructions that affect the secure context; it must delegate this to the SPTM.
sptm_map_iommu(dart_id, context_id, dva, ppn, perms):
- Fingerprint: Look for writes to MMIO regions associated with DART controllers, rather than standard RAM. This function validates that the
ppnis not a protected kernel page before mapping it into a device’s IOVA space.
RE Implication: Automated analysis scripts should not rely on `