# XAgentOSX: Sofacy’s XAgent macOS Tool
**[researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/](http://researchcenter.paloaltonetworks.com/2017/02/unit42-xagentosx-sofacys-xagent-macos-tool/)**
Robert Falcone February 14, 2017
By [Robert Falcone](https://unit42.paloaltonetworks.com/author/robertfalcone/)
February 14, 2017 at 3:59 PM
[Category: Unit 42](https://unit42.paloaltonetworks.com/category/unit42/)
Tags: [macOS,](https://unit42.paloaltonetworks.com/tag/macos/) [Sofacy,](https://unit42.paloaltonetworks.com/tag/sofacy/) [XAgent,](https://unit42.paloaltonetworks.com/tag/xagent/) [XAgentOSX](https://unit42.paloaltonetworks.com/tag/xagentosx/)
This post is also available in: 日本語 [(Japanese)](https://unit42.paloaltonetworks.jp/unit42-xagentosx-sofacys-xagent-macos-tool/)
[During our continued research on Sofacy’s Komplex Trojan, we have found a sample of a](https://blog.paloaltonetworks.com/2016/09/unit42-sofacys-komplex-os-x-trojan/)
backdoor Trojan that we believe the Sofacy group uses when targeting individuals running
macOS systems. The backdoor Trojan authors have called it XAgentOSX, which shares the
name XAgent with one of Sofacy’s Windows-based Trojan and references Apple’s previous
name for macOS, OS X. It appears the same actor developed both the Komplex and
XAgentOSX tools, based on similarities within the following project paths found within the
tools:
Komplex: /Users/kazak/Desktop/Project/komplex
XAgent OSX: /Users/kazak/Desktop/Project/XAgentOSX
We believe it is possible that Sofacy uses Komplex to download and install the XAgentOSX
tool to use its expanded command set on the compromised system.
-----
## XAgent C2 Communications
The macOS variant of XAgent has ability to receive commands from threat actors via its
command and control channel, but is also capable of logging key strokes via its keylogger
functionality. XAgent uses HTTP requests to communicate with its C2 servers, which allows
the threat actor to interact with the compromised system. The Trojan uses HTTP POST
requests, as seen in Figure 1 to send data to the C2 server, and GET requests to receive
commands from the server, as seen in Figure 2. We are still analyzing this Trojan to
determine the specific structure of the data sent between the Trojan and the C2 server;
however, it does appear that the Trojan is using the RC4 algorithm to encrypt data sent to the
C2 server within HTTP POST requests.
_Figure 1 XAgent macOS HTTP POST request_
_Figure 2 XAgent mscOS HTTP GET request_
The C2 URLs generated by XAgentOSX are very similar to those created by its Windowsbased counterpart. When generating the URL for the HTTP requests issued to the C2 server,
the Trojan chooses a random folder from the following to include within the URL path:
watch/?
search/?
find/?
results/?
open/?
search/?
close/?
XAgent also will choose several parameters names from the following list when finishing the
construction of the C2 URL:
-----
itwm=
text=
from=.
itwm=
ags=
oe=
aq=
btnG=
oprnd=
itwm=
utm=
channel=
The XAgent OSX Trojan generates a system specific value that it refers to as an "agent_id",
which is a unique identifier for each compromised host. The value is derived using the
IOService to access the IOPlatformUUID property, which is equivalent to the "Hardware
UUID" listed in the system information application, as seen in the Figure 3 screenshot of our
analysis system. The Trojan uses the first four bytes of this hardware ID as a unique
identifier for the system, which in our case was "0000".
_Figure 3 Hardware ID used by XAgent to uniquely identify compromised hosts_
When generating the URLs within the HTTP POST and GET requests, XAgent sets one
HTTP parameter using a specific data structure that contains this agent_id value. This
parameter transmits the agent_id to the C2 server to obtain commands the actor wishes to
execute on the compromised system. The data structure used to transmit the agent_id to the
C2 is as follows:
-----
struct {
DWORD random_value_for_key;
CHAR[7] constant_value;
DWORD agent_id;
}
The constant value in the data structure is a 7 byte string that is hardcoded to
"\x56\x0E\x9F\xF0\xEB\x98\x43", followed by the agent_id value ("0000" in our case). The
first DWORD in the data is a random value that the Trojan will use as an XOR key to encrypt
the constant value and the agent_id. For instance, the following 15 bytes were used to
generate an HTTP parameter during our analysis:
Random Value Constant Value agent_id
0F EE C8 83 56 0E 9F F0 EB 98 43 30 30 30 30
The resulting ciphertext is then encoded using XAgent's base64 encoding routine that starts
by building the following encoding alphabet:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
As you can see, this is not the standard base64 alphabet, rather it is the "URL and Filename
safe" Base 64 Alphabet from RFC 4648, as the "+" in the standard alphabet is replaced with
"-" and the "/" replaced with "_". It then uses the base64 encoding function with this alphabet
to encode the data, which in the above case resulted in:
D-7Ig1ngV3PkdouzP974
The Trojan then creates a string of 9 random symbols and appends the encoded ciphertext
to this random string. For example, the following string would be included in one of the HTTP
parameters sent to the C2 server:
eRmaVsr90D-7Ig1ngV3PkdouzP974
In this specific case, the actor made a mistake when configuring this XAgent sample with its
C2 locations. The sample creates an array that contains the following strings for the Trojan to
use as C2 locations:
http://23.227.196[.]215/
http://apple-iclods[.]org/
http://apple-checker[.]org/
http://apple-uptoday[.]org/
http://apple-search[.]info
-----
Notice the last one is missing the trailing /, which causes an issue when the Trojan
attempts to use this string to build the remainder of the C2 URL, as the Trojan will append
the next string in the URL directly to this string. For instance, when using this string we
observed DNS queries for "apple-search.infoclose", as the string "close" was supposed to be
the next portion of the C2 URL.
## Available Commands
The XAgent C2 server will provide commands for the Trojan to run on the compromised
system within its response to inbound HTTP request. The XAgentOSX Trojan includes
responses to commands within HTML tags, which we believe allows the C2 server to format
logs for viewing.
In most cases, the responses sent to the C2 server are included between the "" and "
" HTML tags. We analyzed the command handler
and found that it provided the necessary commands for a fully functional backdoor, as seen
in Table 1. The command handler obtains a command identifier from the C2 server and adds
0xFFFFFF9B to this value and then uses a switch statement to determine the appropriate
command to execute. The switch statement checks for 19 cases, between 101 and
[119. (Updated to correct command IDs, thanks @mykill!)](https://twitter.com/mykill)
**Command**
**ID**
**Function** **Description**
101 getInfoOSX Gathers username and OSX version and responds
using the encrypted form of the following string:
"Mac OS X - [OSX version] x64
\nUser name
[username]"
102 getProcessList Runs "ps aux" to obtain a list of running processes
103 remoteShell Runs supplied command using "/bin/sh"
104 getInstalledAPP Gets a list of installed applications by running the
command "ls -la /Applications"
105 showBackupIosFolder Checks to see if an IOS device was backed up to
the system by running the command "ls -la
~/Library/Application\ Support/MobileSync/Backup/"
106 downloadFileFromPath Uploads a file from a specified path
107 createFileInSystem Downloads a file, specifically provided within the
C2 server's HTTP response
108 execFile Executes a specified file on the system using the
NSTask:launch method
-----
109 deletFileFromPath Deletes a specified file using the
NSFileManager:removeFileAtPath method
110 takeScreenShot Takes a screenshot using the
CGGetActiveDisplayList, CGDisplayCreateImage,
NSImage:initWithCGImage methods. Returns the
screenshot to the C2 via:
111 startTakeScreenShot Creates a thread to take a screenshot at a set
interval (default: every 10 seconds). Uses the same
method in "takeScreenShot" function
112 stopTakeScreenShot Closes the thread created in the
"startTakeScreenShot" function
116 getFirefoxPassword Looks for folders with "/Firefox/Profiles" in the path
and reads the contents of the "logins.json" file for
"hostname", "encryptedUsername" and
"encryptedPassword" entries. It also attempts to
issue the following SQL query on the
"signons.sqlite" file: "SELECT hostname,
encryptedUsername, encryptedPassword FROM
moz_logins WHERE timePasswordChanged/1000
BETWEEN ? AND ?"
117 ftpUpload Uses FTPManager:uploadFile method and a
supplied server name, username and password.
118 ftpStop Calls "stopOperation" method, but does not appear
to stop FTP uploads.
119 readFiles Obtains file information on a file or a folder, and
supports a "*" wildcard and recursive file list. The
code will gather the information and format the list
using the following HTML to create a table:
Type | Owner | Permissions | Created | Modificated | Size | Path |
[fileType] | [fileOwnerAccountName] | [number filePosixPermissions] | [fileCreationDate] | [fileModificationDate] | [fileSize] | [file path?] |