Breaking the Sound Barrier, Part II: Exploiting CVE-2024-54529

A type confusion vulnerability in Apple's CoreAudio framework, identified as CVE-2024-54529, has been successfully exploited by a Google security engineer. The vulnerability resides within the `coreaudiod` system daemon, specifically in the `com.apple.audio.audiohald` Mach service. Researchers discovered that certain message handlers within this service would retrieve an object from an internal map based on an ID provided in a Mach message. The code would then proceed to operate on this object, assuming it was of a specific type without performing adequate validation.
This flawed assumption led to a crash when the software attempted to execute a virtual function call on an object whose pointer was stored within the retrieved object. The call was made via an indirect pointer at offset 0x168 within the object. The vulnerability occurs because the code does not verify the actual type of the object before attempting this operation, allowing an attacker to potentially substitute an object of an unexpected type.

Exploiting this vulnerability required a multi-step process to gain control of the program's execution flow. The primary goal was to manipulate the pointer at offset 0x168, which was used for the virtual function call. However, the object containing this pointer was accessed multiple times before the critical call. This necessitated the establishment of a pointer chain.
The exploit strategy involved first ensuring that a specific memory location, controllable by the attacker, was pointed to by an offset within the vulnerable object. This attacker-controlled memory region then needed to contain a pointer at its beginning, which in turn pointed to a fake virtual function table (vtable) also under the attacker's control. By arranging this chain, the attacker could then overwrite an address within the fake vtable at offset 0x168, thereby hijacking the program's control flow.
Initial attempts to exploit the vulnerability directly by writing arbitrary data to the critical offset of a `HALS_Object` proved unsuccessful. One approach involved attempting to use a `CFString` object, a common data structure in macOS. The idea was to place a pointer to a `CFString` at the vulnerable offset. However, the internal structure of `CFString` objects, specifically their headers, could not be fully controlled by the attacker, preventing the necessary pointer manipulation.

To better understand the heap layout and the objects residing within the `coreaudiod` process, custom tools were developed. A key tool was an object dumper, built using the TinyInst Hook API. This tool allowed for dynamic analysis by iterating through the `HALS_ObjectMap` and extracting detailed information about each object on the heap, including its raw contents, size, type, and subtype. This provided crucial insights into object composition and the presence of relevant pointers. Complementing this, a targeted static analysis script was used to identify code paths that wrote to specific offsets after an object was retrieved by its ID.
Another avenue explored was the possibility of triggering an out-of-bounds read. This would involve creating a small `HALS_Object` on the heap and then placing attacker-controlled data immediately after it in memory. If the vulnerability were triggered on the smaller object, the attempt to read at offset 0x68 would go beyond the object's bounds and access the attacker's data. However, analysis revealed that in recent macOS versions, no `HALS_Object` types were smaller than the critical offset of 0x68 bytes, rendering this approach infeasible.
A breakthrough came from investigating uninitialized memory. Using macOS's Guard Malloc with the PreScribble option, which fills newly allocated memory with a specific pattern, researchers identified an object type named `ngne`. A portion of this object's memory was found to be uninitialized, specifically six high bytes of a pointer-sized field at the correct offset. This uninitialized memory provided the necessary primitive to gain control over the pointer at the vulnerable offset, overcoming the previous obstacles. The limited amount of uninitialized memory suggests a specific coding pattern where only a portion of a larger data structure was not properly zeroed out upon allocation.





