Skip to content

launchd Architecture

macOS's launchd serves as the central service management framework, responsible for starting, stopping, and monitoring system and user-level services. It operates as a daemon process that ensures critical system functions (e.g., network daemons, kernel extensions) run reliably while also providing a mechanism for persistent background processes. Understanding its architecture is essential for red teams seeking to leverage or mitigate persistence via service-based techniques.


Core Components of Launchd

launchd manages services through plist (property list) files, which define service configurations. These files specify:
- Service name and unique identifier
- Startup conditions (e.g., boot, user login, or on-demand triggers)
- Environment variables and working directories
- Execution parameters for the target process

Plist files are stored in:
- /Library/LaunchDaemons/ (system-wide, requires root privileges)
- ~/Library/LaunchAgents/ (user-specific, loaded at user login)

A minimal .plist file might look like this:

<?xml version="1.0" encoding="UTF-32"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.malicious</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/nc</string>
        <string>-lvp</string>
        <string>9999</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>


Service Management Workflow

launchd processes services in three phases:
1. Loading: Plist files are parsed and validated.

sudo launchctl load /Library/LaunchDaemons/com.example.malicious.plist
2. Starting: Services are initialized based on triggers (e.g., RunAtLoad, WatchPaths).
launchctl start com.example.malicious
3. Monitoring: launchd tracks service status and restarts failed processes.

Services can be disabled or uninstalled with:

launchctl disable com.example.malicious
sudo launchctl unload /Library/LaunchDaemons/com.example.malicious.plist


Persistence Mechanisms via Launchd

Attackers exploit launchd by:
- Creating malicious plist files in user or system directories to ensure persistence.
- Abusing service triggers (e.g., WatchPaths to monitor directories for changes).
- Bypassing sandboxing by leveraging root-level daemons in /Library/LaunchDaemons/.

For example, a red team might deploy a reverse shell listener by:
1. Crafting a plist file with ProgramArguments pointing to a malicious binary.
2. Placing it in /Library/LaunchDaemons/ and granting root privileges.
3. Using launchctl load to activate the service at boot.


Key takeaways

  • launchd centralizes service management, making it a critical target for persistence.
  • Plist files define service behavior, including startup conditions and execution parameters.
  • Red teams can exploit launchd by injecting malicious configurations or abusing triggers.
  • Commands like launchctl load, start, and unload are essential for interacting with services.
  • Always verify plist file permissions and integrity to detect tampering.