Beyond the good ol' LaunchAgents - 13 - Audio Plugins
This is part 13 in the series of “Beyond the good ol’ LaunchAgents”, where I try to collect various persistence techniques for macOS. For more background check the introduction.
This is another one of my favorites for some reason. macOS being a popular audio editing device, supports external audio drivers and plugins. @xorrior wrote a very extensive blog post about these at his website, here: Audio Unit Plug-ins. Legitimate Un-signed Code Execution | by Christopher Ross | Posts By SpecterOps Team Members
It is pretty amazing, and I don’t plan to repeat what it’s there but show another way of implementing a plugin. I will briefly describe how to create a Hardware Abstraction Layer (HAL) Service plug-in.
Apple has a nice documentation as well: Core Audio Overview
HAL plugins are loaded by coreaudiod
, which runs as root, and defined at /System/Library/LaunchDaemons/com.apple.audio.coreaudiod.plist
. HAL plugins are located at /Library/Audio/Plug-Ins/HAL
, which means that we require root access to install them.
We can easily create such a plugin with Xcode, by creating a new project, and selecting the type as bundle
. For the bundle extension we need to provide .driver
. Once the project is created we need to add a new source file.
#import <Foundation/Foundation.h>
__attribute__((constructor)) static void run()
{
NSLog(@"%@", @"Hello from MasterAudio");
}
We can implement a simple constructor
which will be loaded when the driver is loaded. We don’t really need to do anything else. This will work just fine, and won’t crash coreaudiod
.
In the Info.plist
we also need to add some UUID, and default function name, but we don’t need to implement it.
<key>CFPlugInFactories</key>
<dict>
<key>00000000-0000-0000-0000-000000000000</key>
<string>SomeFunction</string>
</dict>
<key>CFPlugInTypes</key>
<dict>
<key>00000000-0000-0000-0000-000000000000</key>
<array>
<string>00000000-0000-0000-0000-000000000000</string>
</array>
</dict>
Next we can simply compile it and place it in /Library/Audio/Plug-Ins/HAL
. We will need to set folder ownership to root:wheel
.
We can then go and restart coreaudiod
.
csaby@dev ~ % sudo launchctl stop com.apple.audio.coreaudiod
csaby@dev ~ % sudo launchctl start com.apple.audio.coreaudiod
Now we can query the logs.
csaby@dev ~ % log show --predicate 'eventMessage contains[c] "MasterAudio"' --last 20m
Filtering the log data using "composedMessage CONTAINS[c] "MasterAudio""
Skipping info and debug messages, pass --info and/or --debug to include.
Timestamp Thread Type Activity PID TTL
2021-04-19 22:39:55.144111+0200 0x18e2 Default 0x0 586 0 coreaudiod: (MasterAudio) Hello from MasterAudio
As we can see our driver was loaded, and it will run as root.
This was just one option, Chris’s blog (linked above) details a few more.