Example_C2_Profile
folder from Mythic. Copy this folder to the Mythic/C2_Profiles/
folder and rename it to the same name as the C2 profile you want to create. Inside of this folder are a few important pieces:mythic-cli
to install and run your C2 Profile, then Mythic will mount your Mythic/C2_Profiles/[c2 profile name]
folder as /Mythic
inside of the Docker container as a volume. This means that any changes to the Mythic/C2_Profiles/[c2 profile name]
folder that happen on disk will be mirrored inside of the Docker container.config.json
and server
config.json
- this is a JSON file that exposes any configuration parameters that you want to expose to the user (such as which port to open up, do you need SSL, etc).server
- this is the actual piece of code that Mythic executes when you "start" a C2 Profile. This server
file can be whatever you want as long as it's executable. For example, the http
profile uses a Python file with #! /usr/bin/env python3
at the top, and the websocket
profile uses a Golang binary. Whatever you plan on having this file be, just make sure it's executable and parses that config.json
file to get its configuration.c2_functions
- this holds the actual Python definition files and potential RPC functionality you want to expose.C2_RPC_Functions.py
is where you'll define the RPC functions and OPSEC checking code you'll expose to the rest of Mythic. The other file (by default just called HTTP.py
) is what holds all of the important definition information for your profile. It's in this file that you will set the actual name for your profile and what parameters it takes.c2_service.sh
- this is the entrypoint for the docker container. This changes the current working directory and gets everything set up to then call the mythic_service.py
file.mythic_service.py
- this python file is what acts as the long running service in the Docker container which connects up to Mythic, sends heartbeats, and processes messages from Mythic (such as doing OPSEC checks, starting/stopping the profile, updating the config, etc).rabbitmq_config.json
- this configuration file indicates how the mythic_service.py
file will connect to RabbitMQ so that it can get/send messages with Mythic. This will include things like the IP address and password for connecting as well as the name of your profile.name
specified in the rabbitmq_config.json
file matches the name you set in your definition file (within the c2_functions
folder) exactly! sudo ./mythic-cli install github https://github.com/C2Profiles/[profile name]
. However, since you already have the code and folder structure in your Mythic/C2_Profiles
folder, we can just 'tell' Mythic that it exists. You can do this via sudo ./mythic-cli c2 add [profile name]
. You can then start just that one container with sudo ./mythic-cli c2 start [profile name]
. When the container starts, a few things happen:c2_service.sh
c2_service.sh
sets up some environment variables and sets the current working directory, then kicks off mythic_service.py
mythic_service.py
then processes the rabbitmq_config.json
as well as environment variables passed in. It then processes all of the files within the c2_functions
folder to look for your C2 Profile class (You'll notice here that your class extends the C2Profile class). Once it finds that class, it gets a dictionary representation of all of that information (C2 profile name, parameters, etc) and then connects to RabbitMQ to send that data to Mythic. rabbitmq_config.json
file with the name
parameter. This is why it's important for that to match the name of the profile exactly. If something doesn't match up, then you'll run into an instance where you get a heartbeat for C2 Profile X, which Mythic doesn't know. It'll then ask the container to sync up, and the container will send information about C2 Profile Y (based on the information in the c2_functions
folder). That information will get processed, but then the container will send a heartbeat for C2 Profile X again. Again, Mythic doesn't know C2 Profile X, only Y, so it'll ask the container to sync again. And that just repeats forever.MYTHIC_ADDRESS
environment variable is good enough. You'll get an immediate result back from that which your C2 profile should hand back to the agent.[c2 profile name]/c2_code/server
file when the container starts. This same file is what gets executed when you click to "start" the profile in the UI. MYTHIC_ADDRESS
which points to https://127.0.0.1:7443
by default. This information is pulled from the main /Mythic/.env
file. So, if you change Mythic's main UI to HTTP on port 7444, then each C2 Docker container's MYTHIC_ADDRESS
environment variable will have the value http://127.0.0.1:7444
. This allows your code within the docker container to always know where to forward requests so that the main Mythic server can process them.message
is typically an encrypted blob, but could be anything.task_id
, there is some functionality they won't be able to leverage. Specifically, the main functions for C2 profiles are:create_event_message
- This is useful for a c2 profile to send an alert to operators in case something is weirdcreate_encrypted_message
- This is useful for a c2 profile to generate encrypted messagescreate_decrypted_message
- This is useful for a c2 profile to decrypted messages from callbacksserver
file as an example). These functions can be useful if you want to implement your own C2 protocol instead of JSON, but you will have to translate to/from JSON and Mythic's format at some point to interact with Mythic.mythic/c2_functions
folder can be any number of python files that have defined functions. These functions are automatically imported and available for RPC when the container starts. In this case, a remote container can call this C2's test
function.