Breaking the Sound Barrier, Part II: Exploiting CVE-2024-54529
Dillon Franke, Google Information Security Engineering, 20% time on Project Zero ·
2026-01-30 ·
Read original ↗
ATT&CK techniques detected
20 predictions
T1055.001Dynamic-link Library Injection
96%
"is stored in the dyld shared cache and has a constant address until system reboot ) defeating aslr was not necessary in the context of privilege escalation. i crafted a rop chain to open and write a file at a location normally accessible only to coreaudiod. as the rop chain is en…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1574.013KernelCallbackTable
93%
"##00007ff80f4e2c7f libsystem _ pthread. dylib ` _ pthread _ wqthread + 326 frame # 13 : 0x00007ff80f4e1bdb libsystem _ pthread. dylib ` start _ wqthread + 15 understanding the objective exploiting such a vulnerability seemed simple enough : if we could control the address being d…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
89%
"##ll number for open ( ) rop + = p64 ( syscall ) # syscall rop + = b ' \ x42 ' * ( 1152 - len ( rop ) ) # [ rax + 0x168 ] → pointer to pivot gadget ( entrypoint ) rop [ 0x168 : 0x170 ] = p64 ( stack _ pivot _ gadget ) # xchg rsp, rax ; xor edx, edx ; ret with everything in place,…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1574.013KernelCallbackTable
86%
"this chain in place, we could write our target address at offset 0x168 of the fake vtable to hijack control flow. the approach would look like this : initial exploitation attempts and the cfstring hurdle the most direct path to exploitation seemed to be to find an api to write ar…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
85%
"our sprayed data. repeat : repeat steps 3 - 4 until it works! validating the approach in order for the exploit to work, a lot of things needed to go right. before proceeding, i wanted to make sure that my attack chain wasn ’ t purely theoretical - that the pointer chain i sought …"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
83%
"the tricky constraint why only 6 uninitialized bytes you ask? the developer likely did something like this at offset 0x68 when defining the ngne object : class ngne {... size _ t previous _ var ; / / offset 0x60 short var = 0 ; / / offset 0x68 size _ t next _ var ; / / offset 0x7…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1543.001Launch Agent
82%
"operations - - - - cacfdata : : ~ cacfdata ( data ) ; } } } this meant that each time the process restarted, our entire plist structure was reallocated and then freed, giving us a chance for our data to end up within the vulnerable offset of the ngne object. updated exploitation …"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1204.002Malicious File
79%
"##ing cve - 2024 - 54529 was a journey that went from a simple - looking type confusion to a multi - stage exploit involving heap spraying, uninitialized memory, and a carefully orchestrated series of crashes and restarts. this research highlights the power and importance of sand…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
70%
"in the coreaudio framework used by the coreaudiod process. several mach message handlers, such as _ xiocontext _ fetch _ workgroup _ port, would fetch a hals _ object from the object map based on an id from the mach message, and then perform operations on it, assuming it was of a…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1574.013KernelCallbackTable
69%
"##s of interest after an object was fetched via copyobjectbyobjectid. this combination of dynamic and static analysis was essential for systematically mapping out the exploitation surface. forcing out - of - bounds reads on the heap armed with my object dumper, i decided to inves…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
66%
"shifted back to heap manipulation and finding a way to control the contents of an object ’ s allocation directly. a glimmer of hope : uninitialized memory in the ngne object to hunt for other exploitation primitives, i turned to a powerful debugging tool on macos : guard malloc w…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1574.013KernelCallbackTable
63%
"( float ) < real > cfbooleanref < true / > or < false / > this meant i could create plist files with large arrays of cfstring or cfdata objects, giving me a powerful primitive for mass - allocating data and controlling the heap layout. furthermore, i could add cfarray or cfdictio…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
62%
"would be wiped clean moments before the ngne object was placed on top of it. my exploit was dead in the water. a new hope : startup ngne objects this forced a pivot. if i wanted to use uninitialized memory, i needed to land an allocation in a malloc zone that didn ’ t get zeroed …"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
58%
"but i was up for the challenge! freeing the data next, i needed to free the memory structure that had been allocated with my data. this was easy enough - i just had to call the api again with a much smaller plist. then, my large, allocated plist structure was freed. reusing the f…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
53%
"return casettingsstorage : : savesettings ( ( casettingsstorage * ) this ) ; } lucky for me, the casettingsstorage : : savesettings function created a copy of the in - memory plist, wrote it to disk, and then freed the copy. thankfully, this process occurred before the creation o…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1574.013KernelCallbackTable
49%
"##string ’ s header made this impossible. this meant i needed a new approach. i had to find a different way to control the memory at the vulnerable offset. tools of the trade with my initial attempts at finding a suitable object primitive proving fruitless, it became clear i need…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
46%
"breaking the sound barrier, part ii : exploiting cve - 2024 - 54529 in the first part of this series, i detailed my journey into macos security research, which led to the discovery of a type confusion vulnerability ( cve - 2024 - 54529 ) and a double - free vulnerability ( cve - …"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1055.001Dynamic-link Library Injection
46%
"i control in the coreaudiod process. create indirect pointers : create indirect pointers that point to my controlled data. free data containing pointers. reuse pointers : trick the program into reusing memory containing pointers when the ngne object is allocated. heap feng shui w…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
T1543.001Launch Agent
31%
"into memory on startup one difficulty i had to overcome was that after crashing, the newly spawned coreaudiod would be allocated within a new process space. that meant that the previously allocated heap spray would no longer be in play. however, i discovered a nice feature that h…"
Which technique(s) should be tagged here? Pick zero or more — leaving blank just records that the original was wrong.
No matches for .
Loading techniques…
Summary
In the first part of this series, I detailed my journey into macOS security research, which led to the discovery of a type confusion vulnerability (CVE-2024-54529) and a double-free vulnerability (CVE-2025-31235) in the coreaudiod system daemon through a process I call knowledge-driven fuzzing. While the first post focused on the process of finding the vulnerabilities, this post dives into the intricate process of exploiting the type confusion vulnerability. I’ll explain the technical details of turning a potentially exploitable crash into a working exploit: a journey filled with dead ends, creative problem solving, and ultimately, success. The Vulnerability: A Quick Recap If you haven’t already, I highly recommend reading my detailed writeup on this vulnerability before proceeding. As a refresher, CVE-2024-54529 is a type confusion vulnerability within the com.apple.audio.audiohald Mach service in the CoreAudio framework used by the coreaudiod process. Several Mach message handlers, such as _XIOContext_Fetch_Workgroup_Port, would fetch a HALS_Object from the Object Map based on an ID from the Mach message, and then perform operations on it, assuming it was of a specific type (ioct) without proper validation.