Understanding & Detecting C2 Frameworks — Ares
Introduction
Hello and welcome to this new blog series titled “Understanding & Detecting C2 Frameworks”. In the coming weeks and months, i’ll be doing some analysis and deep dives into old and new open source C2 frameworks. Analyzing the source code and try to understand the inner workings in the hope to get more insights into the techniques being used in these different tools. So without further a do let’s start this one with a relatively simple and old framework (RAT) named “Ares” by “sweetsoftware”.
Ares
Here is a definition from their GitHub repository
Ares is a Python Remote Access Tool. Ares is made of two main programs:
A Command aNd Control server, which is a Web interface to administer the agents
An agent program, which is run on the compromised host, and ensures communication with the CNC
In practice the folder structure looks a little like this
Let’s start our journey by analyzing the C2 Agent
“agent.py”
The agent is located in the file “agent.py”. It consists of one giant class called “Agent” that contains all the functionalities. This class will be called from a function called “main” that in turns will execute the “run” function responsible for running the agent.
Within this function we encounter the first functionality of this agent which persistence.
Persistence
Depending on a boolean read from the configuration file “config.py” we call the persist function.
The function only executes if the agent is compiled. This is verified by checking the value the “frozen” attribute from the “sys” package. It also verifies if the agent is already installed on the machine by calling the “is_installed” function which is a wrapper for a function called “get_install_dir”
The “get_install_dir” check the operating system, and depending if its “Linux” or “Windows”. It’ll check the home directory of the “user” running the agent and looks for a folder named “ares”
- Linux : “~/.ares”
- Windows : “%USERPROFILE%/ares”
If the agent is not installed on the machine then the following commands will get executed depending on the platform
Linux
- Create directory “.ares” within the home directory of the user: ~/.ares
- Copy the executable to the following aforementioned directory : ~/.ares/[name_of_executable]
- Executes : chmod +x ~/.ares/[name_of_executable]
- If “~/.config/autostart/” exists then it’ll create the file “~/.config/autostart/ares.desktop” with the following content
[Desktop Entry]
Version=1.0
Type=Application
Name=Ares
Exec=~/.ares/[name_of_executable]
- If aforementioned directory doesn’t exists then the following content will be appended to “~/.bashrc”
(if [ $(ps aux|grep " + os.path.basename(sys.executable) + "|wc -l) -lt 2 ]; then " + ~/.ares/[name_of_executable] + ";fi&)
Windows
- Create directory “ares” within the user profile directory : %USERPROFILE%/ares
- Copy the executable to the following aforementioned directory : %USERPROFILE%/ares/[name_of_executable]
- Create value “ares” in the “HKCU\Software\Microsoft\Windows\CurrentVersion\Run” registry key with the following command
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /f /v ares /t REG_SZ /d \"%s\"" % [agent_path]
With that the “installation” of the agent is finished and it’ll start listening to commands from the C2 in an infinite loop.
It’ starts by executing a function called “server_hello” which’ll perform a simple post request to the following URL and wait for instruction.
POST http(s)://[SERVER_IP]/api/USERNAME_[UUID]/hello
The request will send the following information to the C2 :
- Platform
- Hostname
- Username
Note that since no “User-Agent” is specified, the default User-Agent of the “requests” library will be used. (See below)
User-Agent: python-requests/[Version]
The result of this request will be stored in the variable “todo” that will contain any command(s) sent by the C2 server.
Before it checks the value returned from the server, the function “update_consecutive_failed_connections” will be called. This function serves the purpose of logging the number of “failed” connections or exceptions within the main loop.
If the “agent” is installed, a file named “failed_connections” will get created in the “%USERPROFILE%/ares” folder on Windows systems and in “~/.ares” folder on Linux systems.
The next set of functions that’ll get executed will depend on what command(s) the C2 server will send. Most of the functions contain some unique artifact(s) that’ll help us detect the behavior or functionality being used.
One thing to note before we get into the supported commands. Is that almost all command make use of a function called “send_output”.
The role of this function is to send any data back to the C2 server via a post request using this URL
POST http(s)://[SERVER_IP]/api/USERNAME_[UUID]/report
Bellow are the commands supported by the agent.
cd
This command simply changes the current directory to whatever is sent from the C2
upload
The agent can upload any file to the C2 server. The file in question will be sent via a post request to the following URL:
POST http(s)://[SERVER_IP]/api/USERNAME_[UUID]/upload
download
This command acts as a download agent. Where the C2 server will send a remote file to be downloaded and specify a location to store it.
The agent will send first an output to the C2 via the “send_output” function indicating the start of the download. Then a “get” request will be made to whatever URL was provided from the C2.
This can be identified by looking for the following two requests made back to back with the a “User-Agent” of “python-requests/[Version]” .
POST http(s)://[SERVER_IP]/api/USERNAME_[UUID]/report
GET http(s)://[REMOTE_URL]
clean
The “clean” command will basically undo everything that the “persist” command/function did.
Depending on the platform the following commands will get executed
Linux
- Deletes everything under the “~/.ares” directory
- Deletes “~/.config/autostart/ares.desktop”
- grep -v .ares .bashrc > .bashrc.tmp;mv .bashrc.tmp .bashrc
Windows
- reg delete HKCU\Software\Microsoft\Windows\CurrentVersion\Run /f /v ares
- reg add HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce /f /v ares /t REG_SZ /d \”cmd.exe /c del /s /q [persistence_directory] & rmdir [persistence_directory]\””
persist
If persistence was not enabled in the config file. The operator of the C2 can send the “persist” command to initiate the persistence process (See start of the blog for a detailed description of this function).
exit
This command will simply kill the agent and exit
zip
The “agent” offers the possibility to zip any file or folder and save them on any location.
The newly created zip file can be located wherever, but the most important thing regarding detection is that it will not get deleted automatically. Unless explicitly stated by an “rm” or “del” from the server. So depending on the operator of the C2, any zip file created can still be found on the infected machine.
python
It lets the operator execute arbitrary python files / commands using the “exec” function.
screenshot
Create a screenshot and saves it under the the temp directory of the user (“%temp%” on windows and “/tmp” on linux). Then uploads the results using the “upload” function described above.
Note that the screenshot in question will not get deleted by the agent so you can look for any “.png” files in the temp directory.
help
This will simply print a help menu showcasing the supported operations/commands
runcmd
The final command offered by the agent is arbitrary command execution. The “runcmd” function will execute any commands sent from the C2 using the python “subprocess” package.
One thing to note is that the agent has an “idle” mode that can be configured from the CONFIG file.
This concludes the analysis of all the functionalities offered by the agent. Now let’s take a quick look at the server portion of the code.
“ares.py”
The server side part of this framework is straightforward. Its written in flask and has a local database to store information about commands, agents connected…etc.
By default the C2 server has the server header hard-coded to the string “Ares”. So every response sent from the server will contain the server header “Ares”.
Also, the files uploaded to the C2 server using the “upload” command from the agent will be stored by default on the directory “uploads” and they can be accessed directly from the server without the need for any authentication.
http(s)://[C2_IP]/uploads/[agent_id]/[filename]
Apart from this, the code is just handling the requests sent from the agent.
Conclusion
That’s it for this first blog post. Hopefully it was helpful and you got something out of it. Until the next one. If you have any C2 frameworks suggestions you want me to look at or any feedback you can find me on twitter @nas_bench
Thanks for reading.
Indicators
User-Agent
- User-Agent: python-requests/2.18.4
URL’s & Network Artifacts
- http(s)://[SERVER_IP]/api/USERNAME_[UUID]/upload
- http(s)://[SERVER_IP]/api/USERNAME_[UUID]/report
- http(s)://[SERVER_IP]/api/USERNAME_[UUID]/hello
- http(s)://[C2_IP]/uploads/[agent_id]/[filename]
- Response header : “Server : Ares”
Telemetry
- Folder creation / deletion
- File creation
Commands (Linux)
- chmod +x ~/.ares/[name_of_executable]
- grep -v .ares .bashrc > .bashrc.tmp;mv .bashrc.tmp .bashrc
Commands (Windows)
- reg delete HKCU\Software\Microsoft\Windows\CurrentVersion\Run /f /v ares
- reg add HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce /f /v ares /t REG_SZ /d \”cmd.exe /c del /s /q [persistence_directory] & rmdir [persistence_directory]\””
- reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /f /v ares /t REG_SZ /d \”%s\”” % [agent_path]
Disk Artifacts
- /tmp/[random_name].png
- %temp%/[random_name].png
- Zip files creates by the ZIP command. Creation date can be correlated with HTTP requests to create the zip file
- Files downloaded to the agent using the download command. Creation date can be correlated with HTTP requests to download the file
- File located inside the “ares” folder : failed_connections
- Creation of folder (Linux) : “~/.ares”
- Creation of folder (Windows): “%USERPROFILE%/ares”
- Written to “.bashrc” : (if [ $(ps aux|grep “ + os.path.basename(sys.executable) + “|wc -l) -lt 2 ]; then “ + ~/.ares/[name_of_executable] + “;fi&)
- Written to “~/.config/autostart/ares.desktop”
[Desktop Entry]
Version=1.0
Type=Application
Name=Ares
Exec=~/.ares/[name_of_executable]
MITRE ATT&CK
Below are some of the techniques used by this tool
- T1059.006 — Command and Scripting Interpreter: Python
- T1071.001 — Application Layer Protocol: Web Protocols
- T1547.001 — Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder
- T1041 — Exfiltration Over C2 Channel
- T1546.004 — Event Triggered Execution: Unix Shell Configuration Modification
- T1113 — Screen Capture
- T1059.003 — Command and Scripting Interpreter: Windows Command Shell
- T1059.004 — Command and Scripting Interpreter: Unix Shell