C2 Related Development

C2 Structure

Command and Control (C2) profiles are a little different in Mythic than you might be used to. Specifically, C2 profiles live in their own docker containers and act as a translation mechanism between whatever your special sauce C2 protocol/format/encryption is and what the back-end Mythic server understands (HTTP + JSON).

By defining a C2 protocol specification, other payload types can register that they speak that C2 protocol as well and easily hook in without having to do back-end changes. By having C2 protocols divorced from the main Mythic server, you can create entirely new C2 protocols more easily and you can do them in whatever language you want. If you want to do all your work in Golang, C#, or some other language for the C2 protocol, go for it. It's all encapsulated in the C2's Docker container with whatever environment you desire.

Since there's so much variability possible within a C2 Docker container, there's some required structure and python files similar to how Payload Types are structured. This is covered in C2 Profile Code.

C2 Profiles can also define "translation" containers.

Translation Containers

Translation containers are very similar to C2 Profile containers except they don't sync into the main UI and are only there to support C2 Profile containers. The idea is that you might have a custom protocol that multiple containers or C2 profiles share (such as a custom binary protocol that's used by your agent's HTTP, TCP, SMB, etc profiles). It doesn't make sense to repeat that translation over and over again in each one. Instead, you can specify and create a "translation" container that houses all of this logic in one spot. In this case, the C2 Profile container simply worries about getting messages off the wire and handing them off to Mythic.

C2 / Mythic Comms

Every C2 Docker container has an environment variable, MYTHIC_ADDRESS which points to https://127.0.0.1:7443 by default. This information is pulled from the main /Mythic/mythic-docker/config.json 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.

C2 RPC

C2 Profiles can access the same RPC functions that Payload Types can; however, since C2 profiles don't have things like a 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 weird

  • create_encrypted_message - This is useful for a c2 profile to generate encrypted messages

  • create_decrypted_message - This is useful for a c2 profile to decrypted messages from callbacks

These functions are available from within the C2 docker container via Python (see the http C2 server 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.

Payload Type Docker -> C2 Docker

This one is a little less intuitive than the C2 Docker container directly reaching out to the Mythic server for functionality. This functionality allows tasking as an operator to directly manipulate a C2 component. This functionality has no "default" functions, it's all based on the C2 profile itself. Here is an example of a simple RPC function from a Payload Type Docker container -> C2 Docker container:

from mythic_c2_container.MythicRPC import *

# request is a dictionary: {"action": func_name, "message": "the input",  "task_id": task id num}
# must return an RPCResponse() object and set .status to an instance of RPCStatus and response to str of message
async def test(request):
    response = RPCResponse()
    response.status = RPCStatus.Success
    response.response = "hello"
    resp = await MythicRPC().execute("create_event_message", message="Test message", warning=False)
    return response

Within the C2 profile's 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.

Last updated