T1543.001 Microsoft Sentinel · KQL

Detect Launch Agent in Microsoft Sentinel

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/

KQL Detection Query

Microsoft Sentinel (KQL)
kusto
let SuspiciousParentProcesses = dynamic(["bash", "sh", "zsh", "python3", "python", "ruby", "perl", "curl", "wget", "osascript", "node", "npm", "installer", "pkgutil", "xattr", "mktemp"]);
// Part 1: .plist file creation or modification in LaunchAgent directories
let PlistFileEvents = DeviceFileEvents
| where Timestamp > ago(24h)
| where FolderPath has "/Library/LaunchAgents/"
| where FileName endswith ".plist"
| where ActionType in ("FileCreated", "FileModified")
| extend AgentScope = case(
    FolderPath startswith "/System/Library/LaunchAgents/", "System",
    FolderPath startswith "/Library/LaunchAgents/", "Global",
    "User"
)
| extend SuspiciousWriter = InitiatingProcessFileName in~ (SuspiciousParentProcesses)
| extend AppleNameSpoof = FileName matches regex @"com\.apple\.[a-z]+\.[a-z]+\.plist"
| extend RandomName = FileName matches regex @"com\.[a-z0-9]{4,10}\.[a-z0-9]{4,10}\.plist" and not (FileName startswith "com.apple." or FileName startswith "com.microsoft." or FileName startswith "com.adobe." or FileName startswith "com.google.")
| project Timestamp, DeviceName, AccountName, DetectionType="PlistWritten",
    TargetFile=FileName, TargetPath=FolderPath, AgentScope, SuspiciousWriter, AppleNameSpoof, RandomName,
    WriterProcess=InitiatingProcessFileName, WriterCommandLine=InitiatingProcessCommandLine,
    WriterFolderPath=InitiatingProcessFolderPath;
// Part 2: launchctl load or bootstrap commands targeting LaunchAgent paths
let LaunchctlEvents = DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName =~ "launchctl"
| where ProcessCommandLine has_any ("load", "bootstrap")
| where ProcessCommandLine has "LaunchAgents" or ProcessCommandLine has ".plist"
| extend AgentScope = case(
    ProcessCommandLine has "/System/Library/LaunchAgents", "System",
    ProcessCommandLine has "/Library/LaunchAgents", "Global",
    "User"
)
| extend SuspiciousWriter = InitiatingProcessFileName in~ (SuspiciousParentProcesses)
| extend AppleNameSpoof = ProcessCommandLine matches regex @"com\.apple\.[a-z]+\.[a-z]+\.plist"
| extend RandomName = ProcessCommandLine matches regex @"com\.[a-z0-9]{4,10}\.[a-z0-9]{4,10}\.plist" and not (ProcessCommandLine has "com.apple." or ProcessCommandLine has "com.microsoft." or ProcessCommandLine has "com.adobe." or ProcessCommandLine has "com.google.")
| project Timestamp, DeviceName, AccountName, DetectionType="LaunchctlLoad",
    TargetFile=ProcessCommandLine, TargetPath=ProcessCommandLine, AgentScope, SuspiciousWriter, AppleNameSpoof, RandomName,
    WriterProcess=InitiatingProcessFileName, WriterCommandLine=InitiatingProcessCommandLine,
    WriterFolderPath=InitiatingProcessFolderPath;
PlistFileEvents
| union LaunchctlEvents
| sort by Timestamp desc
high severity high confidence

Detects macOS Launch Agent persistence using Microsoft Defender for Endpoint tables. Monitors two key attack vectors: (1) creation or modification of .plist files in /Library/LaunchAgents directories via DeviceFileEvents, identifying suspicious writer processes such as shells, interpreters, and download utilities; (2) launchctl load/bootstrap commands targeting LaunchAgent paths via DeviceProcessEvents. Enrichment fields flag Apple-name spoofing (com.apple.*.plist from non-Apple writers), randomly generated plist names matching Dok/CoinTicker patterns, and the agent scope (System/Global/User). This detection covers macOS endpoints enrolled in Microsoft Defender for Endpoint.

Data Sources

File: File CreationFile: File ModificationProcess: Process CreationCommand: Command ExecutionMicrosoft Defender for Endpoint (macOS)

Required Tables

DeviceFileEventsDeviceProcessEvents

False Positives & Tuning

  • Legitimate software installers (Adobe Creative Cloud, Zoom, Dropbox, Google Chrome updater) creating Launch Agents for auto-update or helper functionality during user-initiated installation — these will show installer or package manager as the writer process
  • Enterprise MDM solutions (Jamf Pro, Mosyle, Kandji) deploying configuration profiles that include Launch Agent definitions as part of managed device policy enforcement
  • Homebrew package manager and casks installing helper services (e.g., postgresql, redis, docker-machine) via brew services — these will show bash or brew as the writer process
  • VPN clients (Cisco AnyConnect, Palo Alto GlobalProtect) and endpoint security agents (CrowdStrike Falcon, Carbon Black, SentinelOne) creating helper daemons during initial agent installation
  • Developer tools including JetBrains Toolbox, Xcode command line tools, and language version managers (rbenv, pyenv, nvm) registering launch services during setup
Download portable Sigma rule (.yml)

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.

  1. 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...'.

  2. 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.

  3. 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/'.

  4. 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'.

Unlock Pro Content

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

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections