{
	"id": "6d996aac-21b1-4094-92a6-8e8596ac98fb",
	"created_at": "2026-04-06T00:09:59.64094Z",
	"updated_at": "2026-04-10T03:37:50.782786Z",
	"deleted_at": null,
	"sha1_hash": "ace97bc1a817631823c31e381a5644acad3e78fe",
	"title": "XAgentOSX: Sofacy’s XAgent macOS Tool",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 471982,
	"plain_text": "XAgentOSX: Sofacy’s XAgent macOS Tool\r\nBy Robert Falcone\r\nPublished: 2017-02-14 · Archived: 2026-04-05 21:33:42 UTC\r\nDuring our continued research on Sofacy’s Komplex Trojan, we have found a sample of a backdoor Trojan that we\r\nbelieve the Sofacy group uses when targeting individuals running macOS systems. The backdoor Trojan authors\r\nhave called it XAgentOSX, which shares the name XAgent with one of Sofacy’s Windows-based Trojan and\r\nreferences Apple’s previous name for macOS, OS X. It appears the same actor developed both the Komplex and\r\nXAgentOSX tools, based on similarities within the following project paths found within the tools:\r\nKomplex: /Users/kazak/Desktop/Project/komplex\r\nXAgent OSX: /Users/kazak/Desktop/Project/XAgentOSX\r\nWe believe it is possible that Sofacy uses Komplex to download and install the XAgentOSX tool to use its\r\nexpanded command set on the compromised system.\r\nXAgent C2 Communications\r\nThe macOS variant of XAgent has ability to receive commands from threat actors via its command and control\r\nchannel, but is also capable of logging key strokes via its keylogger functionality. XAgent uses HTTP requests to\r\ncommunicate with its C2 servers, which allows the threat actor to interact with the compromised system. The\r\nTrojan uses HTTP POST requests, as seen in Figure 1 to send data to the C2 server, and GET requests to receive\r\ncommands from the server, as seen in Figure 2. We are still analyzing this Trojan to determine the specific\r\nstructure of the data sent between the Trojan and the C2 server; however, it does appear that the Trojan is using the\r\nRC4 algorithm to encrypt data sent to the C2 server within HTTP POST requests.\r\nFigure 1 XAgent macOS HTTP POST request\r\nhttps://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/\r\nPage 1 of 7\n\nFigure 2 XAgent mscOS HTTP GET request\r\nThe C2 URLs generated by XAgentOSX are very similar to those created by its Windows-based counterpart.\r\nWhen generating the URL for the HTTP requests issued to the C2 server, the Trojan chooses a random folder from\r\nthe following to include within the URL path:\r\nwatch/?\r\nsearch/?\r\nfind/?\r\nresults/?\r\nopen/?\r\nsearch/?\r\nclose/?\r\nXAgent also will choose several parameters names from the following list when finishing the construction of the\r\nC2 URL:\r\nitwm=\r\ntext=\r\nfrom=.\r\nitwm=\r\nags=\r\noe=\r\naq=\r\nbtnG=\r\noprnd=\r\nitwm=\r\nutm=\r\nchannel=\r\nThe XAgent OSX Trojan generates a system specific value that it refers to as an \"agent_id\", which is a unique\r\nidentifier for each compromised host. The value is derived using the IOService to access the IOPlatformUUID\r\nproperty, which is equivalent to the \"Hardware UUID\" listed in the system information application, as seen in the\r\nFigure 3 screenshot of our analysis system. The Trojan uses the first four bytes of this hardware ID as a unique\r\nidentifier for the system, which in our case was \"0000\".\r\nhttps://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/\r\nPage 2 of 7\n\nFigure 3 Hardware ID used by XAgent to uniquely identify compromised hosts\r\nWhen generating the URLs within the HTTP POST and GET requests, XAgent sets one HTTP parameter using a\r\nspecific data structure that contains this agent_id value. This parameter transmits the agent_id to the C2 server to\r\nobtain commands the actor wishes to execute on the compromised system. The data structure used to transmit the\r\nagent_id to the C2 is as follows:\r\nstruct {\r\nDWORD random_value_for_key;\r\nCHAR[7] constant_value;\r\nDWORD agent_id;\r\n}\r\nThe constant value in the data structure is a 7 byte string that is hardcoded to \"\\x56\\x0E\\x9F\\xF0\\xEB\\x98\\x43\",\r\nfollowed by the agent_id value (\"0000\" in our case). The first DWORD in the data is a random value that the\r\nTrojan will use as an XOR key to encrypt the constant value and the agent_id. For instance, the following 15 bytes\r\nwere used to generate an HTTP parameter during our analysis:\r\nRandom Value Constant Value agent_id\r\n0F EE C8 83 56 0E 9F F0 EB 98 43 30 30 30 30\r\nThe resulting ciphertext is then encoded using XAgent's base64 encoding routine that starts by building the\r\nfollowing encoding alphabet:\r\nABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\r\nAs you can see, this is not the standard base64 alphabet, rather it is the \"URL and Filename safe\" Base 64\r\nAlphabet from RFC 4648, as the \"+\" in the standard alphabet is replaced with \"-\" and the \"/\" replaced with \"_\". It\r\nthen uses the base64 encoding function with this alphabet to encode the data, which in the above case resulted in:\r\nhttps://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/\r\nPage 3 of 7\n\nD-7Ig1ngV3PkdouzP974\nThe Trojan then creates a string of 9 random symbols and appends the encoded ciphertext to this random string.\nFor example, the following string would be included in one of the HTTP parameters sent to the C2 server:\neRmaVsr90D-7Ig1ngV3PkdouzP974\nIn this specific case, the actor made a mistake when configuring this XAgent sample with its C2 locations. The\nsample creates an array that contains the following strings for the Trojan to use as C2 locations:\nhttp://23.227.196[.]215/\nhttp://apple-iclods[.]org/\nhttp://apple-checker[.]org/\nhttp://apple-uptoday[.]org/\nhttp://apple-search[.]info\nNotice the last one is missing the trailing \"/\", which causes an issue when the Trojan attempts to use this string to\nbuild the remainder of the C2 URL, as the Trojan will append the next string in the URL directly to this string. For\ninstance, when using this string we observed DNS queries for \"apple-search.infoclose\", as the string \"close\" was\nsupposed to be the next portion of the C2 URL.\nAvailable Commands\nThe XAgent C2 server will provide commands for the Trojan to run on the compromised system within its\nresponse to inbound HTTP request. The XAgentOSX Trojan includes responses to commands within HTML tags,\nwhich we believe allows the C2 server to format logs for viewing.\nIn most cases, the responses sent to the C2 server are included between the \"\n\n\"\n    and \"\n\n\" HTML tags. We analyzed the command handler and found that it provided the necessary\ncommands for a fully functional backdoor, as seen in Table 1. The command handler obtains a command identifier\nfrom the C2 server and adds 0xFFFFFF9B to this value and then uses a switch statement to determine the\nappropriate command to execute. The switch statement checks for 19 cases, between 101 and 119. (Updated to\ncorrect command IDs, thanks @mykill!)\nCommand\nID\nFunction Description\n101 getInfoOSX\nGathers username and OSX version and responds using the\nencrypted form of the following string: \"Mac OS X - [OSX version]\nx64  \n\\nUser name - [username]\"\n102 getProcessList Runs \"ps aux\" to obtain a list of running processes\n103 remoteShell Runs supplied command using \"/bin/sh\"\nhttps://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/\nPage 4 of 7\n\n104 getInstalledAPP\nGets a list of installed applications by running the command \"ls -la\n/Applications\"\n105 showBackupIosFolder\nChecks to see if an IOS device was backed up to the system by\nrunning the command \"ls -la ~/Library/Application\\\nSupport/MobileSync/Backup/\"\n106 downloadFileFromPath Uploads a file from a specified path\n107 createFileInSystem\nDownloads a file, specifically provided within the C2 server's\nHTTP response\n108 execFile\nExecutes a specified file on the system using the NSTask:launch\nmethod\n109 deletFileFromPath\nDeletes a specified file using the NSFileManager:removeFileAtPath\nmethod\n110 takeScreenShot\nTakes a screenshot using the CGGetActiveDisplayList,\nCGDisplayCreateImage, NSImage:initWithCGImage methods.\nReturns the screenshot to the C2 via: ![](data:image/jpeg;base64,[base64 of screenshot])  \n111 startTakeScreenShot\nCreates a thread to take a screenshot at a set interval (default: every\n10 seconds). Uses the same method in \"takeScreenShot\" function\n112 stopTakeScreenShot Closes the thread created in the \"startTakeScreenShot\" function\n116 getFirefoxPassword\nLooks for folders with \"/Firefox/Profiles\" in the path and reads the\ncontents of the \"logins.json\" file for \"hostname\",\n\"encryptedUsername\" and \"encryptedPassword\" entries. It also\nattempts to issue the following SQL query on the \"signons.sqlite\"\nfile: \"SELECT hostname, encryptedUsername, encryptedPassword\nFROM moz_logins WHERE timePasswordChanged/1000\nBETWEEN ? AND ?\"\n117 ftpUpload\nUses FTPManager:uploadFile method and a supplied server name,\nusername and password.\n118 ftpStop\nCalls \"stopOperation\" method, but does not appear to stop FTP\nuploads.\n119 readFiles Obtains file information on a file or a folder, and supports a \"*\"\nwildcard and recursive file list. The code will gather the\ninformation and format the list using the following HTML to create\na table:\nhttps://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/\nPage 5 of 7\n\n| Type | Owner | Permissions | Created | Modificated | Size | Path |\n| --- | --- | --- | --- | --- | --- | --- |\n| [fileType] | [fileOwnerAccountName] | [number filePosixPermissions] | [fileCreationDate] | [fileModificationDate] | [fileSize] | [file path?] |\nTable 1 Commands available within XAgent OSX\nThe ‘showBackupIosFolder’ command is rather interesting, as it allows the threat actors to determine if a\ncompromised system was used to backup an IOS device, such as an iPhone or iPad. We believe this command is\nused to determine if a mobile device was backed up, and we speculate that the actors would use other commands\nwithin XAgent to exfiltrate those files.\nKeylogging Functionality\nXAgent also has a keylogger functionality that allows the threat actors to steal credentials as the user types them.\nXAgent logs key strokes by calling the CGEventTapCreate function to set an event hook to call a callback\nfunction named _myCGEventTapCallBack when it detects pressed keys. This callback function will call a\nfunction named pressedKeyWithKeyCode, which is responsible for logging the keystrokes. The keylogger will\nmonitor for active application windows and write them to the log in the following format:[Application Name] The keylogger will log a configurable amount of keystrokes (default 50) before sending the log to the C2 server\nusing the following format:[logged keystrokes] The keylogger can handle logging special keys, such as return and the function keys and will report those within\nthe log in the following format;[special character] Infrastructure\nThe XAgentOSX sample we analyzed was configured to use the following IP address and domain names as its C2\nservers:\n23.227.196[.]215\napple-iclods[.]org\nhttps://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/\nPage 6 of 7\n\napple-checker[.]org\r\napple-uptoday[.]org\r\napple-search[.]info\r\nWhen we analyzed this sample, the domain names that were used as backup C2 locations were not registered;\r\ntherefore, these domains did not provide any links to additional infrastructure. We were also unable to find any\r\nadditional infrastructure based on the primary C2 location of 23.227.196[.]215. However, according to\r\nCrowdStrike, the nearby IP address 23.227.196[.]217 hosted the C2 location for an XTunnel payload used by the\r\nSofacy group in the attack on the Democratic National Committee. While these IP addresses do not directly\r\noverlap, it does appear that the Sofacy group continues to use the same hosting services to host their\r\ninfrastructure.\r\nConclusion\r\nThe Sofacy group continues to bolster their toolset to carry out attack campaigns on multiple platforms. In this\r\ncase, the threat group uses the same name XAgent for this macOS-based tool as one of their Windows-based tools.\r\nAlso, the macOS variant of this tool uses a similar network communications method as its Windows counterpart,\r\nwhich suggests this group continues to use consolidated C2 services to control compromised hosts, as we saw\r\nduring our comparison of the Komplex and Seduploader (formerly referred to as Sofacy Carberp) tools. Also,\r\nwhile we lack attack telemetry, we were able to find a loose connection to the attack campaign that Sofacy waged\r\non the Democratic National Committee based on hosting data in both attacks.\r\nPalo Alto Networks customers are protected from XAgentOSX via:\r\nKnown samples are detected as malicious by WildFire\r\nAll known C2 locations are marked as malicious in PANDB\r\nUsers can use AutoFocus tag XAgent to track this threat\r\nIndicators of Compromise\r\nSHA256\r\n2a854997a44f4ba7e307d408ea2d9c1d84dde035c5dab830689aa45c5b5746ea\r\nCommand and Control\r\n23.227.196[.]215\r\napple-iclods[.]org\r\napple-checker[.]org\r\napple-uptoday[.]org\r\napple-search[.]info\r\nSource: https://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/\r\nhttps://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/\r\nPage 7 of 7",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/"
	],
	"report_names": [
		"unit42-xagentosx-sofacys-xagent-macos-tool"
	],
	"threat_actors": [
		{
			"id": "aa73cd6a-868c-4ae4-a5b2-7cb2c5ad1e9d",
			"created_at": "2022-10-25T16:07:24.139848Z",
			"updated_at": "2026-04-10T02:00:04.878798Z",
			"deleted_at": null,
			"main_name": "Safe",
			"aliases": [],
			"source_name": "ETDA:Safe",
			"tools": [
				"DebugView",
				"LZ77",
				"OpenDoc",
				"SafeDisk",
				"TypeConfig",
				"UPXShell",
				"UsbDoc",
				"UsbExe"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "2864e40a-f233-4618-ac61-b03760a41cbb",
			"created_at": "2023-12-01T02:02:34.272108Z",
			"updated_at": "2026-04-10T02:00:04.97558Z",
			"deleted_at": null,
			"main_name": "WildCard",
			"aliases": [],
			"source_name": "ETDA:WildCard",
			"tools": [
				"RustDown",
				"SysJoker"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "730dfa6e-572d-473c-9267-ea1597d1a42b",
			"created_at": "2023-01-06T13:46:38.389985Z",
			"updated_at": "2026-04-10T02:00:02.954105Z",
			"deleted_at": null,
			"main_name": "APT28",
			"aliases": [
				"Pawn Storm",
				"ATK5",
				"Fighting Ursa",
				"Blue Athena",
				"TA422",
				"T-APT-12",
				"APT-C-20",
				"UAC-0001",
				"IRON TWILIGHT",
				"SIG40",
				"UAC-0028",
				"Sofacy",
				"BlueDelta",
				"Fancy Bear",
				"GruesomeLarch",
				"Group 74",
				"ITG05",
				"FROZENLAKE",
				"Forest Blizzard",
				"FANCY BEAR",
				"Sednit",
				"SNAKEMACKEREL",
				"Tsar Team",
				"TG-4127",
				"STRONTIUM",
				"Grizzly Steppe",
				"G0007"
			],
			"source_name": "MISPGALAXY:APT28",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "256a6a2d-e8a2-4497-b399-628a7fad4b3e",
			"created_at": "2023-11-30T02:00:07.299845Z",
			"updated_at": "2026-04-10T02:00:03.484788Z",
			"deleted_at": null,
			"main_name": "WildCard",
			"aliases": [],
			"source_name": "MISPGALAXY:WildCard",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "e3767160-695d-4360-8b2e-d5274db3f7cd",
			"created_at": "2022-10-25T16:47:55.914348Z",
			"updated_at": "2026-04-10T02:00:03.610018Z",
			"deleted_at": null,
			"main_name": "IRON TWILIGHT",
			"aliases": [
				"APT28 ",
				"ATK5 ",
				"Blue Athena ",
				"BlueDelta ",
				"FROZENLAKE ",
				"Fancy Bear ",
				"Fighting Ursa ",
				"Forest Blizzard ",
				"GRAPHITE ",
				"Group 74 ",
				"PawnStorm ",
				"STRONTIUM ",
				"Sednit ",
				"Snakemackerel ",
				"Sofacy ",
				"TA422 ",
				"TG-4127 ",
				"Tsar Team ",
				"UAC-0001 "
			],
			"source_name": "Secureworks:IRON TWILIGHT",
			"tools": [
				"Downdelph",
				"EVILTOSS",
				"SEDUPLOADER",
				"SHARPFRONT"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "ae320ed7-9a63-42ed-944b-44ada7313495",
			"created_at": "2022-10-25T15:50:23.671663Z",
			"updated_at": "2026-04-10T02:00:05.283292Z",
			"deleted_at": null,
			"main_name": "APT28",
			"aliases": [
				"APT28",
				"IRON TWILIGHT",
				"SNAKEMACKEREL",
				"Group 74",
				"Sednit",
				"Sofacy",
				"Pawn Storm",
				"Fancy Bear",
				"STRONTIUM",
				"Tsar Team",
				"Threat Group-4127",
				"TG-4127",
				"Forest Blizzard",
				"FROZENLAKE",
				"GruesomeLarch"
			],
			"source_name": "MITRE:APT28",
			"tools": [
				"Wevtutil",
				"certutil",
				"Forfiles",
				"DealersChoice",
				"Mimikatz",
				"ADVSTORESHELL",
				"Komplex",
				"HIDEDRV",
				"JHUHUGIT",
				"Koadic",
				"Winexe",
				"cipher.exe",
				"XTunnel",
				"Drovorub",
				"CORESHELL",
				"OLDBAIT",
				"Downdelph",
				"XAgentOSX",
				"USBStealer",
				"Zebrocy",
				"reGeorg",
				"Fysbis",
				"LoJax"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "d2516b8e-e74f-490d-8a15-43ad6763c7ab",
			"created_at": "2022-10-25T16:07:24.212584Z",
			"updated_at": "2026-04-10T02:00:04.900038Z",
			"deleted_at": null,
			"main_name": "Sofacy",
			"aliases": [
				"APT 28",
				"ATK 5",
				"Blue Athena",
				"BlueDelta",
				"FROZENLAKE",
				"Fancy Bear",
				"Fighting Ursa",
				"Forest Blizzard",
				"G0007",
				"Grey-Cloud",
				"Grizzly Steppe",
				"Group 74",
				"GruesomeLarch",
				"ITG05",
				"Iron Twilight",
				"Operation DealersChoice",
				"Operation Dear Joohn",
				"Operation Komplex",
				"Operation Pawn Storm",
				"Operation RoundPress",
				"Operation Russian Doll",
				"Operation Steal-It",
				"Pawn Storm",
				"SIG40",
				"Sednit",
				"Snakemackerel",
				"Sofacy",
				"Strontium",
				"T-APT-12",
				"TA422",
				"TAG-0700",
				"TAG-110",
				"TG-4127",
				"Tsar Team",
				"UAC-0028",
				"UAC-0063"
			],
			"source_name": "ETDA:Sofacy",
			"tools": [
				"ADVSTORESHELL",
				"AZZY",
				"Backdoor.SofacyX",
				"CHERRYSPY",
				"CORESHELL",
				"Carberp",
				"Computrace",
				"DealersChoice",
				"Delphacy",
				"Downdelph",
				"Downrage",
				"Drovorub",
				"EVILTOSS",
				"Foozer",
				"GAMEFISH",
				"GooseEgg",
				"Graphite",
				"HATVIBE",
				"HIDEDRV",
				"Headlace",
				"Impacket",
				"JHUHUGIT",
				"JKEYSKW",
				"Koadic",
				"Komplex",
				"LOLBAS",
				"LOLBins",
				"Living off the Land",
				"LoJack",
				"LoJax",
				"MASEPIE",
				"Mimikatz",
				"NETUI",
				"Nimcy",
				"OCEANMAP",
				"OLDBAIT",
				"PocoDown",
				"PocoDownloader",
				"Popr-d30",
				"ProcDump",
				"PythocyDbg",
				"SMBExec",
				"SOURFACE",
				"SPLM",
				"STEELHOOK",
				"Sasfis",
				"Sedkit",
				"Sednit",
				"Sedreco",
				"Seduploader",
				"Shunnael",
				"SkinnyBoy",
				"Sofacy",
				"SofacyCarberp",
				"SpiderLabs Responder",
				"Trojan.Shunnael",
				"Trojan.Sofacy",
				"USB Stealer",
				"USBStealer",
				"VPNFilter",
				"Win32/USBStealer",
				"WinIDS",
				"Winexe",
				"X-Agent",
				"X-Tunnel",
				"XAPS",
				"XTunnel",
				"Xagent",
				"Zebrocy",
				"Zekapab",
				"carberplike",
				"certutil",
				"certutil.exe",
				"fysbis",
				"webhp"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434199,
	"ts_updated_at": 1775792270,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/ace97bc1a817631823c31e381a5644acad3e78fe.pdf",
		"text": "https://archive.orkl.eu/ace97bc1a817631823c31e381a5644acad3e78fe.txt",
		"img": "https://archive.orkl.eu/ace97bc1a817631823c31e381a5644acad3e78fe.jpg"
	}
}