{
	"id": "7fa44094-2b05-4b17-bc0a-0771c90204d0",
	"created_at": "2026-04-06T01:28:55.074909Z",
	"updated_at": "2026-04-10T03:23:51.84505Z",
	"deleted_at": null,
	"sha1_hash": "119ebb6b211bb4c19e14fe101c66307631eae1f5",
	"title": "Coming Out of Your Shell: From Shlayer to ZShlayer",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 13780665,
	"plain_text": "Coming Out of Your Shell: From Shlayer to ZShlayer\r\nBy Phil Stokes\r\nPublished: 2020-09-08 · Archived: 2026-04-06 00:08:03 UTC\r\nEarlier this year, we discussed how threat actors have been turning to scripting languages as a preferred means of\r\nboth dropping malware and executing payloads. That trend has continued with some interesting innovations in\r\nresponse to the static detection signatures now widely in use both by Apple and other vendors. A recent variant of\r\nthe Shlayer malware follows Apple’s lead in preferring Zsh to Bash as its default shell language and employs a\r\nnovel encoding method to avoid detection. In this post, we describe this variant and show how it can be decoded\r\nto reveal the telltale Shlayer signature.\r\nDidn’t We Just Hear About Shlayer?\r\nShlayer is perhaps the most talked about macOS malware at the moment and hit the news again recently after\r\nbeing caught sneaking past Apple’s macOS Notarization checks. That version of Shlayer was an interesting\r\ndiversion: using a Mach-O binary written in C++ to execute a Bash shell script in memory. That might well\r\nsuggest that Apple’s Notarization checks are static rather than dynamic as the telltale Shlayer code is only evident\r\nonce the packed binary runs:\r\nsh -c “tail -c +1381 \"/Volumes/Install/Installer.app/Contents/Resources/main.png\" | openssl enc -aes-The classic Shlayer technique is clearly evident here: passing encrypted and password-protected code to openssl\r\nand then writing that out as a payload to the /tmp folder.\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 1 of 11\n\nBut Shlayer has been up to other tricks since June of 2020 that have been helping it avoid the static signatures\r\nemployed by most vendors. Although bypassing Apple’s Notarization checks is obviously a headline grabber, this\r\nnew variant of Shlayer utilizes heavily obfuscated Zsh scripts and is in fact far more prolific in the wild. Let’s take\r\na look at how this new variant works.\r\nInside the New ZShlayer Variant\r\nWhereas earlier versions of Shlayer like Shlayer.a came as shell script executables on a removable .DMG disk\r\nimage, the new ZShlayer malware goes back to using a standard Apple application bundle inside the .DMG.\r\nIn place of a Mach-O in the MacOS folder, we instead find this heavily obfuscated Zsh script (only partially\r\nshown in the image below):\r\nIn the Resources folder, we find two base64 encoded text files.\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 2 of 11\n\nThe entire bundle is codesigned, but it is has not been notarized, indicating that the malware is either intended as a\r\npayload for 10.14 or earlier installations or that victims will have to be socially engineered to override the\r\nNotarization check. Unlike many other samples we have seen since Catalina was released last year, this one did\r\nnot include graphical instructions to help the user bypass Apple’s built-in security checks.\r\nThis particular sample ( c561d62c786c757a660c47d133b6d23e030a40c4aa08aebe44b8c4a7711da580 ), which dates\r\nback to early August, has already had its certificate revoked by Apple.\r\nDespite that, due to the use of the Zsh obfuscation, it’s not particularly well-recognized by static signature\r\nscanners on VirusTotal, even as of today.\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 3 of 11\n\nDecoding the First Stage, Zsh Script Payload\r\nIn the following, we’ll use this as for our example:\r\n05b0a4a31f38225d5ad9d133d08c892645639c4661b3e239ef2094381366cb62\r\nBut the same general method should work across all ZShlayer samples noted at the end of this post.\r\nThe Zsh script located in the bundle’s MacOS folder may seem fairly impenetrable at first glance, as indeed it is\r\nintended to:\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 4 of 11\n\nSeeing from the shebang that it’s a shell script, however, immediately tells us that we can isolate each command\r\nby introducing a line break at every semicolon.\r\nIn BBEdit or similar text editor, we can simply search and replace every semicolon with a semicolon and newline:\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 5 of 11\n\nLooking toward the end of that output, we can clearly see now where the variable definitions end and the\r\nexecution logic begins, at line 164:\r\nNote in particular the variable TWm , defined on the penultimate line and executed at line 164. This variable name\r\nwill prove key as we try to deobfuscate the code.\r\nIn order to do that, we’ll first save this modified version of the script with the linebreaks to local disk so that we\r\ncan use it as input to a python script for decoding. Our script will first of all replace all the variable names with the\r\nactual unicode values. Now the line that gets executed looks something like this:\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 6 of 11\n\nWe can echo that code on the command line and print out the unicode in plain text using printf . The full\r\nZShlayer_decode.py script is available here. Here’s what all the above looks like.\r\nAnd the output:\r\nZShlayer Second-Stage Payload\r\nYou’ll notice from the output that the decoded Zsh script takes as input only the smaller of the two encoded files\r\nfrom the Resources folder; in this case, the smaller file is called “tun_kibitzers_Babbitt”. If we echo the output\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 7 of 11\n\nfrom this decoded script to the command line, we’ll see why:\r\nOur ZShlayer script decodes into a trademark Shlayer Bash script which now takes the larger file (here called\r\n“profanations_detraction”) and outputs it to a newly-created application bundle in the /tmp folder. Classic Shlayer\r\nbehavior.\r\nLet’s take that script and comment out the last two lines so that we can get the output while still preventing\r\nexecution:\r\nThe unzipped Player.app now in the /tmp folder looks like a duplicate of the one on the original disk image, with\r\nthe same executable name as the parent and another Bash script in the Resources folder also called\r\n“tun_kibitzers_Babbitt” (in this case). However, note the size is different:\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 8 of 11\n\nDecoding the new script shows that it drops and executes yet another layer of Bash shell scripting. Here’s the head\r\nand tail (sandwiched between the two is a huge chunk of base64):\r\nIf you followed (or want to check out) our earlier Scripting Macs with Malice post, you’ll recognize that this is the\r\nShlayer.d variant we wrote about there. The output of\r\n\"$(_m \"$_t\" \"$_y\")\"\r\nis almost identical to the Shlayer.d sample we wrote about earlier; the most significant difference being a new\r\nURL from which to retrieve the final payload:\r\nhttp[:]//dqb2corklaq0k[.]cloudfront[.]net/\r\n13[.]226[.]23[.]203\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 9 of 11\n\nThe final payload from this point depends on the context of the executing device. As can be seen above, the script\r\ngathers OS version, a session UID and machine ID, all of which it posts to the server for processing.\r\nThe server, which appears to have been up for at least two months, is not recognized as malicious on VirusTotal\r\nand is currently active with a 200 status code.\r\nAs Shlayer payloads have been discussed in detail by other researchers, we refer further analysis of the final\r\npayload to already published work such as here and here.\r\nHow Prevalent is ZShlayer in the Wild?\r\nSearching for ZShlayer on VirusTotal reveals a large number of individual samples and shows that this variant has\r\nbeen active since late June 2020. As of today, our latest retrohunt showed 172 samples. Some of the parent DMGs\r\nof these samples have a reputation score of 0/58 on VT.\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 10 of 11\n\nConclusion\r\nThe ZShlayer variant of the Shlayer malware on top of the recent Shlayer campaign abusing Apple’s Notarization\r\nservice is clear evidence that these threat actors are continuing to evolve and are pursuing multiple campaigns\r\nagainst macOS users. A multi-engined behavioral AI solution that can detect malware based on its behavior rather\r\nthan relying solely on file characteristics continues to be the best way to protect your macOS fleet. If you would\r\nlike to see how SentinelOne can help protect your business, contact us today or request a free demo.\r\nIndicators of Compromise\r\nZShlayer Scripts\r\n269d5f15da3bc3522ca53a3399dbaf4848f86de35d78c636a78336d46c23951c\r\ne3292268c1d0830e76c3e80b4ea57921b9171027e07f064ef3b867b6d0450191\r\n93ff20ff59d4e82e9c0e3b08037c48886dc54b8ed37c19894e0a65c1af8612f6\r\nc561d62c786c757a660c47d133b6d23e030a40c4aa08aebe44b8c4a7711da580\r\n16885c2443b610d80b30828b1445ca326adb727c48f06d073e4dcb70fe3e5c2e\r\n1bc5d3cb3d885fad8230e01dc5f86145d16ed5552a0fa8725689635b96b681e1\r\nParent DMGs\r\nf6cb7f9593d85f0cd1e81d5b9f520b74d9bf5e829206cefe05b956c0f7638c28\r\n3e20c0b2979a368c7d38cf305f1f60693375165bb76150ad80dbd34e7e0550ed\r\nc319761789afb6aa9cddadf340dfa2d4d659e4b420d6dfde9640cdc4c1d813b7\r\n823c4d39b0d93a1358b4fa02539868944ce15df91f78a1142be26edf07a64a5a\r\n45d50559f73e7c12f1d9aa06283182cb67ac953d285f044e77447569ca8a278c\r\nf94c8712dd7716cfeac79e6e59fdca07db4452c5d239593f421f97246ee8ef41\r\nDomains\r\nhttp[:]//dqb2corklaq0k[.]cloudfront[.]net/\r\n13[.]226[.]23[.]203\r\nSource: https://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nhttps://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/\r\nPage 11 of 11",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://www.sentinelone.com/blog/coming-out-of-your-shell-from-shlayer-to-zshlayer/"
	],
	"report_names": [
		"coming-out-of-your-shell-from-shlayer-to-zshlayer"
	],
	"threat_actors": [
		{
			"id": "d90307b6-14a9-4d0b-9156-89e453d6eb13",
			"created_at": "2022-10-25T16:07:23.773944Z",
			"updated_at": "2026-04-10T02:00:04.746188Z",
			"deleted_at": null,
			"main_name": "Lead",
			"aliases": [
				"Casper",
				"TG-3279"
			],
			"source_name": "ETDA:Lead",
			"tools": [
				"Agentemis",
				"BleDoor",
				"Cobalt Strike",
				"CobaltStrike",
				"RbDoor",
				"RibDoor",
				"Winnti",
				"cobeacon"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775438935,
	"ts_updated_at": 1775791431,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/119ebb6b211bb4c19e14fe101c66307631eae1f5.pdf",
		"text": "https://archive.orkl.eu/119ebb6b211bb4c19e14fe101c66307631eae1f5.txt",
		"img": "https://archive.orkl.eu/119ebb6b211bb4c19e14fe101c66307631eae1f5.jpg"
	}
}