{
	"id": "4885a535-27d9-43cb-b765-3337413956ae",
	"created_at": "2026-04-06T00:07:05.60349Z",
	"updated_at": "2026-04-10T13:12:25.431383Z",
	"deleted_at": null,
	"sha1_hash": "b21732aa3237d8ea8967100cf7878358c40d2ccc",
	"title": "OceanLotus: macOS malware update",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 568197,
	"plain_text": "OceanLotus: macOS malware update\r\nBy Romain Dumont\r\nArchived: 2026-04-05 14:00:53 UTC\r\nESET Research\r\nLatest ESET research describes the inner workings of a recently found addition to OceanLotus’s toolset for\r\ntargeting Mac users\r\n09 Apr 2019  •  , 7 min. read\r\nEarly in March 2019, a new macOS malware sample from the OceanLotus group was uploaded to VirusTotal, a\r\npopular online multi-scanner service. This backdoor executable bears the same features as the previous macOS\r\nvariant we looked at, but its structure has changed and its detection was made harder. Unfortunately, we couldn't\r\nfind the dropper associated with this sample so we do not know the initial compromise vector.\r\nWe recently published a detailed update about OceanLotus and how its operators employ a wide range of\r\ntechniques to gain code execution, achieve persistence, and leave as little trace as possible on a Windows system.\r\nOceanLotus is also known to have a malicious macOS component. This article details what has changed from the\r\nprevious macOS version analyzed by Trend Micro and describes how, while analyzing this variant’s code, you can\r\nautomate string decryption using the IDA Hex-Rays API.\r\nAnalysis\r\nhttps://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/\r\nPage 1 of 8\n\nThe following three sections of this blogpost describe the analysis of the sample with the SHA-1 hash\r\nE615632C9998E4D3E5ACD8851864ED09B02C77D2. The file is named flashlightd and is detected by ESET\r\nproducts as OSX/OceanLotus.D.\r\nAnti-debug and anti-sandbox\r\nAs usual for OceanLotus macOS binaries, the sample is packed with UPX, but most packer identification tools do\r\nnot recognize it as such, probably because they mostly include a signature that relies on the presence of a “UPX”\r\nstring, and further, Mach-O signatures are less common and not as regularly updated. This particular characteristic\r\nmakes static detection more difficult. Once unpacked, one interesting thing is that the entry point is located at the\r\nbeginning of the __cfstring section in the .TEXT segment. This section has the flag attributes seen in Figure 1.\r\nFigure 1. MACH-O __cfstring section attributes\r\nAs seen in Figure 2, the fact that the code is in the __cfstring section tricks some disassembly tools to display the\r\ncode as strings.\r\nFigure 2. The backdoor code is defined as data by IDA\r\nWhen run, the binary first creates a thread as an anti-debugging watchdog whose sole purpose is to continuously\r\ncheck if a debugger is present. In order to do that, this thread:\r\nTries to detach any debugger by calling ptrace with PT_DENY_ATTACH as a request parameter\r\nChecks if some exception ports are open by calling the task_get_exception_ports function\r\nhttps://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/\r\nPage 2 of 8\n\nChecks if a debugger is attached, as seen in Figure 3, by verifying if the P_TRACED flag is set in the\r\ncurrent process\r\nFigure 3. Check if a debugger is attached via sysctl function\r\nIf the watchdog detects that a debugger is present the exit function is called. Moreover, the sample then checks its\r\nenvironment by issuing the following two commands:\r\nioreg -l | grep -e \"Manufacturer\" and sysctl hw.model\r\nand checks the return value against a hardcoded list of known virtualization system strings: oracle, vmware,\r\nvirtualbox or parallels. Finally, the command:\r\nsystem_profiler SPHardwareDataType 2\u003e/dev/null | awk '/Boot ROM Version/ {split($0, line, \":\");printf(\"%s\",\r\nline[2]);}\r\nchecks if the machine is one of the following: \"MBP\", “MBA”, “MB”, “MM”, “IM”, “MP” and “XS”. These\r\ncodes represent the model of the system. For instance, “MBP” stands for MacBook Pro, “MBA” stands for\r\nMacBook Air and so on…\r\nMajor updates\r\nEven though the backdoor commands have not changed since the Trend Micro article, we noticed a few other\r\nmodifications. The C\u0026C servers used for this sample are quite recent as their creation date is 2018-10-22.\r\ndaff.faybilodeau[.]com\r\nsarc.onteagleroad[.]com\r\nau.charlineopkesston[.]com\r\nThe URL resource used has changed to /dp/B074WC4NHW/ref=gbps_img_m-9_62c3_750e6b35.\r\nThe first packet that is sent to the C\u0026C server contains more information regarding the host machine. All data\r\ngathered by the commands in the following table are included.\r\nhttps://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/\r\nPage 3 of 8\n\nCommands Description\r\nsystem_profiler SPHardwareDataType 2\u003e/dev/null\r\nawk '/Processor / {split($0,line,\":\"); printf(\"%s\",line[2]);}'\r\nmachdep.cpu.brand_string\r\nGather processor information\r\nsystem_profiler SPHardwareDataType 2\u003e/dev/null\r\nawk '/Memory/ {split($0,line, \":\"); printf(\"%s\", line[2]);}'\r\nGather memory information\r\nifconfig -l\r\nGather network interface MAC\r\naddresses\r\nioreg -rd1 -c IOPlatformExpertDevice\r\nawk '/IOPlatformSerialNumber/ { split($0, line, \"\\\"\");\r\nprintf(\"%s\", line[4]); }'\r\nRetrieves the serial number of the\r\ndevice\r\nOn top of this configuration change, this sample does not use the libcurl library for network exfiltration. Instead, it\r\nuses an external library. To locate it, the backdoor tries to decrypt each file in the current directory using AES-256-\r\nCBC with the key gFjMXBgyXWULmVVVzyxy padded with zeroes. Each file is “decrypted” and saved as\r\n/tmp/store and an attempt to load it as a library made using the dlopen function. When a decryption attempt results\r\nin a successful call to dlopen, the backdoor then retrieves the exported functions Boriry and ChadylonV, which\r\nseem to be responsible for the network communication with the server. As we do not have the dropper or other\r\nfiles from the original sample’s location, we could not analyse this library. Moreover, since the component is\r\nencrypted, a YARA rule based on these strings would not match the file found on disk.\r\nAs described in the analysis of the group’s previous macOS backdoor, a clientID is created. This identifier is the\r\nMD5 hash of the return value of one of the following commands:\r\nioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformSerialNumber/ { split($0, line, \"\\\"\"); printf(\"%s\",\r\nline[4]); }'\r\nioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { split($0, line, \"\\\"\"); printf(\"%s\", line[4]);\r\n}'\r\nifconfig en0 | awk \\'/ether /{print $2}\\' (obtain the MAC address)\r\nan unknown command (\"\\x1e\\x72\\x0a\") which used to be “uuidgen” in the previous samples\r\nBefore being hashed, the character “0” or “1” is appended to the return value indicating root privileges. This\r\nclientID is stored in /Library/Storage/File System/HFS/25cf5d02-e50b-4288-870a-528d56c3cf6e/pivtoken.appex\r\nif the code runs as root, or in ~/Library/SmartCardsServices/Technology/PlugIns/drivers/snippets.ecgML\r\notherwise. This file is normally hidden via the _chflags function and its timestamp is modified using the “touch –\r\nt” command with a random value.\r\nhttps://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/\r\nPage 4 of 8\n\nString decryption\r\nLike previous variants, the strings are encrypted using AES-256-CBC (hex-encoded key:\r\n9D7274AD7BCEF0DED29BDBB428C251DF8B350B92 padded with zeroes and the IV is filled with zeroes)\r\nusing the CCCrypt function. The key has changed from previous versions but since the group is still using the\r\nsame algorithm to encrypt strings, decryption could be automated. Along with this article, we are releasing an IDA\r\nscript leveraging the Hex-Rays API to decrypt the strings present in the binary. This script may help future\r\nanalysis of OceanLotus and the analysis of existing samples that we have not yet been able to obtain. At the core\r\nof this script lies a generic method to obtain the arguments passed to a function. Moreover, it looks for the\r\nparameter assignments in order to find their values. This method could be reused to retrieve the list of arguments\r\nof a function and then pass them to a callback.\r\nKnowing the prototype of the decrypt function, the script first finds all cross-references to this function, finds all\r\nthe arguments, decrypts the data and puts the plaintext inside a comment at the address of the cross-reference. In\r\norder for the script to work correctly, the custom alphabet used by the base64 decode function must be set in the\r\nscript and the global variable containing the length of the key must be defined (as a DWORD in this case; see\r\nFigure 4).\r\nFigure 4. Defining the global variable key_len\r\nIn the Function window, you can right-click the decryption function and click “Extract and decrypt arguments”.\r\nThe script should put the decrypted strings in comments, much as in Figure 5.\r\nhttps://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/\r\nPage 5 of 8\n\nFigure 5. Decrypted text is put into comments\r\nThis conveniently lists the decrypted strings together in IDA’s xrefs to window for that function, as seen in\r\nFigure 6.\r\nFigure 6. Xrefs to of f_decrypt function\r\nThe final script can be found on our Github repository.\r\nhttps://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/\r\nPage 6 of 8\n\nConclusion\r\nAs recently documented in another of our articles, the OceanLotus group keeps improving and updating its\r\ntoolset, and once again, it has improved its tools for targeting Mac users. The code has not changed that much, but\r\nbecause many Mac users don’t run security software on their machines, the need to evade detection is of less\r\nimportance. ESET products already detected this file when we found it. Since the network library used for the\r\nC\u0026C communication is now encrypted on the disk, the exact network protocol used remains unknown.\r\nIndicators of Compromise (IoCs)\r\nThe IoCs in this blogpost, as well as the MITRE ATT\u0026CK attributes, are also available in our GitHub repository.\r\nDomain names\r\ndaff.faybilodeau[.]com\r\nsarc.onteagleroad[.]com\r\nau.charlineopkesston[.]com\r\nURL resource\r\n/dp/B074WC4NHW/ref=gbps_img_m-9_62c3_750e6b35\r\nFile paths\r\n~/Library/SmartCardsServices/Technology/PlugIns/drivers/snippets.ecgML\r\n/Library/Storage/File System/HFS/25cf5d02-e50b-4288-870a-528d56c3cf6e/pivtoken.appex\r\n/tmp/store\r\nSample analyzed SHA-1 hash ESET detection name\r\nfleshlightd E615632C9998E4D3E5ACD8851864ED09B02C77D2 OSX/OceanLotus.D\r\nMITRE ATT\u0026CK techniques\r\nTactic ID Name Description\r\nDefense\r\nEvasion\r\nT1158\r\nHidden Files and\r\nDirectories\r\nThe backdoor hides the clientID file via chflags\r\nfunction.\r\nT1107 File Deletion The backdoor can receive a “delete” command.\r\nT1222\r\nFile Permissions\r\nModification\r\nThe backdoor changes the permission of the file\r\nit wants to execute to 755.\r\nhttps://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/\r\nPage 7 of 8\n\nTactic ID Name Description\r\nT1027\r\nObfuscated Files or\r\nInformation\r\nThe library used for network exfiltration is\r\nencrypted with AES-256 in CBC mode.\r\nT1099\r\n(macOS)\r\nTimestomp\r\nThe timestamp of the file storing the clientID is\r\nmodified with a random value.\r\nDiscovery T1082\r\nSystem Information\r\nDiscovery\r\nThe backdoor performs a fingerprint of the\r\nmachine on its first connection to the C\u0026C\r\nserver.\r\nExfiltration T1022 Data Encrypted\r\nThe backdoor encrypts the data before\r\nexfiltration.\r\nCommand and\r\nControl\r\nT1094\r\nCustom Command and\r\nControl Protocol\r\nThe backdoor implements a specific format for\r\nthe packet involving random values. See Trend\r\nMicro article.\r\nSource: https://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/\r\nhttps://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/\r\nPage 8 of 8",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia",
		"MITRE",
		"ETDA"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.welivesecurity.com/2019/04/09/oceanlotus-macos-malware-update/"
	],
	"report_names": [
		"oceanlotus-macos-malware-update"
	],
	"threat_actors": [
		{
			"id": "af509bbb-8d18-4903-a9bd-9e94099c6b30",
			"created_at": "2023-01-06T13:46:38.585525Z",
			"updated_at": "2026-04-10T02:00:03.030833Z",
			"deleted_at": null,
			"main_name": "APT32",
			"aliases": [
				"OceanLotus",
				"ATK17",
				"G0050",
				"APT-C-00",
				"APT-32",
				"Canvas Cyclone",
				"SeaLotus",
				"Ocean Buffalo",
				"OceanLotus Group",
				"Cobalt Kitty",
				"Sea Lotus",
				"APT 32",
				"POND LOACH",
				"TIN WOODLAWN",
				"Ocean Lotus"
			],
			"source_name": "MISPGALAXY:APT32",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "870f6f62-84f5-48ca-a18e-cf2902cd6924",
			"created_at": "2022-10-25T15:50:23.303818Z",
			"updated_at": "2026-04-10T02:00:05.301184Z",
			"deleted_at": null,
			"main_name": "APT32",
			"aliases": [
				"APT32",
				"SeaLotus",
				"OceanLotus",
				"APT-C-00",
				"Canvas Cyclone"
			],
			"source_name": "MITRE:APT32",
			"tools": [
				"Mimikatz",
				"ipconfig",
				"Kerrdown",
				"Cobalt Strike",
				"SOUNDBITE",
				"OSX_OCEANLOTUS.D",
				"KOMPROGO",
				"netsh",
				"RotaJakiro",
				"PHOREAL",
				"Arp",
				"Denis",
				"Goopy"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "f9806b99-e392-46f1-9c13-885e376b239f",
			"created_at": "2023-01-06T13:46:39.431871Z",
			"updated_at": "2026-04-10T02:00:03.325163Z",
			"deleted_at": null,
			"main_name": "Watchdog",
			"aliases": [
				"Thief Libra"
			],
			"source_name": "MISPGALAXY:Watchdog",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "5da6b5fd-1955-412a-81aa-069fb50b6e31",
			"created_at": "2025-08-07T02:03:25.116085Z",
			"updated_at": "2026-04-10T02:00:03.668978Z",
			"deleted_at": null,
			"main_name": "TIN WOODLAWN",
			"aliases": [
				"APT32 ",
				"Cobalt Kitty",
				"OceanLotus",
				"WOODLAWN "
			],
			"source_name": "Secureworks:TIN WOODLAWN",
			"tools": [
				"Cobalt Strike",
				"Denis",
				"Goopy",
				"JEShell",
				"KerrDown",
				"Mimikatz",
				"Ratsnif",
				"Remy",
				"Rizzo",
				"RolandRAT"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "2439ad53-39cc-4fff-8fdf-4028d65803c0",
			"created_at": "2022-10-25T16:07:23.353204Z",
			"updated_at": "2026-04-10T02:00:04.55407Z",
			"deleted_at": null,
			"main_name": "APT 32",
			"aliases": [
				"APT 32",
				"APT-C-00",
				"APT-LY-100",
				"ATK 17",
				"G0050",
				"Lotus Bane",
				"Ocean Buffalo",
				"OceanLotus",
				"Operation Cobalt Kitty",
				"Operation PhantomLance",
				"Pond Loach",
				"SeaLotus",
				"SectorF01",
				"Tin Woodlawn"
			],
			"source_name": "ETDA:APT 32",
			"tools": [
				"Agentemis",
				"Android.Backdoor.736.origin",
				"AtNow",
				"Backdoor.MacOS.OCEANLOTUS.F",
				"BadCake",
				"CACTUSTORCH",
				"CamCapture Plugin",
				"CinaRAT",
				"Cobalt Strike",
				"CobaltStrike",
				"Cuegoe",
				"DKMC",
				"Denis",
				"Goopy",
				"HiddenLotus",
				"KOMPROGO",
				"KerrDown",
				"METALJACK",
				"MSFvenom",
				"Mimikatz",
				"Nishang",
				"OSX_OCEANLOTUS.D",
				"OceanLotus",
				"PHOREAL",
				"PWNDROID1",
				"PhantomLance",
				"PowerSploit",
				"Quasar RAT",
				"QuasarRAT",
				"RatSnif",
				"Remy",
				"Remy RAT",
				"Rizzo",
				"Roland",
				"Roland RAT",
				"SOUNDBITE",
				"Salgorea",
				"Splinter RAT",
				"Terracotta VPN",
				"Yggdrasil",
				"cobeacon",
				"denesRAT",
				"fingerprintjs2"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434025,
	"ts_updated_at": 1775826745,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/b21732aa3237d8ea8967100cf7878358c40d2ccc.pdf",
		"text": "https://archive.orkl.eu/b21732aa3237d8ea8967100cf7878358c40d2ccc.txt",
		"img": "https://archive.orkl.eu/b21732aa3237d8ea8967100cf7878358c40d2ccc.jpg"
	}
}