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.
You can use the Example_C2_Profile
folder as a template when designing your C2 profile.
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 Docker containers allow RPC calls to them from other containers. This gives even more flexibility to C2 containers since they can do some of the pieces of the Mythic server for themselves. Specifically, there's two directions of C2 RPC calls: C2 Docker -> Mythic and Payload Type Docker -> C2 Docker.
C2 Docker -> Mythic RPC
The C2 Docker container can make the following requests to the Mythic server:
get_tasking
- Given a callback's UUID, use that to check if there's any tasking for the callback or any callback that's routable through that callback.parameters are:
uuid
- the UUID of the callback you're interested intasking_size
- the number of tasks you want at a time. Defaults to 1, but if you specify -1 you'll get all that are in thesubmitted
state.raw_response
- Boolean flag if you want mythic to return the raw response for you or try to encrypt/encode it
add_route
- Add a route from one callback to another callback. This is what illustrates to Mythic and in the UI what P2P connections exist.parameters are:
source
- The source of the connection as a callback UUIDdestination
- the destination of the connection as a callback UUIDdirection
- the direction of the connection. Defaults to 1 (source to destination), but can also be 2 (destination to source).metadata
- string of any additional metadata you might want to store or share about the connection. This data must match when you go to remove the route!
remove_route
- Remove a route from one callback to another callback.parameters are:
source
- The source of the connection as a callback UUIDdestination
- the destination of the connection as a callback UUIDdirection
- the direction of the connection.metadata
- string of any additional metadata you might want to store or share about the connection. This data must match what was set when the connection was added!
get_callback_info
- Get all the information related to the callbackparameters are:
uuid
- The callback UUID you're interested in
update_callback_info
- Update information related to a callbackparameters are:
uuid
- the callback UUID you're interested ininfo
- a dictionary of updated values you want to set for the callback (this can include encryption information as well).
add_event_message
- Send a message to the Mythic event logparameters are:
level
- what level of severity is the message ("info" or "warning")message
- what is the actual message you want to send
get_encryption_data
- Get the current encryption data for a callback if a callback UUID is specified, or get all of the C2 profile parameters associated with the payload if a payload UUID is specifiedparameters are:
uuid
- the UUID we're interested in (can be callback UUID or payload UUID)profile
- the name of your c2 profile. This allows Mythic to look up the c2 profile parameters associated with your profile.
encrypt_bytes
- The C2 profile gives Mythic some bytes and a callback UUID and asks Mythic to encrypt themparameters are:
uuid
- the UUID for the callback we're interested indata
- the raw bytes that we're wanting to encryptwith_uuid
- this indicates if the resulting data should bewith_uuid
(i.e. base64(uuid+encrypted_blob) or just base64(encrypted_blob).
decrypt_bytes
- The C2 profile gives Mythic some bytes and a callback UUID and asks Mythic to decrypt themparameters are:
uuid
- the UUID for the callback we're interested indata
- the raw bytes of the data we're wanting to decrypt (if this is a message that already has the UUID prepended to the front, leave it there)with_uuid
- this indicates if thedata
portion has the UUID included or if the C2 profile is simply passing in raw bytes to decrypt. The scenario here is that a C2 profile could get a normal Mythic message, pass it off to get decrypted, then manipulate the data as needed.
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:
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