Detect Launch Agent in IBM QRadar
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/
QRadar Detection Query
SELECT
DATEFORMAT(starttime, 'YYYY-MM-dd HH:mm:ss') AS event_time,
logsourcename(logsourceid) AS log_source,
"username",
"hostname",
"sourceip",
QIDNAME(qid) AS event_name,
"filename",
"filepath",
"command" AS process_args,
"parentcommand" AS parent_process,
CASE
WHEN ISNULL("filepath") = FALSE AND "filepath" ILIKE '/System/Library/LaunchAgents/%' THEN 'System'
WHEN ISNULL("filepath") = FALSE AND "filepath" ILIKE '/Library/LaunchAgents/%' THEN 'Global'
ELSE 'User'
END AS agent_scope,
CASE
WHEN LOWER("parentcommand") MATCHES '(^|/)bash$|(^|/)sh$|(^|/)zsh$|(^|/)python3?$|(^|/)ruby$|(^|/)perl$|(^|/)curl$|(^|/)wget$|(^|/)osascript$|(^|/)node$|(^|/)installer$|(^|/)pkgutil$' THEN 1
ELSE 0
END AS suspicious_writer,
CASE
WHEN "filename" ILIKE 'com.apple.%.%.plist' AND "filepath" NOT ILIKE '/System/Library/%' THEN 1
ELSE 0
END AS apple_name_spoof,
CASE
WHEN REGEXP("filename", 'com\.[a-z0-9]{4,10}\.[a-z0-9]{4,10}\.plist')
AND "filename" NOT ILIKE 'com.apple.%'
AND "filename" NOT ILIKE 'com.microsoft.%'
AND "filename" NOT ILIKE 'com.adobe.%'
AND "filename" NOT ILIKE 'com.google.%'
THEN 1 ELSE 0
END AS random_name
FROM events
WHERE
starttime > NOW() - 1 DAYS
AND (
(
CATEGORYNAME(category) ILIKE '%file%create%' OR CATEGORYNAME(category) ILIKE '%file%write%' OR CATEGORYNAME(category) ILIKE '%file%modified%'
AND ("filepath" ILIKE '/Library/LaunchAgents/%.plist' OR "filepath" ILIKE '/System/Library/LaunchAgents/%.plist' OR "filepath" ILIKE '%/Library/LaunchAgents/%.plist')
)
OR (
CATEGORYNAME(category) ILIKE '%process%'
AND "command" ILIKE '%launchctl%'
AND ("command" ILIKE '%load%' OR "command" ILIKE '%bootstrap%')
AND ("command" ILIKE '%LaunchAgents%' OR "command" ILIKE '%.plist%')
)
)
AND (
CASE
WHEN LOWER("parentcommand") MATCHES '(^|/)bash$|(^|/)sh$|(^|/)zsh$|(^|/)python3?$|(^|/)ruby$|(^|/)perl$|(^|/)curl$|(^|/)wget$|(^|/)osascript$|(^|/)node$|(^|/)installer$|(^|/)pkgutil$' THEN 1
ELSE 0
END +
CASE WHEN "filename" ILIKE 'com.apple.%.%.plist' AND "filepath" NOT ILIKE '/System/Library/%' THEN 1 ELSE 0 END +
CASE WHEN REGEXP("filename", 'com\.[a-z0-9]{4,10}\.[a-z0-9]{4,10}\.plist') AND "filename" NOT ILIKE 'com.apple.%' AND "filename" NOT ILIKE 'com.microsoft.%' THEN 1 ELSE 0 END
) > 0
ORDER BY event_time DESC Detects macOS Launch Agent persistence by monitoring file creation/modification events targeting LaunchAgent plist directories and launchctl load/bootstrap commands. Scores events by suspicious writer process, Apple name spoofing, and random reverse-DNS naming patterns to reduce false positives.
Data Sources
Required Tables
False Positives & Tuning
- Enterprise MDM solutions such as Jamf Pro write legitimate LaunchAgent plists during device enrollment, software deployment, or profile updates using installer as the parent process
- Developer environments like Homebrew, MacPorts, or Conda install plists via shell scripts as part of package post-install hooks, generating high-volume true-positive-like events on developer workstations
- Apple's own Software Update mechanism can trigger launchctl bootstrap operations for newly installed system daemons during OS updates, appearing as System-scope events
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.