delegates
array in messages. An example of what this looks like is in the next section, but this delegates
array can be part of any message from an agent to mythic.
UUID
- This field is some UUID identifier used by the agent to track where a message came from and where it should go back to. Ideally this is the same as the UUID for the callback on the other end of the connection, but can be any value. If the agent uses a value that does not match up with the UUID of the agent on the other end, Mythic will indicate that in the response. This allows the middle-man agent to generate some UUID identifier as needed upon first connection and then learn of and use the agent’s real UUID once the messages start flowing.
message
- this is the actual message that the agent is transmitting on behalf of the other agent
c2_profile
- This field indicates the name of the C2 Profile associated with the connection between this agent and the delegated agent. This allows Mythic to know how these two agents are talking to each other when generating and tracking connections.
new_uuid
field indicates that the uuid
field the agent sent doesn’t match up with the UUID in the associated message. If the agent uses the right UUID with the agentMessage then the response would be:
get_tasking
request OR a post_response
request, you could get back delegates
data. The same goes for rpfwd
, interactive
, and socks
.{"action": "get_tasking", "tasking_size": 1}
. All is well.
{"action": "get_tasking", "tasking_size": 1, "delegates": [ {"message": agentB's message, "c2_profile": "Name of the profile we're using to communicate", "uuid": "myRandomUUID"} ] }
. That’s the message agentA sends to Mythic.
delegate
messages (i.e. messages that it’s passing along on behalf of other agents). So Mythic recursively processes each of the messages in this array. Because that message
value is the same as if agentB was talking directly to Mythic, Mythic can parse out the right UUIDs and information. The c2_profile
piece allows Mythic to look up any c2-specific encryption information to pass along for the message. Once Mythic is done processing the message, it sends a response back to agentA like: {"action": "get_tasking", "tasks": [ normal array of tasks ], "delegates": [ {"message": "response back to what agentB sent", "uuid": "myRandomUUID that agentA generated", "new_uuid": "the actual UUID that Mythic uses for agentB"} ] }
. If this is the first time that Mythic has seen a delegate from agentB through agentA, then Mythic knows that there’s a route between the two and via which C2 profile, so it can automatically display that in the UI
delegates
array and loops through those messages. It sees “oh, it’s myRandomUUID, i know that guy, let me forward it along” and also sees that it’s been calling agentB by the wrong name, it now knows agentB’s real name according to Mythic. This is important because if agentA and agentB ever lose connection, agentA can report back to Mythic that it can no longer to speak to agentB with the right UUID that Mythic knows.
get_tasking
message (with or without a delegate message from agentB), if mythic sees a tasking for agentB, Mythic will automatically add in the same delegates
message that we saw before and send it back with agentA so that agentA can forward it to agentB. That’s important - agentB never had to ask for tasking, Mythic automatically gave it to agentA because it knew there was a route between the two agents.
get_delegate_tasks
to False. i.e ({"action": "get_tasking", "tasking_size": 1, "get_delegate_tasks": false}
) then even if there are tasks for agentB, Mythic WILL NOT send them along with agentA. agentB will have to ask for them directly
edges
structure at a higher point in the message: