XCSSET Malware Update | macOS Threat Actors Prepare for Life Without Python

Threat actors behind the XCSSET malware have been relatively quiet since last year. However, new activity beginning around April 2022 and increasing through May to August shows that actors have not only adapted to changes in macOS Monterey, but are preparing for the demise of Python, an integral and essential part of their current toolkit.

In this post, we review changes made to the latest versions of XCSSET and reveal some of the context in which these threat actors operate.

XCSSET Changes in 2022

Since XCSSSET first appeared, the authors have made consistent use of two primary tools to obfuscate both droppers and dropped files: SHC and run-only compiled AppleScripts, respectively.

SHC-compiled shell scripts are opaque to traditional static scanning tools and contain only a few human-readable strings.

string in XCSSET dubrobber malware

As all SHC-compiled binaries, legitimate or malicious, contain these same strings, signature scanners cannot distinguish between them.

SHA1: 127b66afa20a1c42e653ee4f4b64cf1ee3ed637d

Dynamic execution of this recent SHC-compiled XCSSET dropper, currently with 0 detections on VirusTotal despite having been known for 2 months, also reveals that the malware authors have changed from hiding the primary executable in a fake Xcode.app in the initial versions in 2020 to a fake Mail.app in 2021 and now to a fake Notes.app in 2022. These fake apps are invariably dropped in a parent folder created in random locations in the user’s Library folder. When executed, this particular sample writes the fake Notes.app to:

~/Library/Application Scripts/com.apple.CalendarAgent

The updated run-only AppleScripts that XCSSET drops as second-stage payloads use a collection of newly-registered domains:

set domains to {

Changes in the replicator.applescript file, which infects users’ Xcode projects with the XCSSET malware, show that both curl’s –max-time value and the script’s phaseName variable have now been randomized, presumably to hamper static detection or hunting rules.

Xcode infection script from 2021 (Left) and 2022 (Right)

The –max-time option is now set to a random value between 5 and 9, while phaseName is chosen from the following list:

"Copy Bundle Frameworks",
"Compile Binary Libraries",
"Compile Swift Frameworks",
"Binary Frameworks Compiler"

In the previous version of XCSSET, the malware created and dropped files for its own caches and control functions in a folder at ~/Library/Caches/GeoServices/. This has been modified slightly to “GitServices”.

Persistence plists are currently chosen from the following list:


and target a file at one of:


As previously, XCSSET continues to attempt to evade detection by masquerading as either system software or the almost ubiquitous Google and Chrome browser software.

XCSSET’s Updated Fake Notes.app

As noted, XCSSET makes use of a fake Notes.app to hide the primary executable, a.scpt, itself launched by the run-only compiled AppleScript main.scpt when “Notes” is executed via the dropped LaunchAgent.

The SHC-compiled dropper script defines several random paths to use as parent directories for the fake Notes.app.

osacompile -x -e try do shell script "osascript '/Users/user1/Library/Application Support/com.apple.spotlight/Notes.app/Contents/Resources/Scripts/a.scpt'" end try -o

The a.scpt remains, in essence, the same as earlier versions except that the encoding handler has changed from one previously shared with OSAMiner.

on xe(_str)
  set x to id of _str
  repeat with c in x
    set contents of c to c - (102 - 2)
   end repeat
  return string id x
end xe

on xex(_str)
  set x to id of _str
  repeat with c in x
    set contents of c to c - (102 - 1)
  end repeat
  return string id x
end xex

Malicious Run-Only AppleScripts

Aside from a.scpt, XCSSET makes use of multiple run-only AppleScripts. Although these scripts are written to disk as compiled and run-only, we were able to capture the scripts in plain text on the wire. In the updated version of XCSSET, these continue to target Telegram and other chat apps heavily in use by Chinese users such as WeChat and Tencent’s 360, along with an expanded list of browsers, including Opera, Brave, Edge and other Chromium-based browsers.

Many of the scripts shown above share the same structure and list of handlers but make minor changes to handle the specifics of each target application.

upload(filePath, fileName)

The contacts.applescript has the role of targeting various chat apps from which to steal and exfiltrate data.

Among other tasks, the payloader.applescript checks for AppleBackLightDisplay, presumably to distinguish between laptops and desktops. This info is part of what is exfiltrated, showing that the threat actors are keen to gather very precise hardware profiling information.

Similarly, the threat actors are interested in exactly how up-to-date the victim is with Apple’s XProtect and MRT malware removal tool, presumably all the better to target them with more effective payloads. The listing.applescript script is used for this purpose.

Also of interest is the use of the public service transfer.sh for exfiltrating data files that are too large for the attacker’s server.

XCSSET Changes for Monterey and Python

One of the more interesting things we noted in recent samples of XCSSET is the developer’s awareness of OS versions and the clear intent that the authors are here for the long run.

Right from its initial version, XCSSET made use of python scripts for certain functions, in particular for dropping fake application icons on the Dock. It achieved this by abusing a public Github repo called DockUtil. In the latest version, we also note that XCSSET uses python to parse and steal data from the user’s (legitimate) Notes.app. For this functionality, they use a modified version of a plugin from a legitimate python-based tool called mac_apt used by macOS forensics experts.

mac_apt on Github (left); malware script found in XCSSET (right)

XCSSET’s authors have updated their AppleScripts to account for Apple’s recent removal of python 2. The following image shows how the malware authors updated their safari_remote.applescript for python3 and Monterey 12.3 and above.

Similarly, the comment in edge_remote.applescript shows that the authors are keenly aware that DockUtil and other utilities will need to be replaced in their toolkit in the near future.

XCSSET Threat Actors and Targets

While very little is publicly known about the actors behind XCSSET, their motivations or their exact targets, the actors have engaged with journalists and security researchers at times. The original version of XCCSET, which appeared in August 2020, contained the full names of two individuals. Subsequently, a Twitter account with the name ‘Hans’ briefly became active and sent private messages to a journalist, claiming that he was the real author and not the two individuals whose names appeared in the malware code. The same individual claimed that the targets were “developers from China” and “big gambling business”.

‘Hans’ subsequently disappeared from view, but about a year later another Twitter account in the name of ‘Vlad F’ began reaching out to researchers, complaining that they had been falsely accused of being the actors behind the malware.

While Apple refused to comment on these claims at the time, Vlad F’s Twitter account ceased to respond. Earlier this year, however, Chinese users reported XCSSET infections and attempts to unlock stolen “accounts” from victims in return for “200 USDT” (a so-called “stable” bitcoin belonging to Tether).

Prior to that, researchers had noticed that XCSSET infections were being embedded in a number of Github repositories.

At this point in time, it’s unclear whether these infected repos are victims or plants by threat actors hoping to infect unwary users. It has been suggested that unsuspecting users may be pointed to the infected repositories through tutorials and screencasts for novice developers. Our research into XCSSET and its infection vectors continues.

Staying Protected Against XCSSET Malware on macOS

XCSSET has many moving parts, and samples change rapidly. While some static signatures such as those used in Apple’s XProtect service will detect known samples, full protection against evolving threats like these is only really possible with a multi-engine agent including behavioral AI.

SentinelOne Singularity fully protects SentinelOne customers against XCSSET malware.

With the agent policy set to ‘Protect’, the malware is prevented from executing or dropping any of its components. For this demonstration, we set the policy to ‘Detect-only’ in order to observe further stage payloads.

Indicators of Compromise

25f8d7ac99e00c9d69679f2d9aca5954d2609a03 ./brave_remote.applescript
0e1b2f01441e6e6fc8a48a7871e649d3647828cd ./canary_remote.applescript
4c368635ecfee61a89203f3f0e84bfdd7d85073d ./chrome_remote.applescript
2a2330b13886ffe0e4fe54f7254008490814b5fa ./chromium_remote.applescript
fd82b821fa2c23f2b88f64179e3a7a8905c1e40b ./contacts.applescript
bde20788e2656454052aae9baf2f4d2b7c256c9d ./edge_remote.applescript
3f35fd8306d4a05fadd9095acacd8d5f297a112e ./firefox_remote.applescript
3de232d0a42959b20703ebb9d9376b3ef3d3015d ./firewall_off.applescript
3257a1f540455444a56975e7fd9cdb6f8148b828 ./listing.applescript
2dbf06445a294b4f786501ef16ea4aabd8e1ad72 ./notes.applescript
6c0b4e3e3bac36f3228e69ab1e53884f76f6828b ./notes.py
6cf1ec6af6c6102c9d4929b1a83e0a463e737255 ./notes_app.applescript
73918b840384e485d009632fdf1a396758d7c515 ./opera_remote.applescript
e2de10a6b517e298cb2e7da150224dfe7e5717a7 ./payloader.applescript
5e673f4c494c424ae450f2ea5c0b066f912edccb ./pods_infect.applescript
73d9a443933fb0c40dde3065ec77adad35a5c49a ./remove_old.applescript
5b66e4b1556ad03b4bf072d061de0606eabe8603 ./replicator.applescript
672837de18d0e34f8b2a77bc2646b245671c83dc ./safari_remote.applescript
b66dbd55ce42a61cfedd06f31725b7f56d10d548 ./safari_update.applescript
fb29c9daa6fdeaa945446fe7cde185d51296dc7d ./telegram.applescript
760676a2e05d25959dee1f9ffaf3042e5f2e0f31 ./telegram_lite.applescript
4ffb268475e3816b22aadfb147bd7cd2f211e3d5 ./uploader.applescript
c2a90c68ad9d93139ebce981a409beae5d7de8bf ./yandex_remote.applescript
d70f4974bd531af674c5c2da3bc3c7d1a0ac9b54 ./360_remote.applescript
a57b73190525a729d821b6aed6849084fc1beddd ./a.applescript

127b66afa20a1c42e653ee4f4b64cf1ee3ed637d ./exec.2430808
f4099a0884d3f1bf5602c8c6ba5265b76d7f4953 ./Pods
dde87aefcaf788f770e5e1229db4fe73873e1c36 ./agentd
bd13d22095d377938c50088e59fa3079143cb0f2 ./braved
a1449c5fbf8cf126502bd68a8e8d657b3dcfd87a ./canaryd
cbf08fae71fcd46cc852fad7502685466c40e168 ./edged
2a62d6bcac7b0c5e75f561458e934ec45c77699c ./firefoxd
263b243df32be6d9d9878c459d2fc6491342d547 ./metald
f3a747bf10763d7d8c1cd9ccedd1e25ee195fce3 ./open
2a6d37160f21ec13aa6c692a3ca3374db3d35e96 ./operad
1396fdbff38b787d14b1135dcdfc367658669637 ./speedd
e4b6c56faa97493dc0f0f7c4fc2196096ef66513 ./yandexd