T1569.001

Launchctl

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.

Microsoft Sentinel / Defender
kusto
let SuspiciousPaths = dynamic([
  "/tmp/", "/private/tmp/", "/var/tmp/", "/var/folders/",
  "/Users/Shared/", "/Library/Caches/"
]);
let SuspiciousParents = dynamic([
  "bash", "sh", "zsh", "ksh", "fish",
  "python", "python3", "ruby", "perl", "osascript",
  "curl", "wget", "node", "npm"
]);
DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName =~ "launchctl"
| where ProcessCommandLine has_any ("load", "start", "kickstart", "bootstrap")
| extend LoadFromTempPath = ProcessCommandLine has_any (SuspiciousPaths)
| extend ForceLoad = ProcessCommandLine has "-w"
| extend LoadFromUserLibrary = ProcessCommandLine matches regex @"/Users/[^/]+/Library/LaunchAgents/"
| extend ScriptingEngineParent = InitiatingProcessFileName has_any (SuspiciousParents)
| extend SuspicionScore = toint(LoadFromTempPath) + toint(ForceLoad) + toint(ScriptingEngineParent)
| where LoadFromTempPath
    or ScriptingEngineParent
    or (ForceLoad and LoadFromUserLibrary)
    or (ForceLoad and SuspicionScore >= 1)
| project Timestamp, DeviceName, AccountName, ProcessCommandLine,
         InitiatingProcessFileName, InitiatingProcessCommandLine,
         LoadFromTempPath, ForceLoad, LoadFromUserLibrary,
         ScriptingEngineParent, SuspicionScore
| sort by Timestamp desc
high severity medium confidence

Data Sources

Process: Process Creation Command: Command Execution Microsoft Defender for Endpoint (macOS agent)

Required Tables

DeviceProcessEvents

False Positives

  • 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

Unlock Pro Content

Get the full detection package for T1569.001 including response playbook, investigation guide, and atomic red team tests.

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections