Introduction to Mythic C2
By Red Siege | June 28, 2023

Continuing along with my occasional series looking at how to set up and use various C2 frameworks, this is a guide to Mythic C2. Developed by Cody Thomas at SpecterOps and originally named Apfell, Mythic started out as a C2 targeted at running operations against organizations running MacOS, but rebranded as Mythic in 2020 once it became clear to the developers that it had grown into a multi-platform project.
The core elements of Mythic are written in Python 3, and the framework relies heavily on docker for managing key elements of its functionality, including the server, agents and C2 profiles (communications channels). Mythic is a multi-user C2 platform with a Web UI. It’s designed to be extensible, with the ability for other people to write agents and communications channels for it. As of late January 2023, it supported communications over tcp, http, websockets, smb and dns. It also has about a dozen different agents written in languages including Go, Python and C#, among others, and targeting Windows, MacOS and Linux.
The docker containers Mythic relies on for agents, C2 communication channels and the like can be large, as they can contain whole build environments, sometimes for multiple OSes. For point of reference, one of the Mythic installs I was recently experimenting with, including the server, the HTTP communication channel, and the Poseidon and Apollo agents, used approximately 13 GB of disk space. I also used a VPS with 2GB of RAM, as the host was giving me issues when running with only 1GB.
To get started with Mythic, you can run git clone https://github.com/its-a-feature/Mythic
for the most current version in the repo, or visit the releases page at https://github.com/its-a-feature/Mythic/releases
and download the most recent release.
Before running Mythic for the first time, make sure that both docker
and docker-compose
are installed, as both are necessary for Mythic to install and run. On Kali, apt update && apt upgrade -y && apt install docker docker-compose
should suffice. For Debian and Ubuntu, which may require additional repos, Mythic includes a pair of scripts (install_docker_debian.sh
and install_docker_ubuntu.sh
) to make things easier. (There is an install_docker_kali.sh
, but it’s just the commands I listed previously.)
Mythic configurations are stored in Mythic/.env
. Mythic will automatically generate this file the first time mythic-cli
runs, using the defaults shown in the Mythic documentation here. I will note that these configurations only affect the Mythic server, not the agents, and there are a few settings you may want to set for opsec reasons. The ALLOWED_IP_BLOCKS
variable lets one specify blocks of IP addresses which are allowed to connect to the Mythic server. These should be set as a comma-separated list of netblocks with no host IP addresses set (e.g. 127.0.0.0/24,192.168.0.0/16,etc.).
NGINX_PORT
sets the TCP port the Mythic server GUI listens on (default is 7443). While this port that can be exposed to the internet, a preferable way of connecting would be to block connections to the NGINX port from the internet, and instead use an ssh rule to forward connections from 127.0.0.1:<NGINX_PORT> on one’s workstation to 127.0.0.1:<NGINX_PORT> on the Mythic server. Setting the following configuration in the workstation’s .ssh/config
file before can enable this automatically:
host mythic-c2
hostname <server IP>
LocalForward 127.0.0.1:7443 127.0.0.1:7443
The two options that can affect operations with Mythic are EXCLUDED_C2_PROFILES
and EXCULDED_PAYLOAD_TYPES
, which can be used to disallow specific C2 channels and agents (e.g. http,tcp
or typhon,atlas
).
For purposes of this blog, I used Mythic’s default settings. I started Mythic by running sudo ./mythic-cli start
in the Mythic/
directory. As this was the first time I’d run the start command for this instance of Mythic, it took several minutes to run as it pulled down and built the necessary Docker images.
By default, Mythic has no C2 profiles or agents installed. Anything you want to use needs to be installed using the Mythic CLI tool. To install the Poseidon agent, I typed the command below:
sudo ./mythic-cli install github https://github.com/MythicAgents/Poseidon
I followed that up with installing the Medusa and Apollo agents, using essentially the same command as shown below
sudo ./mythic-cli install github https://github.com/MythicAgents/<agent name>
Poseidon installs its own TCP C2 channel, but this is a peer-to-peer channel for agents communicating inside a compromised environment, so to enable outbound communications to my server, I also installed the http C2 channel with the following command:
sudo ./mythic-cli install github https://github.com/MythicC2Profiles/http
I opened my Mythic/.env
file to find the password for the mythic_admin
user.
Password in hand, I authenticated to the server at https://127.0.0.1:7443. Mythic generates a self-signed cert, so I needed to click through the browser warnings.
Mythic is a multi-operator framework, and using an admin account you can add users by clicking the user icon in the upper right-hand corner of the page and selecting User Management.
Mythic groups activities performed against a target or related set of targets into “operations”. Mythic users must be granted permissions on a per-operation basis. The default operation, which can be set in the .env
file is Operation Chimera
. You can access the operations screen by clicking Operation Chimera
in the button bar at the top of the page.
On the operations screen, you can create and edit operations, create new users, and also create command blocklists. I clicked New Operation
to create a new operation, and named it Operation RedSiege
. Once it was created, I clicked the Edit
button for operators
on that operation, and I had the option to assign users to the operation, set their role, and assign blocklists.
The available roles are lead
, operator
and spectator
. Lead
is also the operation admin, with the ability to add/remove operators and change roles, operator
is the standard operator, and spectators
can observe the operation, but not take any actions.
I assigned my justin
account as the lead for the operation, then logged out of the mythic_admin
account and logged back in with justin
. As an aside I’ll note that, even as the operation lead, I could not modify the operation until I clicked the blue Make Current
button on the operation management screen.
Clicking the Edit
button for the operation itself brings up the options to rename the operation, mark it completed, or configure Slack webhooks for the operation, if you’re integrating with Slack.
The last thing on the operations configuration page is the blocklists section. Blocklists define a list of commands that Mythic will not permit a given agent (e.g. Apollo, Poseidon, Merlin) to run.
Blocklists can be assigned per-user, per-operation. So, If you wanted a particular user to not be able to do anything to modify the disk on a compromised machine, you could create a blocklist that disables commands such as cp
, upload
, mv
, mkdir
, etc., and then assign it under the operation’s operators
edit page.
I clicked the headphones icon at the top of the page to bring up the Payload Types and C2 Profiles page.
This page shows information about all the installed agents and C2 channels. On my server this showed that I had the Apollo and Poseidon agents installed, and the http and Poseidon TCP C2 channels installed.
Mythic’s http C2 channel configuration options are limited to changing server headers, the port, URL, and whether TLS is enabled. To access the profile configuration, I hit the down arrow on the start profile
button to access the dropdown menu and selected View/Edit Config
.
The config is a JSON file which allows an operator to set server headers, the listening port, and whether TLS/SSL is enabled. To enable TLS/SSL, set use ssl
to true
. If the key path
and cert path
are valid files, Mythic will use those for the http2 C2 profile. If not, it will generate self-signed certificates.
I chose to use the default profile. The http C2 profile will be relatively easy to fingerprint, as every request will be essentially identical. There is a dynamichttp C2 profile , which allows for much more tailoring and building randomness into the traffic, but as near as I can tell, no agents are equipped to use that profile at this time.
I saved my configuration and hit the Start Profile
button. After a moment, an output log popped up, confirming the action, and the Profile panel reflected the new status.
Mythic supports a variety of agents, each of which has its own set of capabilities and support for OSes and communications channels. As a result, it’s important to read the documentation for a given agent carefully to ensure that the agent will be able to support the specific operations it’s going to be used for.
Clicking the biohazard icon in the button bar at the top of the page brings up the payloads page.
I clicked the Actions
dropdown and picked Generate New Payload
from the menu.
I selected Linux for my target operating system. Selecting the target OS will limit which agent types are selectable on the next screen.
Having selected a Linux agent, my options for agents were Medusa and Poseidon. I chose Medusa, and got the build parameters. Medusa supports producing agents as regular scripts or base64-encoded blobs. It also gives options for producing agents compatible with either Python 2.7 or 3.8, choosing the cryptography implementation (manual or the cryptography
library), and whether to encode and encrypt the agent code. I chose to go with the defaults.
Some agent types allow the operator to configure what commands are built into an agent. This can be used to manage the size of the payload, and to ensure certain commands aren’t available to run. Medusa requires the operator to affirmatively specify what commands to build in. I elected to build all commands into my agent.
On the next page, I selected the http C2 profile (the only one available), and set the callback host to http://cdn.ravenrockgifts.com
, after creating an A record for that host with my DNS provider. Other options here include setting a kill date for the agent, the URIs and parameters for POST and GET requests, and the callback port.
On the final agent creation page, I can set the filename and a description for the agent and approve its creation.
Pretty quickly, a popup appeared telling me the agent was ready for download, and it appeared on the payloads page.
Clicking on the information icon on the right calls up the configuration of the payload, including the list of embedded commands.
When working with an active agent, the same information can be accessed through the agent’s dropdown menu, under the View Metadata
option.
For testing purposes, I downloaded the agent to the machine I was operating from and ran python3 medusa.py
, and almost immediately got a callback. Clicking the keyboard icon allowed me to interact with the beacon.
I also created an Apollo agent which I ran on a workstation in my test lab.
Apollo, Medusa and Poseidon illustrate the divergence of capabilities across Mythic agents. Apollo is a C#-based agent which only runs on Windows, with built-in process migration commands, mimikatz, and assembly execution, among other features. Python-based Medusa runs on Windows, Linux and MacOS, but is missing Windows-specific features, although it includes the ability to execute arbitrary Python code. Poseidon is written in Go, targets Linux and MacOS, and has some MacOS specific features, such as launchd
persistence.
In terms of C2 channels, all of them support the http(s) C2 profile, while only Apollo supports SMB C2 for communications inside an environment. Poseidon has its own TCP-based in-environment C2 communications profile, as well as supporting websockets.
Mythic has C2 channels that support linking beacons together, building a chain of beacons deep into a network that all connect out through one beacon that has HTTP access back to the C2 server. A beacon needs to be built with a peer-to-peer C2 channel and then linked to a beacon that has either direct, or chained C2 server access using the link
command. The SMB channel is the most common, although the Poseidon and Freyja beacons have their own custom TCP P2P channels.
Executing the link
command will bring up a dialog window allowing the operator to either select a known host that has been previously linked to, or define a new host.
Linked agents will show up with a chain-link icon under the C2 type. They may also have unusually high last checkin times, as they appear to not register a checkin unless they’ve been sent a command or have data to return.
Some Mythic agents support creating SOCKS5 proxies to allow an operator to proxy traffic from their testing host into the target network. Both the Apollo and Medusa agents support SOCKS5 proxies, and the new .NET 6-based Athena agent is listed as having beta support for proxies.
An operator can start a proxy using the command socks [port]
. The given port must be in the range specified in the Mythic configuration file’s MYTHIC_SERVER_DYNAMIC_PORTS
variable, which defaults to 7000-7010. At this time, Mythic only supports using TCP over its SOCKS5 proxies; UDP communications are not supported.
Once an operator has created a proxy, clicking on the socks icon at the top of the screen will bring up the SOCKS tab, showing all active proxies, the ports they’re running on and the agents they’re running through.
With my Mythic server running on a different host than the one I’m sitting at, I need to add a port forward to my ssh connection to make the proxy accessible to my tools. I can do this either when I start the connection by adding -L 127.0.0.1:7000:127.0.0.1:7000
to the end of my ssh command line, or by using an ssh control sequence to add it to an existing session by doing the following:
$ <enter>
$~C
ssh> -L 127.0.0.1:7000:127.0.0.1:7000
The ~C
doesn’t appear in my terminal, but the prompt changes to ssh>
letting me know I’m now giving commands directly to SSH, and I can add my port forward just as if I were doing it when I started the client.
Now, with a proxy and a local port forward in place, I can proxy tools like Certipy through the agent.
I’ll note that launching a SOCKS5 proxy will not change the check-in interval on the agent, so if commands being executed through an agent seem to be taking an exceptionally long time to run, setting that agent to an interactive mode (sleep 0
) will speed things up.
That’s the basics of installing and using Mythic. It’s one of the more customizable C2s out there, both in terms of the different agents and the ways individual agents can be tailored for a given task. Stand up a server, give it a spin, then head over to our Discord to share your thoughts.
Justin Palk has more than 16 years of experience in IT and information security, and has worked in the academic, federal civilian government and health research sectors. He has held a variety of roles including system administrator, developer, auditor, assessment team lead and web application penetration tester. He regularly competes in CTFs in the U.S. and Europe.
Certifications:
GCIH, GWAPT, GPEN, GMOB, GDSA
Related Stories
View MoreBy Red Siege | November 28, 2023
from Ian Briley, Security Consultant The weakest link in your information security chain will always be the human behind the keyboard. No matter how much death by PowerPoint security training […]
Learn MoreBy Tim Medin | November 13, 2023
As the CEO of Red Siege Information Security, I’ve had the privilege of building an outstanding team of ethical hackers to conduct numerous penetration tests for organizations across many industries. […]
Learn MoreBy Red Siege | October 5, 2023
In this blog post I wanted to share a few tips and tricks I’ve found in Burp that have really helped me in the past. Double Click and Right Click […]
Learn More