Mac malware of 2020: Dacls, EvilQuest, WatchCat, XCSSET
Free public brief. The indicators, the detections with Splunk SPL already written (plus Elastic and KQL where they apply), and a Slack alert the next time this touches a vendor you run are in the app — free account, no card.
Objective-See's annual macOS malware review covering four major threats: Lazarus Dacls RAT, EvilQuest ransomware, WatchCat backdoor, and XCSSET developer-targeting credential stealer.
Objective-See's 2020 macOS malware roundup documents four significant threats discovered or prevalent during the year. OSX.Dacls is a macOS variant of the Lazarus-attributed cross-platform RAT, distributed via trojanized two-factor authentication apps (TinkaOTP), providing remote command execution and file management through a plugin architecture. OSX.EvilQuest (ThiefQuest) combines ransomware, file exfiltration, remote tasking, and viral self-propagation into other binaries; it was found in pirated software on torrent sites and scans for cryptocurrency wallets and certificates. OSX.WatchCat, likely Lazarus-created, is a backdoor with webshell capabilities distributed via trojanized applications, offering command execution and data theft. OSX.XCSSET uniquely targets macOS developers by hiding in Xcode projects on GitHub; it exploits two zero-day vulnerabilities to bypass Full Disk Access and steals credentials from Apple ID, Google, PayPal and data from Notes, Evernote, Skype, Telegram, and WeChat. All four use launch items for persistence.
Mentioned in this report
Detection guidance
macOS Launch Agent or Daemon Plist Masquerading as Apple Created by Non-Apple Process
A launchd plist named com.apple.* is written to a LaunchAgents or LaunchDaemons folder by a process outside Apple system paths, as Dacls and EvilQuest do to persist while looking legitimate. Auto-generated starting point — validate and tune in your environment before deploying. IOC matches can false-positive on shared infrastructure and decay as adversary infrastructure rotates.
title: macOS Launch Agent or Daemon Plist Masquerading as Apple Created by Non-Apple
Process
id: bea80f65-6608-56e5-bd96-425032db88ba
status: experimental
description: Detects creation of a launchd plist named com.apple.* in LaunchAgents
or LaunchDaemons directories by a process that does not live in Apple-owned system
paths. Dacls and EvilQuest persist through launch items with Apple-looking labels.
Generalises on the masquerading naming plus the writer location, not on specific
label names.
references:
- https://objective-see.org/blog/blog_0x5F.html
tags:
- attack.persistence
- attack.t1543.001
- attack.t1543.004
- attack.stealth
- attack.t1036.005
logsource:
category: file_event
product: macos
detection:
selection:
TargetFilename|contains:
- /LaunchAgents/com.apple.
- /LaunchDaemons/com.apple.
TargetFilename|endswith: .plist
filter_apple:
Image|startswith:
- /System/
- /usr/libexec/
- /usr/sbin/
- /usr/bin/
- /Library/Apple/
- /Applications/Xcode.app/
condition: selection and not filter_apple
falsepositives:
- Third-party installers or MDM agents that deliberately write com.apple.* preference
or launch plists
- Backup or migration tools restoring a user's LaunchAgents folder
level: medium
author: Vorant
macOS launchctl Loading a Job from a Temporary or Shared Writable Path
launchctl is used to load or bootstrap a launchd job whose plist sits in /tmp, /var/folders, or /Users/Shared, a pattern consistent with launch-item persistence by macOS malware such as Dacls, EvilQuest, WatchCat, and XCSSET. Auto-generated starting point — validate and tune in your environment before deploying. IOC matches can false-positive on shared infrastructure and decay as adversary infrastructure rotates.
title: macOS launchctl Loading a Job from a Temporary or Shared Writable Path
id: 046fc0ba-2752-5e83-8008-457e10720539
status: experimental
description: Detects launchctl load or bootstrap against a plist located in world-writable
or temporary directories. The malware families in this report use launch items for
persistence, and droppers often register a job straight from a staging directory.
Generalises on the launchctl verb and staging location, not on specific plist names.
references:
- https://objective-see.org/blog/blog_0x5F.html
tags:
- attack.persistence
- attack.t1543.001
- attack.t1543.004
logsource:
category: process_creation
product: macos
detection:
selection_img:
Image|endswith: /launchctl
selection_verb:
CommandLine|contains:
- ' load'
- ' bootstrap'
selection_path:
CommandLine|contains:
- /tmp/
- /private/tmp/
- /var/tmp/
- /var/folders/
- /Users/Shared/
condition: all of selection_*
falsepositives:
- Developers testing launchd jobs from a scratch directory
- Software installers that stage a plist in a temp folder before loading it
level: medium
author: Vorant
3 more detections for this report are in the app — the rules that match its indicators, plus the Sigma rules already converted to Splunk SPL, to Elastic where their fields map onto Elastic's integrations and to Microsoft Defender XDR KQL wherever Defender records the activity, and the YARA and Suricata. Three days of it free, no card.
Behavioural rules are generated from public reporting — validate in your environment before deploying.
Source reporting: https://objective-see.org/blog/blog_0x5F.html
What this brief leaves out
This page is the free tier: the write-up, the severity, the names. In the app the same report carries its extracted indicators, its detections (Splunk SPL already written, plus Elastic and Microsoft KQL where they apply), the actors and CVEs it names as live profiles, and the vendor research on the same campaign — the primary source the news paraphrased, cited and read directly.
It sits in a corpus of 13,854 reports from 146 sources, 616 of them written in the last seven days, and it grows through the day.
A new account starts with three days of all of it, no card, then keeps the government and CERT reporting free. Name the vendors you run and Slack hears about the reports that touch them — about forty a week that are yours, not the four hundred that are not.
Create a free account What it costs