pub struct MythicAgent {
pub callback_uuid: Uuid,
}Expand description
Post-checkin phase — holds the callback UUID assigned by Mythic.
Encryption state is kept on the C2Transport via
get_aes_psk /
set_aes_psk so the same agent
can switch transports without duplicating key state.
§Examples
use mythic::{C2Transport, MythicAgent, MythicError};
use uuid::Uuid;
let c2 = HttpC2;
let payload_uuid = Uuid::parse_str("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee").unwrap();
let agent = MythicAgent::easy_checkin(
payload_uuid,
&c2,
vec!["10.0.0.1".into()],
Some("linux".into()),
Some("root".into()),
Some("web01".into()),
Some(1337),
Some("x86_64".into()),
None, None, None, None, None, None,
)
.unwrap();
println!("callback UUID: {}", agent.callback_uuid());Fields§
§callback_uuid: UuidImplementations§
Source§impl MythicAgent
impl MythicAgent
pub fn new(payload_uuid: Uuid) -> Self
Sourcepub fn callback_uuid(&self) -> Uuid
pub fn callback_uuid(&self) -> Uuid
Examples found in repository?
52fn main() {
53 let payload_uuid = Uuid::parse_str("f0f0f0f0-1111-2222-3333-444444444444").unwrap();
54
55 // ── Plaintext checkin ─────────────────────────────────
56 {
57 let c2 = HttpC2 { key_b64: None };
58 let agent = MythicAgent::easy_checkin(
59 payload_uuid,
60 &c2,
61 vec!["10.0.0.1".into()],
62 Some("linux".into()),
63 Some("root".into()),
64 Some("web01".into()),
65 Some(1337),
66 Some("x86_64".into()),
67 None, None, None, None, None, None,
68 )
69 .unwrap();
70 println!("Plaintext callback UUID: {}", agent.callback_uuid());
71 }
72
73 // ── Static-key checkin ────────────────────────────────
74 {
75 let key = Aes256HmacCrypto::new([0xAB; 32]).key_b64();
76 let c2 = HttpC2 { key_b64: Some(key) };
77 let agent = MythicAgent::easy_checkin(
78 payload_uuid,
79 &c2,
80 vec!["192.168.1.100".into()],
81 Some("windows".into()),
82 Some("admin".into()),
83 Some("DESKTOP-XYZ".into()),
84 Some(2048),
85 Some("x86_64".into()),
86 None, None, None, None, None, None,
87 )
88 .unwrap();
89 println!("Static-key callback UUID: {}", agent.callback_uuid());
90 }
91
92 // ── Full lifecycle: get_tasking → post_response ───────
93 {
94 let c2 = HttpC2 { key_b64: None };
95
96 // 1. Checkin
97 let agent = MythicAgent::easy_checkin(
98 payload_uuid,
99 &c2,
100 vec!["10.0.0.2".into()],
101 Some("linux".into()),
102 Some("operator".into()),
103 Some("implant01".into()),
104 Some(9999),
105 Some("aarch64".into()),
106 None, None, None, None, None, None,
107 )
108 .unwrap();
109
110 // 2. Poll for tasks
111 match agent.get_tasking(1, &c2) {
112 Ok(resp) => {
113 for task in &resp.tasks {
114 println!("Received task {}: {}", task.id, task.command);
115
116 // 3. Execute and respond
117 let _ = agent.post_response(
118 vec![TaskResponse::completed(task.id, "task executed successfully")],
119 &c2,
120 );
121 }
122 }
123 Err(e) => eprintln!("get_tasking failed: {e}"),
124 }
125 }
126
127 println!("All demo scenarios complete.");
128}Sourcepub fn easy_checkin<C: C2Transport>(
payload_uuid: Uuid,
c2: &C,
ips: Vec<String>,
os: Option<String>,
user: Option<String>,
host: Option<String>,
pid: Option<u32>,
architecture: Option<String>,
domain: Option<String>,
integrity_level: Option<u32>,
external_ip: Option<String>,
encryption_key: Option<String>,
decryption_key: Option<String>,
process_name: Option<String>,
) -> MythicResult<Self>
pub fn easy_checkin<C: C2Transport>( payload_uuid: Uuid, c2: &C, ips: Vec<String>, os: Option<String>, user: Option<String>, host: Option<String>, pid: Option<u32>, architecture: Option<String>, domain: Option<String>, integrity_level: Option<u32>, external_ip: Option<String>, encryption_key: Option<String>, decryption_key: Option<String>, process_name: Option<String>, ) -> MythicResult<Self>
One-shot checkin — create an agent and check it in, no new() needed.
For full control use checkin with a pre-built
ReqCheckin.
Examples found in repository?
52fn main() {
53 let payload_uuid = Uuid::parse_str("f0f0f0f0-1111-2222-3333-444444444444").unwrap();
54
55 // ── Plaintext checkin ─────────────────────────────────
56 {
57 let c2 = HttpC2 { key_b64: None };
58 let agent = MythicAgent::easy_checkin(
59 payload_uuid,
60 &c2,
61 vec!["10.0.0.1".into()],
62 Some("linux".into()),
63 Some("root".into()),
64 Some("web01".into()),
65 Some(1337),
66 Some("x86_64".into()),
67 None, None, None, None, None, None,
68 )
69 .unwrap();
70 println!("Plaintext callback UUID: {}", agent.callback_uuid());
71 }
72
73 // ── Static-key checkin ────────────────────────────────
74 {
75 let key = Aes256HmacCrypto::new([0xAB; 32]).key_b64();
76 let c2 = HttpC2 { key_b64: Some(key) };
77 let agent = MythicAgent::easy_checkin(
78 payload_uuid,
79 &c2,
80 vec!["192.168.1.100".into()],
81 Some("windows".into()),
82 Some("admin".into()),
83 Some("DESKTOP-XYZ".into()),
84 Some(2048),
85 Some("x86_64".into()),
86 None, None, None, None, None, None,
87 )
88 .unwrap();
89 println!("Static-key callback UUID: {}", agent.callback_uuid());
90 }
91
92 // ── Full lifecycle: get_tasking → post_response ───────
93 {
94 let c2 = HttpC2 { key_b64: None };
95
96 // 1. Checkin
97 let agent = MythicAgent::easy_checkin(
98 payload_uuid,
99 &c2,
100 vec!["10.0.0.2".into()],
101 Some("linux".into()),
102 Some("operator".into()),
103 Some("implant01".into()),
104 Some(9999),
105 Some("aarch64".into()),
106 None, None, None, None, None, None,
107 )
108 .unwrap();
109
110 // 2. Poll for tasks
111 match agent.get_tasking(1, &c2) {
112 Ok(resp) => {
113 for task in &resp.tasks {
114 println!("Received task {}: {}", task.id, task.command);
115
116 // 3. Execute and respond
117 let _ = agent.post_response(
118 vec![TaskResponse::completed(task.id, "task executed successfully")],
119 &c2,
120 );
121 }
122 }
123 Err(e) => eprintln!("get_tasking failed: {e}"),
124 }
125 }
126
127 println!("All demo scenarios complete.");
128}Sourcepub fn checkin<C: C2Transport>(
self,
req: ReqCheckin,
c2: &C,
) -> MythicResult<Self>
pub fn checkin<C: C2Transport>( self, req: ReqCheckin, c2: &C, ) -> MythicResult<Self>
Perform a direct checkin (plaintext or static-key PSK).
The mode is determined automatically from the transport
via C2Transport::get_aes_psk. req.uuid must be the payload
UUID; it is used both in the JSON body and the wire framing.
Sourcepub fn get_tasking<C: C2Transport>(
&self,
tasking_size: u32,
c2: &C,
) -> MythicResult<RespGetTasking>
pub fn get_tasking<C: C2Transport>( &self, tasking_size: u32, c2: &C, ) -> MythicResult<RespGetTasking>
Poll for new tasks from the Mythic server (no extras).
Examples found in repository?
52fn main() {
53 let payload_uuid = Uuid::parse_str("f0f0f0f0-1111-2222-3333-444444444444").unwrap();
54
55 // ── Plaintext checkin ─────────────────────────────────
56 {
57 let c2 = HttpC2 { key_b64: None };
58 let agent = MythicAgent::easy_checkin(
59 payload_uuid,
60 &c2,
61 vec!["10.0.0.1".into()],
62 Some("linux".into()),
63 Some("root".into()),
64 Some("web01".into()),
65 Some(1337),
66 Some("x86_64".into()),
67 None, None, None, None, None, None,
68 )
69 .unwrap();
70 println!("Plaintext callback UUID: {}", agent.callback_uuid());
71 }
72
73 // ── Static-key checkin ────────────────────────────────
74 {
75 let key = Aes256HmacCrypto::new([0xAB; 32]).key_b64();
76 let c2 = HttpC2 { key_b64: Some(key) };
77 let agent = MythicAgent::easy_checkin(
78 payload_uuid,
79 &c2,
80 vec!["192.168.1.100".into()],
81 Some("windows".into()),
82 Some("admin".into()),
83 Some("DESKTOP-XYZ".into()),
84 Some(2048),
85 Some("x86_64".into()),
86 None, None, None, None, None, None,
87 )
88 .unwrap();
89 println!("Static-key callback UUID: {}", agent.callback_uuid());
90 }
91
92 // ── Full lifecycle: get_tasking → post_response ───────
93 {
94 let c2 = HttpC2 { key_b64: None };
95
96 // 1. Checkin
97 let agent = MythicAgent::easy_checkin(
98 payload_uuid,
99 &c2,
100 vec!["10.0.0.2".into()],
101 Some("linux".into()),
102 Some("operator".into()),
103 Some("implant01".into()),
104 Some(9999),
105 Some("aarch64".into()),
106 None, None, None, None, None, None,
107 )
108 .unwrap();
109
110 // 2. Poll for tasks
111 match agent.get_tasking(1, &c2) {
112 Ok(resp) => {
113 for task in &resp.tasks {
114 println!("Received task {}: {}", task.id, task.command);
115
116 // 3. Execute and respond
117 let _ = agent.post_response(
118 vec![TaskResponse::completed(task.id, "task executed successfully")],
119 &c2,
120 );
121 }
122 }
123 Err(e) => eprintln!("get_tasking failed: {e}"),
124 }
125 }
126
127 println!("All demo scenarios complete.");
128}Sourcepub fn get_tasking_with<C: C2Transport>(
&self,
tasking_size: u32,
c2: &C,
extras: AgentMessageExtras,
) -> MythicResult<RespGetTasking>
pub fn get_tasking_with<C: C2Transport>( &self, tasking_size: u32, c2: &C, extras: AgentMessageExtras, ) -> MythicResult<RespGetTasking>
Poll for new tasks, carrying delegates, SOCKS, RPFWD, interactive data, edges, alerts, and/or responses alongside the request.
Sourcepub fn post_response<C: C2Transport>(
&self,
responses: Vec<TaskResponse>,
c2: &C,
) -> MythicResult<RespPostResponse>
pub fn post_response<C: C2Transport>( &self, responses: Vec<TaskResponse>, c2: &C, ) -> MythicResult<RespPostResponse>
Send task responses back to the Mythic server (no extras).
The responses vector contains the output of completed (or in-progress)
tasks. Use crate::protocol::TaskResponse builders like
crate::protocol::TaskResponse::completed or construct custom
responses with hooking-feature data.
Examples found in repository?
52fn main() {
53 let payload_uuid = Uuid::parse_str("f0f0f0f0-1111-2222-3333-444444444444").unwrap();
54
55 // ── Plaintext checkin ─────────────────────────────────
56 {
57 let c2 = HttpC2 { key_b64: None };
58 let agent = MythicAgent::easy_checkin(
59 payload_uuid,
60 &c2,
61 vec!["10.0.0.1".into()],
62 Some("linux".into()),
63 Some("root".into()),
64 Some("web01".into()),
65 Some(1337),
66 Some("x86_64".into()),
67 None, None, None, None, None, None,
68 )
69 .unwrap();
70 println!("Plaintext callback UUID: {}", agent.callback_uuid());
71 }
72
73 // ── Static-key checkin ────────────────────────────────
74 {
75 let key = Aes256HmacCrypto::new([0xAB; 32]).key_b64();
76 let c2 = HttpC2 { key_b64: Some(key) };
77 let agent = MythicAgent::easy_checkin(
78 payload_uuid,
79 &c2,
80 vec!["192.168.1.100".into()],
81 Some("windows".into()),
82 Some("admin".into()),
83 Some("DESKTOP-XYZ".into()),
84 Some(2048),
85 Some("x86_64".into()),
86 None, None, None, None, None, None,
87 )
88 .unwrap();
89 println!("Static-key callback UUID: {}", agent.callback_uuid());
90 }
91
92 // ── Full lifecycle: get_tasking → post_response ───────
93 {
94 let c2 = HttpC2 { key_b64: None };
95
96 // 1. Checkin
97 let agent = MythicAgent::easy_checkin(
98 payload_uuid,
99 &c2,
100 vec!["10.0.0.2".into()],
101 Some("linux".into()),
102 Some("operator".into()),
103 Some("implant01".into()),
104 Some(9999),
105 Some("aarch64".into()),
106 None, None, None, None, None, None,
107 )
108 .unwrap();
109
110 // 2. Poll for tasks
111 match agent.get_tasking(1, &c2) {
112 Ok(resp) => {
113 for task in &resp.tasks {
114 println!("Received task {}: {}", task.id, task.command);
115
116 // 3. Execute and respond
117 let _ = agent.post_response(
118 vec![TaskResponse::completed(task.id, "task executed successfully")],
119 &c2,
120 );
121 }
122 }
123 Err(e) => eprintln!("get_tasking failed: {e}"),
124 }
125 }
126
127 println!("All demo scenarios complete.");
128}Sourcepub fn post_response_with<C: C2Transport>(
&self,
responses: Vec<TaskResponse>,
c2: &C,
shared: AgentExtras,
) -> MythicResult<RespPostResponse>
pub fn post_response_with<C: C2Transport>( &self, responses: Vec<TaskResponse>, c2: &C, shared: AgentExtras, ) -> MythicResult<RespPostResponse>
Send task responses, carrying delegates, SOCKS, RPFWD, interactive data, edges, and/or alerts alongside the response.
shared is the AgentExtras portion — it does not contain
responses (those are the first argument).