Detect Launchctl in Splunk
Adversaries may abuse launchctl to execute commands or programs on macOS. Launchctl interfaces with launchd, the macOS service management framework, and supports subcommands including load, unload, start, stop, and kickstart. Adversaries use launchctl to execute payloads as Launch Agents (per-user persistence in ~/Library/LaunchAgents/ or /Library/LaunchAgents/) or Launch Daemons (system-level persistence in /Library/LaunchDaemons/). Common attack patterns include loading malicious plist files from world-writable directories such as /tmp, using the -w flag to force-enable disabled services, and invoking launchctl from scripting engines after initial access. Real-world threat actors using this technique include LoudMiner (QEMU-based cryptominer), Cuckoo Stealer, AppleJeus (North Korean cryptocurrency theft), macOS.OSAMiner, XCSSET (Xcode project infection), and Calisto spyware.
MITRE ATT&CK
- Tactic
- Execution
- Technique
- T1569 System Services
- Sub-technique
- T1569.001 Launchctl
- Canonical reference
- https://attack.mitre.org/techniques/T1569/001/
SPL Detection Query
index=* sourcetype="osquery:results" (columns.path="/usr/bin/launchctl" OR columns.path="/bin/launchctl" OR like(columns.cmdline, "%launchctl%"))
| eval cmdline=coalesce('columns.cmdline', "")
| eval parent_path=coalesce('columns.parent_path', 'columns.parent', "")
| eval username=coalesce('columns.username', 'columns.uid', "")
| eval LoadFromTempPath=if(match(cmdline, "(/tmp/|/private/tmp/|/var/tmp/|/var/folders/|/Users/Shared/)"), 1, 0)
| eval ForceLoad=if(match(cmdline, "launchctl\s+load\s+-w"), 1, 0)
| eval KickstartCmd=if(match(cmdline, "launchctl\s+kickstart"), 1, 0)
| eval BootstrapCmd=if(match(cmdline, "launchctl\s+bootstrap"), 1, 0)
| eval ScriptingParent=if(match(parent_path, "/(bash|sh|zsh|ksh|python[0-9.]*|ruby|perl|osascript|curl|wget|node|npm)$"), 1, 0)
| eval LoadUserAgent=if(match(cmdline, "/Users/[^/]+/Library/LaunchAgents/"), 1, 0)
| eval SuspicionScore=LoadFromTempPath + ForceLoad + ScriptingParent + KickstartCmd
| where SuspicionScore > 0 OR (LoadUserAgent=1 AND ScriptingParent=1)
| table _time, host, username, cmdline, parent_path, LoadFromTempPath, ForceLoad, ScriptingParent, LoadUserAgent, KickstartCmd, SuspicionScore
| sort - SuspicionScore - _time Detects suspicious launchctl execution patterns on macOS using osquery process event data forwarded to Splunk. Evaluates command lines for high-risk indicators: loading from temp paths, force-loading with -w flag, kickstart/bootstrap subcommands, and invocation from scripting engines or download utilities. Assigns a cumulative suspicion score for analyst prioritization. Requires osquery deployed via Fleet, Kolide, or the Splunk Add-on for osquery with the process_events or processes table enabled in the osquery configuration.
Data Sources
Required Sourcetypes
False Positives & Tuning
- MDM solutions (Jamf, Mosyle, Kandji) deploying configuration profiles and LaunchAgents via scripts that invoke launchctl load — parent process will be jamf, jamfManagementService, or mdmclient
- Homebrew package manager loading service plists during installation (brew services start) which internally invokes launchctl — parent path will be under /opt/homebrew/ or /usr/local/Homebrew/
- macOS software installers (PKG files, App Store updates) loading LaunchDaemons for background helper processes via installer scripts
- IT automation tools (Ansible, Chef, Puppet) managing Launch Daemons via shell scripts that invoke launchctl — correlate with scheduled maintenance windows
- Developer tools and build systems (Docker Desktop, file sync utilities, local web servers) creating LaunchAgents for background daemons during first-run setup
Other platforms for T1569.001
Testing Methodology
Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Load LaunchAgent from /tmp (Malware Staging Pattern)
Expected signal: Process creation: launchctl with ProcessCommandLine containing 'load /tmp/com.df00tech.atomictest.plist'; parent process is the executing shell. Secondary process creation: /bin/sh spawned by launchd executing the RunAtLoad ProgramArguments. File creation: /tmp/launchctl_test_output.txt written by the loaded agent. macOS Unified Log entry for com.df00tech.atomictest service start under the current user's launchd domain.
- Test 2Load LaunchDaemon with Force-Enable Flag (-w) — XCSSET and LoudMiner Technique
Expected signal: Process creation: sudo followed by launchctl with ProcessCommandLine containing 'load -w /Library/LaunchDaemons/com.df00tech.daemontest.plist'. File creation event in /Library/LaunchDaemons/ directory (anomalous outside MDM-managed deployments). launchd override database updated at /var/db/launchd.db/. macOS Unified Log records bootstrap of com.df00tech.daemontest in the system launchd domain.
- Test 3Enable Screen Sharing via Launchctl — Calisto Spyware Technique
Expected signal: Process creation: launchctl with ProcessCommandLine 'load -w /System/Library/LaunchDaemons/com.apple.screensharing.plist'. Parent process is sudo/shell. macOS Unified Log records screensharing daemon activation. System Preferences -> Sharing would show Screen Sharing enabled. VNC listener appears on TCP port 5900 (detectable via network telemetry). launchd override database records screensharing as enabled.
- Test 4Launchctl Invoked from Python Dropper (Staged Execution Chain)
Expected signal: Process creation chain: python3 spawning /bin/launchctl as a child process. ProcessCommandLine for launchctl: 'load /tmp/com.df00tech.pytest.plist'. InitiatingProcessFileName: python3. This specific parent-child relationship (python3 → launchctl) is the key detection signal. Secondary process creation: /bin/sh running the ProgramArguments payload, spawned by launchd.
References (11)
- https://attack.mitre.org/techniques/T1569/001/
- https://ss64.com/osx/launchctl.html
- https://researchcenter.paloaltonetworks.com/2016/09/unit42-sofacys-komplex-os-x-trojan/
- https://labs.sentinelone.com/20-common-tools-techniques-used-by-macos-threat-actors-malware/
- https://blog.kandji.io/cuckoo-stealer
- https://us-cert.cisa.gov/ncas/alerts/aa21-048a
- https://securelist.com/calisto-trojan-for-macos/86543/
- https://www.trendmicro.com/en_us/research/20/h/xcsset-mac-malware--infects-xcode-projects--uses-zero-day-exploit.html
- https://www.welivesecurity.com/2019/07/09/mac-cryptocurrency-trading-app-repackaged-deliver-sigspoof-backdoor/
- https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1569.001/T1569.001.md
Unlock Pro Content
Get the full detection package for T1569.001 including response playbook, investigation guide, and atomic red team tests.