Breaking the Sound Barrier: Exploiting CoreAudio via Mach Message Fuzzing
Dillon Franke (Senior Security Engineer · Google)
OffensiveCon 2025 · Day 1 · Main · Briefings
Overview
Dillon Franke of Google developed a coverage-guided fuzzing harness targeting macOS's coreaudiod daemon via its Mach IPC interface, introducing a technique called "API call chaining" to guide stateful fuzzing past initialization barriers. The research produced two memory-corruption vulnerabilities — a type confusion and a double-free — in the CoreAudio framework, with the type confusion turned into a working sandbox escape on modern macOS. ---

Key moments
- 3:41 Knowledge-driven fuzzing: monitor coverage plateaus to identify violated initialization assumptions
- 9:05 Sandbox .sb profile analysis maps Mach services reachable from Safari GPU process to coreaudiod
- 10:25 CoreAudio framework is entirely closed-source; extracted from dyld shared cache via IDA Pro
- 11:43 Direct in-process harness enables coverage instrumentation; interprocess send cannot instrument
- 15:21 MIG subsystem structures in binary map ~60 handler functions as fuzzable RPC-style attack surface
- 20:42 API call chaining: replay prerequisite state setup before fuzzing to reach deep stateful handlers
- 26:56 Type confusion in MIG handler corrupts vtable pointer, enabling attacker-controlled virtual dispatch
- 30:26 Double-free in separate handler: type confusion and double-free combined yield macOS sandbox escape
Breaking the Sound Barrier: Exploiting CoreAudio via Mach Message Fuzzing
Speaker: Dillon Franke (Google)
Conference: OffensiveCon 2025 — May 16–17, 2025, Berlin
YouTube: https://www.youtube.com/watch?v=USQtPedx9Xg
Reading time: ~10 minutes
TL;DR
Dillon Franke of Google developed a coverage-guided fuzzing harness targeting macOS's coreaudiod daemon via its Mach IPC interface, introducing a technique called "API call chaining" to guide stateful fuzzing past initialization barriers. The research produced two memory-corruption vulnerabilities — a type confusion and a double-free — in the CoreAudio framework, with the type confusion turned into a working sandbox escape on modern macOS.
Introduction
macOS's Mach IPC layer has a long history as an attack surface for sandbox escapes and local privilege escalation, but most published research has focused on a narrow set of targets. Dillon Franke, a researcher at Google working as part of his Project Zero 20% time, set out to systematically map the Mach message attack surface reachable from within a browser sandbox, then apply structured fuzzing to the most promising target. The result — a full sandbox escape from the Safari GPU process context — demonstrates both a reproducible methodology for attacking closed-source, stateful system daemons and the power of combining coverage-guided fuzzing with manual reverse engineering. Franke open-sourced the tooling developed during the research, making the methodology directly available to the community.
Mach IPC as a Sandbox Escape Vector
Mach messages are the lowest-level IPC mechanism on macOS, sitting below higher-level abstractions such as XPC. Every process can send messages to the bootstrap server — a special kernel-managed port that brokers connections between named services. System daemons register their Mach services with launchd using plist entries in /Library/LaunchDaemons and /Library/LaunchAgents; any sandbox that permits an allow-mach-lookup for a given service name can reach the daemon implementing it.
Franke's target selection pipeline began by enumerating all Mach services registered on the system, then cross-referencing them against the TinyScheme-format .sb sandbox profiles used by high-value sandboxed processes — Safari's GPU process, Chromium's renderer, Adobe Acrobat, and Microsoft Word. AllowMachLookup entries in those profiles define the universe of daemons reachable from a compromised browser renderer. Jonathan Levin's sandbox_check tooling provides a dynamic complement to static profile analysis. After filtering, coreaudiod emerged as a compelling target: it exposes a complex service called AudioHalD, accepts Mach messages from the Safari GPU process, manages audio hardware with elevated privileges, and its implementing binary — the CoreAudio framework — is entirely closed-source.
▶ Watch: Attack surface enumeration and target selection (8:00)
Reversing a Closed-Source MIG Server
Because macOS Big Sur moved most framework binaries off disk into a dyld shared cache, the CoreAudio framework binary was not directly accessible. Franke extracted it using IDA Pro's built-in dyld cache parser, then located the AudioHalD service registration in the extracted binary.
Message dispatch in coreaudiod is handled via the Mach Interface Generator (MIG), an IDL that abstracts the Mach layer and generates stub code for RPC-style message routing. Grepping the binary for MIG subsystem structures revealed a message lookup table that maps incoming message IDs to handler functions via a subsystem offset. The CoreAudio framework exposes approximately 60 such handler functions, forming a large RPC-like attack surface with diverse parameter types.
Understanding the MIG dispatch path was essential for constructing an effective fuzzing harness. Static analysis in IDA Pro revealed the subsystem structure layout, allowing Franke to identify the entry point at which fuzzer-controlled bytes could be injected directly into the handler dispatch logic.
▶ Watch: MIG reverse engineering and subsystem discovery (14:00)
Building a Direct-Harness Fuzzer with API Call Chaining
Franke considered two harness architectures: an interprocess send that passes messages through the kernel to the live coreaudiod process, and a direct harness that loads the CoreAudio framework in-process and calls the MIG handler functions directly. He chose the direct harness for two decisive reasons: it places the fuzzer and the target in the same process space — enabling coverage instrumentation — and it allows precise crash attribution without relying on cross-process signaling.
The direct approach exposed an initialization problem common to stateful targets. Many CoreAudio handler functions are only reachable after a sequence of prior API calls that establish device state. A fuzzer calling handlers in isolation would fail to reach deeper code paths because prerequisite state was absent, producing artificially low coverage. Franke developed a technique he calls "API call chaining" to address this: the fuzzing harness replays a recorded sequence of legitimate API calls to bring the framework to the desired state before injecting fuzz input. This guided the fuzzer past initialization gates and into the handlers that actually manipulate audio device structures.
The fuzzer used was libFuzzer with coverage feedback. Dynamic instrumentation via DynamoRIO provided block coverage data to drive corpus evolution. The combination of a in-process harness, coverage instrumentation, and API call chaining allowed the fuzzer to explore code paths that were invisible to naive message-send approaches.
▶ Watch: Harness design and API call chaining technique (12:00)
Vulnerability 1: Type Confusion in CoreAudio
The fuzzer surfaced a type confusion vulnerability in one of the MIG handler functions. The handler accepts a message parameter that it treats as a pointer to one type of audio object, but under a specific sequence of message IDs and parameter values, the framework stores a pointer to a different object type in the same field. When the handler subsequently dereferences the field using the original type's virtual dispatch table, the resulting method call operates on memory belonging to the wrong type — a classic type confusion pattern that produces an attacker-controlled virtual function dispatch.
Type confusion vulnerabilities in C++ code are particularly powerful because they allow the attacker to redirect virtual function calls to arbitrary code. On modern macOS the relevant mitigations include Pointer Authentication Codes (PAC) and Control Flow Integrity (CFI), which constrain but do not eliminate exploitation paths from type confusion primitives. Franke worked through these mitigations to construct a working sandbox escape, achieving code execution in the coreaudiod process — which runs with privileges beyond those of the Safari GPU process — from within the sandboxed context.
Vulnerability 2: Double-Free in CoreAudio
A second, independent crash surfaced during fuzzing: a double-free in a different handler function. The framework allocates a buffer to hold an audio property value, returns a pointer to it via the Mach reply message, and later frees the same pointer along a separate code path when the device is torn down. If an attacker sends a crafted teardown message before the client has finished using the returned pointer, the free executes twice against the same heap chunk.
Double-free vulnerabilities in malloc-managed heap allocators typically allow heap metadata corruption. On macOS with libmalloc, tcache-style mechanisms introduce some exploitation complexity, but the primitive still provides a meaningful path toward arbitrary write. Franke disclosed both vulnerabilities to Apple, which patched them in a subsequent macOS security update.
Notable Quotes
"I tried to take an approach that I like to refer to as knowledge-driven fuzzing — a blend between automation and manual analysis. As you're fuzzing, you look at the code coverage and say, 'Why is this plateauing? What assumptions have I made that are invalid?'"
— Dillon Franke, ▶ 2:00
"The entry point really matters here for where you're actually going to send your fuzzing input. Fuzzers are highly capable of finding more than just surface-level bugs, but it only works if the fuzzer's energy is focused in the right place."
— Dillon Franke, ▶ 10:00
"Finally, the CoreAudioD binary and the CoreAudio framework that it uses are both closed source. So I thought it would be a unique reverse engineering challenge."
— Dillon Franke, ▶ 10:00
Key Takeaways
- Mach IPC as a browser sandbox escape vector: Any Mach service reachable via
allow-mach-lookupin a browser sandbox profile is a potential sandbox escape channel — systematic enumeration of these services using.sbprofile analysis andsandbox_checkis a productive first step for macOS security research. - Direct in-process harnesses outperform interprocess fuzzing: Loading the target library directly into the fuzzer process provides coverage instrumentation, fast iteration, and reliable crash attribution that interprocess approaches cannot match.
- API call chaining unlocks stateful code paths: Coverage-guided fuzzers plateau against stateful targets without initialization scaffolding; replaying prerequisite API call sequences before injecting fuzz input allows the fuzzer to explore deeper handler logic.
- Closed-source targets are tractable with dyld cache extraction: The macOS dyld shared cache is not an obstacle; IDA Pro and Binary Ninja parse it natively, and MIG subsystem patterns in the binary reliably identify message dispatch tables.
- Type confusion in CoreAudio yields sandbox escape on modern macOS: Despite PAC and CFI protections, a type confusion in a MIG handler function in
coreaudiodwas exploitable as a sandbox escape from the Safari GPU process context, demonstrating that the MIG attack surface in system daemons remains high-impact.
Reviews
Dr. Zero (Offensive Security Researcher) — STRONG ACCEPT
Franke's Mach IPC fuzzing methodology is practical, well-reasoned, and delivered a working sandbox escape on modern macOS — the API call chaining technique for breaking through stateful initialization barriers is a concrete contribution that will be reused. Two memory-corruption bugs in coreaudiod, one weaponized to escape a Safari GPU process sandbox despite PAC and CFI, is a legitimate result with strong platform impact.
Heather Calloway (CISO) — PASS
CoreAudio sandbox escape from the Safari GPU process — type confusion plus double-free in coreaudiod via Mach IPC, working against full mitigations including PAC and CFI. Dillon Franke, Google Project Zero.