Detect Launch Agent in Elastic Security
Adversaries may create or modify launch agents to repeatedly execute malicious payloads as part of persistence on macOS. When a user logs in, a per-user launchd process loads parameters for each launch-on-demand user agent from property list (.plist) files in /System/Library/LaunchAgents, /Library/LaunchAgents, and ~/Library/LaunchAgents. Adversaries install Launch Agents by placing a .plist file into these directories with RunAtLoad or KeepAlive keys set to true, ensuring malicious payloads execute at every user login. Launch Agents execute with user-level permissions and are commonly disguised using Apple-like naming conventions (e.g., com.apple.softwareupdate.plist, com.apple.GrowlHelper.plist). This technique is used by Calisto, Proton, MacSpy, CrossRAT, Dok, OceanLotus, ThiefQuest, Dacls, macOS.OSAMiner, InvisibleFerret (Contagious Interview), CoinTicker, and Green Lambert malware families.
MITRE ATT&CK
- Tactic
- Persistence Privilege Escalation
- Technique
- T1543 Create or Modify System Process
- Sub-technique
- T1543.001 Launch Agent
- Canonical reference
- https://attack.mitre.org/techniques/T1543/001/
Elastic Detection Query
sequence by host.name with maxspan=5m
[
file where host.os.type == "macos"
and event.type in ("creation", "change")
and file.path : ("/Library/LaunchAgents/*.plist", "/System/Library/LaunchAgents/*.plist", "/Users/*/Library/LaunchAgents/*.plist")
and (
process.name in ("bash", "sh", "zsh", "python3", "python", "ruby", "perl", "curl", "wget", "osascript", "node", "npm", "installer", "pkgutil", "xattr", "mktemp")
or file.name : ("com.apple.*.*.plist")
or file.path : ("*/tmp/*", "*/var/folders/*")
)
] by process.entity_id
[
process where host.os.type == "macos"
and process.name == "launchctl"
and process.args in ("load", "bootstrap")
and (
process.args : "*LaunchAgents*"
or process.args : "*.plist"
)
] by process.parent.entity_id
---
ALTERNATIVE STANDALONE FILE EVENT QUERY:
file where host.os.type == "macos"
and event.type in ("creation", "change")
and file.path : (
"/Library/LaunchAgents/*.plist",
"/System/Library/LaunchAgents/*.plist",
"/Users/*/Library/LaunchAgents/*.plist"
)
and (
process.name in ("bash", "sh", "zsh", "python3", "python", "ruby", "perl", "curl", "wget", "osascript", "node", "npm", "installer", "pkgutil", "xattr", "mktemp")
or file.name : ("com.apple.*.*.plist")
or file.path : ("*/tmp/*.plist", "*/var/folders/*.plist")
) Detects macOS Launch Agent persistence by correlating suspicious .plist file creation in LaunchAgent directories with subsequent launchctl load/bootstrap execution, or standalone plist writes by interpreted language runtimes and download utilities. Covers Apple name-spoofing patterns and anomalous plist placement in temp paths.
Data Sources
Required Tables
False Positives & Tuning
- Legitimate software installers (e.g., Homebrew casks, Adobe Creative Cloud updaters) write plist files to /Library/LaunchAgents using installer or pkgutil as the initiating process
- Developer tools such as Docker Desktop, Vagrant, or VMware Fusion register launch agents during initial setup or updates, which may match the initiating process list
- macOS software updates can use launchctl bootstrap commands during OS patch application, potentially triggering the launchctl sequence detection branch
Other platforms for T1543.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 1Create Persistent Launch Agent via Bash
Expected signal: DeviceFileEvents: FileCreated action for file 'com.df00tech.atomictest.plist' in '~/Library/LaunchAgents/', InitiatingProcessFileName='bash'. osquery_differential: action='added' in launchd table with label='com.df00tech.atomictest', run_at_load='1', program_arguments='/bin/bash -c date...'.
- Test 2Load Launch Agent with launchctl
Expected signal: DeviceProcessEvents: FileName='launchctl', ProcessCommandLine contains 'load' and 'LaunchAgents/com.df00tech.launchctltest.plist', InitiatingProcessFileName='bash'. DeviceFileEvents: FileCreated for the plist in LaunchAgents directory.
- Test 3Apple Name Spoof Launch Agent (MacMa/Green Lambert Pattern)
Expected signal: DeviceFileEvents: FileCreated for 'com.apple.softwareupdate.helper.plist' in ~/Library/LaunchAgents/, InitiatingProcessFileName='bash'. osquery_differential: action='added', label='com.apple.softwareupdate.helper', run_at_load='1', keep_alive='1', path contains '/Users/<user>/Library/LaunchAgents/'.
- Test 4KeepAlive Launch Agent with Randomly Named Plist (Dok/CoinTicker Pattern)
Expected signal: DeviceFileEvents: FileCreated for 'com.<rand1>.<rand2>.plist' in ~/Library/LaunchAgents/, InitiatingProcessFileName='bash'. osquery_differential: action='added', label='com.<rand1>.<rand2>', run_at_load='1', keep_alive='1'.
References (11)
- https://attack.mitre.org/techniques/T1543/001/
- https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html
- https://www.sentinelone.com/blog/how-malware-persists-on-macos/
- https://objective-see.org/blog/blog_0x25.html
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1543.001/T1543.001.md
- https://www.trendmicro.com/en_us/research/20/d/new-macos-dacls-rat-backdoor-show-lazarus-apt-targets-macos.html
- https://securelist.com/calisto-trojan-for-macos/86543/
- https://www.checkpoint.com/research/may-i-download-adware-please-new-macos-malware-spreading-via-bundled-software/
- https://www.welivesecurity.com/2016/07/06/new-osxkeydnap-malware-hungry-credentials/
- https://www.zscaler.com/blogs/security-research/contagiousinterview-invisibleferret
- https://github.com/SigmaHQ/sigma/tree/master/rules/macos
Unlock Pro Content
Get the full detection package for T1543.001 including response playbook, investigation guide, and atomic red team tests.