diff --git a/implants/golem/Cargo.toml b/implants/golem/Cargo.toml index 9c0260e36..45db1ea5f 100644 --- a/implants/golem/Cargo.toml +++ b/implants/golem/Cargo.toml @@ -25,3 +25,6 @@ tempfile = { workspace = true } [target.'cfg(target_os = "windows")'.build-dependencies] static_vcruntime = { workspace = true } + +[features] +verbose-logging = ["pb/verbose-logging", "eldritch-core/verbose-logging", "eldritch-macros/verbose-logging", "eldritch/verbose-logging", "eldritch-agent/verbose-logging"] diff --git a/implants/imix/Cargo.toml b/implants/imix/Cargo.toml index beb68cb11..6f16a6771 100644 --- a/implants/imix/Cargo.toml +++ b/implants/imix/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" crate-type = ["cdylib"] [features] +verbose-logging = ["portal-stream/verbose-logging", "eldritch/verbose-logging", "eldritch-agent/verbose-logging", "transport/verbose-logging", "pb/verbose-logging", "eldritch-libchain/verbose-logging", "transport/verbose-logging"] default = ["install", "grpc", "http1", "dns", "doh", "icmp", "tcp-bind"] grpc = ["transport/grpc"] http1 = ["transport/http1"] diff --git a/implants/imix/src/agent.rs b/implants/imix/src/agent.rs index c0a7ea2ff..c4dd16fbe 100644 --- a/implants/imix/src/agent.rs +++ b/implants/imix/src/agent.rs @@ -156,7 +156,7 @@ impl ImixAgent { } } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!( "Flushing {} task outputs and {} process list reports", outputs.len(), @@ -233,7 +233,7 @@ impl ImixAgent { } for (_, (ctx, output)) in merged_task_outputs { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Task Output: {output:#?}"); let req = ReportOutputRequest { @@ -246,13 +246,13 @@ impl ImixAgent { }; if let Err(_e) = transport.report_output(req).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to report task output: {_e}"); } } for (_, (ctx, output)) in merged_shell_outputs { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Shell Task Output: {output:#?}"); let req = ReportOutputRequest { @@ -265,7 +265,7 @@ impl ImixAgent { }; if let Err(_e) = transport.report_output(req).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to report shell task output: {_e}"); } } @@ -273,7 +273,7 @@ impl ImixAgent { // Only send the latest process list report (it replaces previous ones) if let Some(req) = process_list_reqs.into_iter().last() { if let Err(_e) = transport.report_process_list(req).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to report process list: {_e}"); } } @@ -314,7 +314,7 @@ impl ImixAgent { let t = transport::create_transport(config).context("Failed to create on-demand transport")?; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Created on-demand transport for background task"); Ok(t) @@ -348,11 +348,11 @@ impl ImixAgent { self.runtime_handle.spawn(async move { if let Ok(mut t) = agent.get_usable_transport().await { if let Err(_e) = t.forward_raw(path.clone(), rx, tx).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Deferred forward_raw to {} failed: {}", path, _e); } } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "Failed to get transport for deferred forward_raw to {}", path @@ -370,7 +370,7 @@ impl ImixAgent { let registry = self.task_registry.clone(); let agent = Arc::new(self.clone()); for task in resp.tasks { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Claimed task {}: JWT={}", task.id, task.jwt); registry.spawn(task, agent.clone()); @@ -430,12 +430,12 @@ impl ImixAgent { match agent.get_usable_transport().await { Ok(transport) => { if let Err(_e) = action(transport).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Subtask {} error: {_e:#}", task_id); } } Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Subtask {} failed to get transport: {_e:#}", task_id); } } @@ -861,7 +861,7 @@ impl Agent for ImixAgent { .map_err(|_| "Poisoned lock".to_string())?; if let Some(handle) = map.remove(&task_id) { handle.abort(); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Aborted subtask {task_id}"); } Ok(()) diff --git a/implants/imix/src/install.rs b/implants/imix/src/install.rs index a2f53874a..6580e9847 100644 --- a/implants/imix/src/install.rs +++ b/implants/imix/src/install.rs @@ -7,7 +7,7 @@ use std::sync::Arc; #[cfg(feature = "install")] pub async fn install() -> Result<()> { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("starting installation"); let asset_backend = Arc::new(EmbeddedAssets::::new()); @@ -15,19 +15,19 @@ pub async fn install() -> Result<()> { for embedded_file_path in crate::assets::Asset::iter() { // Find "main.eldritch" files if embedded_file_path.ends_with("main.eldritch") { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("loading tome {}", embedded_file_path); let content = match crate::assets::Asset::get(&embedded_file_path) { Some(f) => String::from_utf8_lossy(&f.data).to_string(), None => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to load install asset: {}", embedded_file_path); continue; } }; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("running tome {}", embedded_file_path); // Execute using Eldritch Interpreter @@ -38,11 +38,11 @@ pub async fn install() -> Result<()> { match interpreter.interpret(&content) { Ok(_) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Successfully executed {embedded_file_path}"); } Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to execute {embedded_file_path}: {_e}"); } } diff --git a/implants/imix/src/main.rs b/implants/imix/src/main.rs index f295c043c..869f5c4fd 100644 --- a/implants/imix/src/main.rs +++ b/implants/imix/src/main.rs @@ -43,7 +43,7 @@ async fn main() -> Result<()> { #[cfg(feature = "install")] { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("beginning installation"); if std::env::args().any(|arg| arg == "install") { @@ -57,7 +57,7 @@ async fn main() -> Result<()> { return Ok(()); } Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to start service (running as exe?): {_err}"); } } diff --git a/implants/imix/src/portal/run.rs b/implants/imix/src/portal/run.rs index 4cdb3ae0f..8f05ce5f5 100644 --- a/implants/imix/src/portal/run.rs +++ b/implants/imix/src/portal/run.rs @@ -32,10 +32,10 @@ pub async fn run( // Note: We use a separate task for transport since it might be long-running let transport_handle = tokio::spawn(async move { if let Err(_e) = transport.create_portal(req_rx, resp_tx).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Portal transport error: {}", _e); } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Portal transport loop exited"); }); @@ -64,7 +64,7 @@ pub async fn run( }) .await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to send initial portal registration: {}", _e); return Err(anyhow::anyhow!( "Failed to send initial portal registration" @@ -80,14 +80,14 @@ pub async fn run( #[allow(clippy::collapsible_if)] if let Some(mote) = resp.mote { if let Err(_e) = handle_incoming_mote(mote, &mut streams, &out_tx, &mut tasks, &shell_manager_tx).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Error handling incoming mote: {}", _e); } } } None => { // Transport closed - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Transport channel closed (resp_rx), shutting down portal loop"); break; } @@ -109,13 +109,13 @@ pub async fn run( mote: Some(mote), }; if let Err(_e) = req_tx.send(req).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to send outgoing mote to transport: {}", _e); break; } } None => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Outgoing mote channel (out_rx) closed"); break; // All handlers closed? Unlikely. } @@ -144,7 +144,7 @@ async fn handle_incoming_mote( if let Some(Payload::Bytes(ref mut bytes_payload)) = mote.payload && bytes_payload.kind == BytesPayloadKind::Trace as i32 { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::trace!("portal trace mote received: {:?}", &bytes_payload.clone()); // 1. Add Agent Recv Event @@ -175,7 +175,7 @@ async fn handle_incoming_mote( // Get or create context if !streams.contains_key(&stream_id) { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] { let seq_id = mote.seq_id; let size = mote.payload.as_ref().map_or(0, |p| match p { @@ -199,10 +199,10 @@ async fn handle_incoming_mote( let task = tokio::spawn(async move { if let Err(_e) = stream_handler(stream_id_clone.clone(), rx, out_tx_clone).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Stream handler error for {}: {}", stream_id_clone, _e); } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Stream handler finished for {}", stream_id_clone); }); tasks.push(task); @@ -218,7 +218,7 @@ async fn handle_incoming_mote( if ctx.tx.send(m).await.is_err() { // Handler closed, maybe remove stream? // For now, we just ignore/log - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Stream handler closed for {}", stream_id); } } @@ -270,13 +270,13 @@ async fn stream_handler( Payload::Udp(_) => udp::handle_udp(first_mote, rx, out_tx, sequencer).await, Payload::Bytes(_) => bytes::handle_bytes(first_mote, rx, out_tx, sequencer).await, Payload::Shell(_) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Shell payloads should have been intercepted before stream handler"); Ok(()) } } } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Received mote with no payload for stream {}", stream_id); Ok(()) } diff --git a/implants/imix/src/portal/tcp.rs b/implants/imix/src/portal/tcp.rs index 8a4d31005..9243029ce 100644 --- a/implants/imix/src/portal/tcp.rs +++ b/implants/imix/src/portal/tcp.rs @@ -22,7 +22,7 @@ pub async fn handle_tcp( let addr = format!("{}:{}", dst_addr, dst_port); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Connecting TCP to {}", addr); let stream = TcpStream::connect(&addr) @@ -34,7 +34,7 @@ pub async fn handle_tcp( .set_nodelay(true) .context("Failed to set TCP_NODELAY")?; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!( "Connected TCP to {} (local: {:?})", addr, @@ -53,7 +53,7 @@ pub async fn handle_tcp( let out_tx_clone = out_tx.clone(); let dst_addr_clone = dst_addr.clone(); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] let addr_for_read = addr.clone(); let read_task = tokio::spawn(async move { @@ -61,12 +61,12 @@ pub async fn handle_tcp( loop { match read_half.read(&mut buf).await { Ok(0) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("TCP connection closed by remote peer: {}", addr_for_read); break; // EOF } Ok(n) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "← TCP {} {n} bytes from portal stream ", dst_addr_clone.clone() @@ -75,7 +75,7 @@ pub async fn handle_tcp( let data = buf[0..n].to_vec(); let mote = sequencer.new_tcp_mote(data, dst_addr_clone.clone(), dst_port); if out_tx_clone.send(mote).await.is_err() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!( "Failed to send mote to C2 (channel closed) for {}", addr_for_read @@ -84,7 +84,7 @@ pub async fn handle_tcp( } } Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Error reading from TCP socket {}: {:?}", addr_for_read, _e); break; } @@ -97,16 +97,16 @@ pub async fn handle_tcp( if let Some(Payload::Tcp(tcp)) = mote.payload && !tcp.data.is_empty() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] let n = tcp.data.len(); match write_half.write_all(&tcp.data).await { Ok(_) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("→ TCP {dst_addr} {n} bytes to portal stream "); } Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to write tcp ({n} bytes)to {}: {_e:?}", addr); break; diff --git a/implants/imix/src/portal/udp.rs b/implants/imix/src/portal/udp.rs index 0272cf7ae..6c58568de 100644 --- a/implants/imix/src/portal/udp.rs +++ b/implants/imix/src/portal/udp.rs @@ -22,7 +22,7 @@ pub async fn handle_udp( let target_addr = format!("{}:{}", dst_addr, dst_port); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Setting up UDP for {}", target_addr); // Bind to 0.0.0.0:0 @@ -30,7 +30,7 @@ pub async fn handle_udp( .await .context("Failed to bind UDP")?; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("UDP bound to {:?}", socket.local_addr()); socket @@ -38,7 +38,7 @@ pub async fn handle_udp( .await .context("Failed to connect UDP")?; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("UDP connected to {}", target_addr); let socket = Arc::new(socket); @@ -53,7 +53,7 @@ pub async fn handle_udp( let out_tx_clone = out_tx.clone(); let dst_addr_clone = dst_addr.clone(); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] let addr_for_read = target_addr.clone(); let read_task = tokio::spawn(async move { @@ -64,7 +64,7 @@ pub async fn handle_udp( let data = buf[0..n].to_vec(); let mote = sequencer.new_udp_mote(data, dst_addr_clone.clone(), dst_port); if out_tx_clone.send(mote).await.is_err() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!( "Failed to send UDP mote to C2 (channel closed) for {}", addr_for_read @@ -73,7 +73,7 @@ pub async fn handle_udp( } } Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to read from udp socket ({}): {_e:?}", addr_for_read); } } @@ -88,7 +88,7 @@ pub async fn handle_udp( match socket.send(&udp.data).await { Ok(_) => {} Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to write udp to {}: {_e:?}", target_addr); break; diff --git a/implants/imix/src/run.rs b/implants/imix/src/run.rs index d0486cd98..b504a62fd 100644 --- a/implants/imix/src/run.rs +++ b/implants/imix/src/run.rs @@ -17,7 +17,7 @@ pub async fn run_agent() -> Result<()> { // Load config / defaults let config = Config::default_with_imix_version(VERSION); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Loaded config: {config:#?}"); let run_once = config.run_once; @@ -42,7 +42,7 @@ pub async fn run_agent() -> Result<()> { let mut last_interval = agent.get_callback_interval_u64().unwrap_or(5); // Do we need to move this into the loop and check the agent_ref? - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Agent initialized"); while !SHUTDOWN.load(Ordering::Relaxed) { @@ -61,7 +61,7 @@ pub async fn run_agent() -> Result<()> { } if let Err(e) = sleep_until_next_cycle(&agent, start).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "Failed to sleep, falling back to last interval {last_interval} sec: {e:#}" ); @@ -71,14 +71,14 @@ pub async fn run_agent() -> Result<()> { } } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Agent shutting down"); Ok(()) } pub fn init_logger() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] { use pretty_env_logger; let _ = pretty_env_logger::formatted_timed_builder() @@ -100,7 +100,7 @@ async fn run_agent_cycle(agent: Arc, registry: Arc) { match transport::create_transport(config) { Ok(t) => t, Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to create transport: {_e:#}"); agent.rotate_callback_uri().await; return; @@ -123,11 +123,11 @@ async fn run_agent_cycle(agent: Arc, registry: Arc) { async fn process_tasks(agent: &ImixAgent, _registry: &TaskRegistry) { match agent.process_job_request().await { Ok(_) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Callback success"); } Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Callback failed: {_e:#}"); agent.rotate_callback_uri().await; } @@ -150,7 +150,7 @@ async fn sleep_until_next_cycle(agent: &ImixAgent, start: Instant) -> Result<()> let delay = Duration::from_secs_f32(sleep_secs); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!( "Callback complete (duration={:.2}s, sleep={:.2}s, interval={}s, jitter={:.2})", elapsed_secs, diff --git a/implants/imix/src/shell/manager.rs b/implants/imix/src/shell/manager.rs index 5e001f6b7..7a3df3504 100644 --- a/implants/imix/src/shell/manager.rs +++ b/implants/imix/src/shell/manager.rs @@ -71,7 +71,7 @@ fn dispatch_output( }; if let Err(e) = agent.report_output(req) { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "Failed to report shell task output {}: {}", stc.shell_task_id, @@ -102,7 +102,7 @@ fn dispatch_output( let tx = tx.clone(); tokio::spawn(async move { if let Err(e) = tx.send(mote).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to send shell output to portal: {}", e); } }); diff --git a/implants/imix/src/shell/parser.rs b/implants/imix/src/shell/parser.rs index c56a1c4ad..f53b78ebf 100644 --- a/implants/imix/src/shell/parser.rs +++ b/implants/imix/src/shell/parser.rs @@ -17,7 +17,7 @@ impl InputParser { } pub fn parse(&mut self, data: &[u8]) -> Vec { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Received raw bytes: {data:02x?}"); self.buffer.extend_from_slice(data); @@ -59,7 +59,7 @@ impl InputParser { if let Some(input) = self.parse_csi(seq) { inputs.push(input); } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Ignored CSI sequence: {seq:02x?}"); } // Consume @@ -68,7 +68,7 @@ impl InputParser { // Incomplete CSI or very long garbage if self.buffer.len() > 32 { // Safety valve: sequence too long, probably garbage. Consume ESC and continue. - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!( "Dropping long incomplete CSI buffer: {:02x?}", &self.buffer[..32] @@ -90,7 +90,7 @@ impl InputParser { if let Some(input) = self.parse_ss3(code) { inputs.push(input); } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Ignored SS3 sequence: {_seq:02x?}"); } self.buffer.drain(0..3); @@ -98,7 +98,7 @@ impl InputParser { _ => { // Unknown Escape Sequence or Alt+Key // To be safe and avoid "random characters injected", we consume ESC and the next char. - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Unknown Escape sequence start: 1b {second:02x}"); self.buffer.drain(0..2); } @@ -122,7 +122,7 @@ impl InputParser { x if x >= 0x20 => inputs.push(Input::Char(x as char)), _ => { // Other control codes? Ignore them to prevent weirdness - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Ignored control char: {b:02x}"); } } diff --git a/implants/imix/src/shell/pty.rs b/implants/imix/src/shell/pty.rs index 6da011184..8e012d9c7 100644 --- a/implants/imix/src/shell/pty.rs +++ b/implants/imix/src/shell/pty.rs @@ -19,7 +19,7 @@ pub async fn run_reverse_shell_pty( // We will recreate the internal channels needed for the loop. let (internal_exit_tx, mut internal_exit_rx) = tokio::sync::mpsc::channel(1); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("starting reverse_shell_pty (context={:?})", context); let context_val = match &context { @@ -38,7 +38,7 @@ pub async fn run_reverse_shell_pty( }) .await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to send initial registration message: {_err}"); } @@ -105,7 +105,7 @@ pub async fn run_reverse_shell_pty( let n = match reader.read(&mut buffer[..]) { Ok(n) => n, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to read pty: {_err}"); break; } @@ -115,12 +115,12 @@ pub async fn run_reverse_shell_pty( match internal_exit_rx.try_recv() { Ok(None) | Err(tokio::sync::mpsc::error::TryRecvError::Empty) => {} Ok(Some(_status)) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("closing output stream, pty exited: {_status}"); break; } Err(tokio::sync::mpsc::error::TryRecvError::Disconnected) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("closing output stream, exit channel closed"); } } @@ -135,7 +135,7 @@ pub async fn run_reverse_shell_pty( }) .await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("reverse_shell_pty output failed to queue: {_err}"); break; } @@ -149,7 +149,7 @@ pub async fn run_reverse_shell_pty( }) .await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("reverse_shell_pty ping failed: {_err}"); break; } @@ -165,7 +165,7 @@ pub async fn run_reverse_shell_pty( // Handle Input loop { if let Ok(Some(_status)) = child.try_wait() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("closing input stream, pty exited: {_status}"); break; } @@ -181,13 +181,13 @@ pub async fn run_reverse_shell_pty( }) .await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("reverse_shell_pty ping echo failed: {_err}"); } continue; } if let Err(_err) = writer.write_all(&msg.data) { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("reverse_shell_pty failed to write input: {_err}"); } } else { @@ -201,7 +201,7 @@ pub async fn run_reverse_shell_pty( let _ = internal_exit_tx.send(Some(s)).await; } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("stopping reverse_shell_pty"); Ok(()) } diff --git a/implants/imix/src/shell/repl.rs b/implants/imix/src/shell/repl.rs index eee4242e8..b403e4f60 100644 --- a/implants/imix/src/shell/repl.rs +++ b/implants/imix/src/shell/repl.rs @@ -107,7 +107,7 @@ pub async fn run_repl_reverse_shell( let (output_tx, output_rx) = tokio::sync::mpsc::channel(100); let (input_tx, mut input_rx) = tokio::sync::mpsc::channel(100); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("starting repl_reverse_shell (context={:?})", context); let context_val = match &context { @@ -126,7 +126,7 @@ pub async fn run_repl_reverse_shell( }) .await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to send initial registration message: {_err}"); } @@ -318,7 +318,7 @@ pub async fn run_repl_reverse_shell( let mut pending_render = false; for (i, input) in inputs.iter().enumerate() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Handling input: {input:?}"); let action = repl.handle_input(input.clone()); match action { diff --git a/implants/imix/src/task.rs b/implants/imix/src/task.rs index d289500f5..6cf68eb24 100644 --- a/implants/imix/src/task.rs +++ b/implants/imix/src/task.rs @@ -62,19 +62,19 @@ impl TaskRegistry { let runtime_handle = tokio::runtime::Handle::current(); // 2. Spawn thread - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Spawning Task: {0}", task_context.clone().task_id); thread::spawn(move || { if let Some(tome) = task.tome { execute_task(context, tome, agent, runtime_handle); } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Task {0} has no tome", task_context.clone().task_id); } // Cleanup - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Completed Task: {0}", task_context.clone().task_id); let mut tasks = tasks_registry.lock().unwrap(); tasks.remove(&task_context.task_id); @@ -112,7 +112,7 @@ impl TaskRegistry { } else { // Task might have finished already, or this is an orphan subtask. // In the future we might want to track these anyway. - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Attempted to register subtask '{name}' for non-existent task {task_id}"); } } @@ -133,7 +133,7 @@ impl TaskRegistry { pub fn stop(&self, task_id: i64) { let mut tasks = self.tasks.lock().unwrap(); if let Some(handle) = tasks.remove(&task_id) { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("Task {task_id} stop requested (thread may persist)"); let subtasks = handle.subtasks.read().unwrap(); @@ -195,7 +195,7 @@ fn execute_task( match runtime_handle.block_on(consumer_join_handle) { Ok(_) => {} Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "task={0} failed to wait for output consumer to join: {_e}", task_id @@ -245,7 +245,7 @@ fn report_start(context: Context, agent: &Arc) { _ => return, // Only reporting for TaskContext }; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("task={task_id} Started execution"); match agent.report_output(ReportOutputRequest { @@ -264,7 +264,7 @@ fn report_start(context: Context, agent: &Arc) { }) { Ok(_) => {} Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("task={task_id} failed to report task start: {_e}"); } } @@ -283,7 +283,7 @@ fn spawn_output_consumer( _ => return, // Only reporting for TaskContext }; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("task={} Started output stream", task_id); let mut rx_open = true; let mut error_rx_open = true; @@ -309,7 +309,7 @@ fn spawn_output_consumer( }) { Ok(_) => {} Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("task={task_id} failed to report output: {_e}"); } } @@ -338,7 +338,7 @@ fn spawn_output_consumer( }) { Ok(_) => {} Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("task={task_id} failed to report error: {_e}"); } } @@ -379,7 +379,7 @@ fn report_panic(context: Context, agent: &Arc, err: String) { }) { Ok(_) => {} Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("task={task_id} failed to report error: {_e}"); } } @@ -393,7 +393,7 @@ fn report_result(context: Context, result: Result, agent: &Arc { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("task={task_id} Success: {v}"); let _ = agent.report_output(ReportOutputRequest { @@ -412,7 +412,7 @@ fn report_result(context: Context, result: Result, agent: &Arc { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("task={task_id} Error: {e}"); match agent.report_output(ReportOutputRequest { @@ -431,7 +431,7 @@ fn report_result(context: Context, result: Result, agent: &Arc {} Err(_e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("task={task_id} failed to report task error: {_e}"); } } diff --git a/implants/lib/eldritch/eldritch-agent/Cargo.toml b/implants/lib/eldritch/eldritch-agent/Cargo.toml index ece9ba48a..14e63b1a5 100644 --- a/implants/lib/eldritch/eldritch-agent/Cargo.toml +++ b/implants/lib/eldritch/eldritch-agent/Cargo.toml @@ -7,3 +7,6 @@ edition = "2021" pb = { workspace = true } tokio = { workspace = true, features = ["sync"] } async-trait = { workspace = true } + +[features] +verbose-logging = ["pb/verbose-logging"] diff --git a/implants/lib/eldritch/eldritch-core/Cargo.toml b/implants/lib/eldritch/eldritch-core/Cargo.toml index fd0fdb674..cc11a544c 100644 --- a/implants/lib/eldritch/eldritch-core/Cargo.toml +++ b/implants/lib/eldritch/eldritch-core/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" crate-type = ["cdylib", "rlib"] [features] +verbose-logging = [] default = [] no_std = [] std = [] diff --git a/implants/lib/eldritch/eldritch-core/fuzz/Cargo.toml b/implants/lib/eldritch/eldritch-core/fuzz/Cargo.toml index 7a90681dd..3348a2fe6 100644 --- a/implants/lib/eldritch/eldritch-core/fuzz/Cargo.toml +++ b/implants/lib/eldritch/eldritch-core/fuzz/Cargo.toml @@ -29,3 +29,6 @@ path = "fuzz_targets/operations.rs" [workspace] members = ["."] + +[features] +verbose-logging = [] diff --git a/implants/lib/eldritch/eldritch-lsp/Cargo.toml b/implants/lib/eldritch/eldritch-lsp/Cargo.toml index b9c20c20c..94a4d8f4d 100644 --- a/implants/lib/eldritch/eldritch-lsp/Cargo.toml +++ b/implants/lib/eldritch/eldritch-lsp/Cargo.toml @@ -13,3 +13,6 @@ serde_json = "1.0" anyhow = "1.0" log = "0.4" env_logger = "0.11" + +[features] +verbose-logging = ["eldritch-core/verbose-logging"] diff --git a/implants/lib/eldritch/eldritch-macros/Cargo.toml b/implants/lib/eldritch/eldritch-macros/Cargo.toml index 8ff5ee6c0..fcc723b77 100644 --- a/implants/lib/eldritch/eldritch-macros/Cargo.toml +++ b/implants/lib/eldritch/eldritch-macros/Cargo.toml @@ -4,6 +4,7 @@ version = "0.3.4" edition = "2024" [features] +verbose-logging = [] [lib] proc-macro = true diff --git a/implants/lib/eldritch/eldritch-repl/Cargo.toml b/implants/lib/eldritch/eldritch-repl/Cargo.toml index d9d966dcd..3d67fd193 100644 --- a/implants/lib/eldritch/eldritch-repl/Cargo.toml +++ b/implants/lib/eldritch/eldritch-repl/Cargo.toml @@ -17,3 +17,6 @@ log = { workspace = true } [dev-dependencies] criterion = { workspace = true } + +[features] +verbose-logging = ["eldritch-core/verbose-logging"] diff --git a/implants/lib/eldritch/eldritch-repl/src/parser.rs b/implants/lib/eldritch/eldritch-repl/src/parser.rs index 56ea743db..7dde05afd 100644 --- a/implants/lib/eldritch/eldritch-repl/src/parser.rs +++ b/implants/lib/eldritch/eldritch-repl/src/parser.rs @@ -18,7 +18,7 @@ impl InputParser { } pub fn parse(&mut self, data: &[u8]) -> Vec { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Received raw bytes: {data:02x?}"); self.buffer.extend_from_slice(data); @@ -60,7 +60,7 @@ impl InputParser { if let Some(input) = self.parse_csi(seq) { inputs.push(input); } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Ignored CSI sequence: {seq:02x?}"); } // Consume @@ -69,7 +69,7 @@ impl InputParser { // Incomplete CSI or very long garbage if self.buffer.len() > 32 { // Safety valve: sequence too long, probably garbage. Consume ESC and continue. - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!( "Dropping long incomplete CSI buffer: {:02x?}", &self.buffer[..32] @@ -91,7 +91,7 @@ impl InputParser { if let Some(input) = self.parse_ss3(code) { inputs.push(input); } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Ignored SS3 sequence: {seq:02x?}"); #[cfg(not(debug_assertions))] let _ = seq; @@ -101,7 +101,7 @@ impl InputParser { _ => { // Unknown Escape Sequence or Alt+Key // To be safe and avoid "random characters injected", we consume ESC and the next char. - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!("Unknown Escape sequence start: 1b {second:02x}"); self.buffer.drain(0..2); } @@ -125,7 +125,7 @@ impl InputParser { x if x >= 0x20 => inputs.push(Input::Char(x as char)), _ => { // Other control codes? Ignore them to prevent weirdness - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Ignored control char: {b:02x}"); } } diff --git a/implants/lib/eldritch/eldritch-wasm/Cargo.toml b/implants/lib/eldritch/eldritch-wasm/Cargo.toml index 7ad3c54f5..b38373737 100644 --- a/implants/lib/eldritch/eldritch-wasm/Cargo.toml +++ b/implants/lib/eldritch/eldritch-wasm/Cargo.toml @@ -4,6 +4,7 @@ version = "0.3.4" edition = "2024" [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-repl/verbose-logging"] stdlib = ["eldritch/stdlib", "eldritch/std"] fake_bindings = ["eldritch/fake_bindings"] diff --git a/implants/lib/eldritch/eldritch/Cargo.toml b/implants/lib/eldritch/eldritch/Cargo.toml index 481906a2e..a199c4dc2 100644 --- a/implants/lib/eldritch/eldritch/Cargo.toml +++ b/implants/lib/eldritch/eldritch/Cargo.toml @@ -28,6 +28,7 @@ pb = { workspace = true, optional = true } eldritch-repl = { workspace = true, default-features = false } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging", "eldritch-agent/verbose-logging", "eldritch-libagent/verbose-logging", "eldritch-libassets/verbose-logging", "eldritch-libcrypto/verbose-logging", "eldritch-libfile/verbose-logging", "eldritch-libhttp/verbose-logging", "eldritch-libpivot/verbose-logging", "eldritch-libprocess/verbose-logging", "eldritch-librandom/verbose-logging", "eldritch-libregex/verbose-logging", "eldritch-libreport/verbose-logging", "eldritch-libsys/verbose-logging", "eldritch-libtime/verbose-logging", "eldritch-libchain/verbose-logging", "pb/verbose-logging", "eldritch-repl/verbose-logging", "eldritch-mockagent/verbose-logging"] default = ["std", "stdlib"] std = ["eldritch-core/std"] fake_bindings = [ diff --git a/implants/lib/eldritch/stdlib/eldritch-libagent/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libagent/Cargo.toml index 68d6821ba..3030ea81a 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libagent/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libagent/Cargo.toml @@ -17,6 +17,7 @@ prost-types = { workspace = true, optional = true } spin = { version = "0.10.0", features = ["rwlock"] } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging", "eldritch-agent/verbose-logging", "pb/verbose-logging", "eldritch-mockagent/verbose-logging"] default = ["stdlib"] stdlib = ["dep:eldritch-agent", "dep:serde_json", "dep:pb", "dep:prost", "dep:prost-types"] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/eldritch-libassets/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libassets/Cargo.toml index 197707df0..89bcef412 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libassets/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libassets/Cargo.toml @@ -13,6 +13,7 @@ rust-embed = { version = "8.0" } log = { workspace = true } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging", "eldritch-agent/verbose-logging", "pb/verbose-logging", "eldritch-mockagent/verbose-logging"] default = ["std", "stdlib"] std = ["eldritch-core/std"] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/eldritch-libchain/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libchain/Cargo.toml index f3e0ecefb..4ba78b576 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libchain/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libchain/Cargo.toml @@ -19,6 +19,7 @@ eldritch-core = { workspace = true } eldritch-macros = { workspace = true } [features] +verbose-logging = ["pb/verbose-logging", "eldritch-agent/verbose-logging", "eldritch-core/verbose-logging", "eldritch-macros/verbose-logging"] default = ["stdlib"] stdlib = [] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/eldritch-libchain/src/std/chain_impl.rs b/implants/lib/eldritch/stdlib/eldritch-libchain/src/std/chain_impl.rs index 54b1b296d..b5dfe9d15 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libchain/src/std/chain_impl.rs +++ b/implants/lib/eldritch/stdlib/eldritch-libchain/src/std/chain_impl.rs @@ -5,7 +5,7 @@ use std::sync::Arc; pub fn tcp(addr: String, agent: Arc) -> Result { tokio::spawn(async move { if let Err(_e) = crate::tcp_impl::start_tcp_chain_server(&addr, agent).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("tcp chain proxy error: {}", _e); } }); diff --git a/implants/lib/eldritch/stdlib/eldritch-libchain/src/tcp_impl.rs b/implants/lib/eldritch/stdlib/eldritch-libchain/src/tcp_impl.rs index 108fee56b..648e1db42 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libchain/src/tcp_impl.rs +++ b/implants/lib/eldritch/stdlib/eldritch-libchain/src/tcp_impl.rs @@ -15,7 +15,7 @@ async fn handle_request( mut req: HyperRequest, ) -> Result>, Infallible> { let path = req.uri().path().to_string(); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("[tcp-chain-server] incoming forward request: {}", path); let grpc_response = |body: Vec| { @@ -28,7 +28,7 @@ async fn handle_request( }; let _grpc_error = |code: u32, msg: String| { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("tcp chain proxy: {} — {}", path, msg); HyperResponse::builder() .status(200) @@ -46,7 +46,7 @@ async fn handle_request( let agent_clone = agent.clone(); if let Err(e) = agent_clone.forward_raw(path_clone, rx_in, tx_out).await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("tcp forward_raw error: {}", e); #[cfg(not(debug_assertions))] let _ = e; @@ -101,7 +101,7 @@ async fn handle_request( /// Agent B's C2 messages enter through the TCP socket and exit through /// Agent A's normal upstream channel. pub async fn start_tcp_chain_server(addr: &str, agent: Arc) -> Result<()> { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!( "[tcp-chain-server] connecting to Agent B's TCP listener at {}", addr @@ -109,12 +109,12 @@ pub async fn start_tcp_chain_server(addr: &str, agent: Arc) -> Result let stream = match tokio::net::TcpStream::connect(addr).await { Ok(s) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("[tcp-chain-server] connected to Agent B at {}", addr); s } Err(e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("[tcp-chain-server] connect error: {}", e); return Err(anyhow!( "Failed to connect to Agent B TCP listener at {}: {}", @@ -127,7 +127,7 @@ pub async fn start_tcp_chain_server(addr: &str, agent: Arc) -> Result let agent_clone = agent.clone(); let io = TokioIo::new(stream); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("[tcp-chain-server] starting HTTP/2 on connection to Agent B"); let service = service_fn(move |req| { let a = agent_clone.clone(); @@ -138,12 +138,12 @@ pub async fn start_tcp_chain_server(addr: &str, agent: Arc) -> Result .serve_connection(io, service) .await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("[tcp-chain-server] HTTP/2 connection error: {:?}", err); return Err(anyhow!("HTTP/2 connection to Agent B failed: {:?}", err)); } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("[tcp-chain-server] connection closed cleanly"); Ok(()) } diff --git a/implants/lib/eldritch/stdlib/eldritch-libcrypto/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libcrypto/Cargo.toml index a2fcfa166..09fae0efc 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libcrypto/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libcrypto/Cargo.toml @@ -4,6 +4,7 @@ version = "0.3.4" edition = "2024" [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging"] default = ["stdlib"] stdlib = [ "dep:aes", diff --git a/implants/lib/eldritch/stdlib/eldritch-libfile/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libfile/Cargo.toml index 10d266e6f..73bf8b17d 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libfile/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libfile/Cargo.toml @@ -4,6 +4,7 @@ version = "0.3.4" edition = "2024" [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging"] default = ["stdlib"] stdlib = [ "dep:flate2", diff --git a/implants/lib/eldritch/stdlib/eldritch-libhttp/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libhttp/Cargo.toml index e054f3411..a0329c1da 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libhttp/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libhttp/Cargo.toml @@ -16,6 +16,7 @@ tokio = { version = "1", features = ["rt", "macros"], optional = true } futures = { version = "0.3", optional = true } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging"] default = ["stdlib"] stdlib = ["dep:reqwest", "dep:tokio", "dep:futures"] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/eldritch-libpivot/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libpivot/Cargo.toml index 1f22e9979..64601b2f2 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libpivot/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libpivot/Cargo.toml @@ -33,6 +33,7 @@ tempfile = { workspace = true } eldritch-agent = { workspace = true } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging", "eldritch-agent/verbose-logging", "pb/verbose-logging", "eldritch-mockagent/verbose-logging", "eldritch-agent/verbose-logging"] default = ["stdlib"] stdlib = [ "dep:eldritch-agent", diff --git a/implants/lib/eldritch/stdlib/eldritch-libpivot/src/std/arp_scan_impl.rs b/implants/lib/eldritch/stdlib/eldritch-libpivot/src/std/arp_scan_impl.rs index c2e6d03b3..b1cbca6c2 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libpivot/src/std/arp_scan_impl.rs +++ b/implants/lib/eldritch/stdlib/eldritch-libpivot/src/std/arp_scan_impl.rs @@ -224,7 +224,7 @@ pub fn handle_arp_scan( move || match start_listener(inner_interface.clone(), inner_out) { Ok(_) => {} Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Listener on {} failed: {}", inner_interface.name, _err); } }, diff --git a/implants/lib/eldritch/stdlib/eldritch-libprocess/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libprocess/Cargo.toml index 5b6dc098b..d0f109c51 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libprocess/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libprocess/Cargo.toml @@ -14,6 +14,7 @@ netstat = { workspace = true } libc = { workspace = true } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging", "netstat/verbose-logging"] default = ["stdlib"] stdlib = ["dep:sysinfo"] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/eldritch-librandom/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-librandom/Cargo.toml index de75b1939..7c665e46c 100644 --- a/implants/lib/eldritch/stdlib/eldritch-librandom/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-librandom/Cargo.toml @@ -11,6 +11,7 @@ rand_chacha = { workspace = true, optional = true } uuid = { workspace = true, optional = true, features = ["v4", "fast-rng"] } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging"] default = ["stdlib"] stdlib = ["dep:rand", "dep:rand_chacha", "dep:uuid"] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/eldritch-libregex/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libregex/Cargo.toml index d80ed8e7b..464b24290 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libregex/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libregex/Cargo.toml @@ -9,6 +9,7 @@ eldritch-macros = { workspace = true } regex = { workspace = true, optional = true } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging"] default = ["stdlib"] stdlib = ["dep:regex"] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/eldritch-libreport/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libreport/Cargo.toml index 8134acee0..d6073b441 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libreport/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libreport/Cargo.toml @@ -18,6 +18,7 @@ xcap = { workspace = true, optional = true } image = { version = "0.25", optional = true } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging", "eldritch-agent/verbose-logging", "pb/verbose-logging", "eldritch-libprocess/verbose-logging"] default = ["stdlib"] stdlib = ["dep:pb", "dep:eldritch-agent", "dep:nix", "dep:xcap", "dep:image"] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/eldritch-libsys/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libsys/Cargo.toml index 31c11fef3..3871b371b 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libsys/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libsys/Cargo.toml @@ -32,6 +32,7 @@ windows-sys = { workspace = true, features = [ ] } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging"] default = ["stdlib"] stdlib = ["dep:sysinfo", "dep:whoami", "dep:local-ip-address", "dep:hex"] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/eldritch-libtime/Cargo.toml b/implants/lib/eldritch/stdlib/eldritch-libtime/Cargo.toml index b475fb708..201ecc65d 100644 --- a/implants/lib/eldritch/stdlib/eldritch-libtime/Cargo.toml +++ b/implants/lib/eldritch/stdlib/eldritch-libtime/Cargo.toml @@ -13,6 +13,7 @@ chrono = { version = "0.4", optional = true } anyhow = { version = "1.0", optional = true } [features] +verbose-logging = ["eldritch-core/verbose-logging", "eldritch-macros/verbose-logging"] default = ["stdlib"] stdlib = ["dep:chrono", "dep:anyhow"] fake_bindings = [] diff --git a/implants/lib/eldritch/stdlib/tests/Cargo.toml b/implants/lib/eldritch/stdlib/tests/Cargo.toml index 523ef045e..daf2c4823 100644 --- a/implants/lib/eldritch/stdlib/tests/Cargo.toml +++ b/implants/lib/eldritch/stdlib/tests/Cargo.toml @@ -12,3 +12,6 @@ serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" spin = { version = "0.10.0", features = ["rwlock"] } log = "0.4" + +[features] +verbose-logging = ["eldritch/verbose-logging", "eldritch-core/verbose-logging"] diff --git a/implants/lib/eldritch/testutils/eldritch-mockagent/Cargo.toml b/implants/lib/eldritch/testutils/eldritch-mockagent/Cargo.toml index 11726ccb8..1bcb6fbaa 100644 --- a/implants/lib/eldritch/testutils/eldritch-mockagent/Cargo.toml +++ b/implants/lib/eldritch/testutils/eldritch-mockagent/Cargo.toml @@ -8,3 +8,6 @@ eldritch-agent = { path = "../../eldritch-agent" } pb = { path = "../../../pb" } tokio = { workspace = true, features = ["sync"] } async-trait = { workspace = true } + +[features] +verbose-logging = ["eldritch-agent/verbose-logging", "pb/verbose-logging"] diff --git a/implants/lib/guardrails/Cargo.toml b/implants/lib/guardrails/Cargo.toml index 80a8decf4..6cb64d279 100644 --- a/implants/lib/guardrails/Cargo.toml +++ b/implants/lib/guardrails/Cargo.toml @@ -18,3 +18,6 @@ serde_json = { workspace = true } [dev-dependencies] pretty_env_logger = "0.5.0" tempfile = { workspace = true } + +[features] +verbose-logging = [] diff --git a/implants/lib/guardrails/src/lib.rs b/implants/lib/guardrails/src/lib.rs index c9881c8be..92c088374 100644 --- a/implants/lib/guardrails/src/lib.rs +++ b/implants/lib/guardrails/src/lib.rs @@ -77,11 +77,11 @@ pub fn check_guardrails(guardrails: Vec>) -> bool { for guardrail in guardrails { if guardrail.check() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Guardrail {} passed", guardrail.get_name()); return true; } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Guardrail {} failed", guardrail.get_name()); } false diff --git a/implants/lib/host_unique/Cargo.toml b/implants/lib/host_unique/Cargo.toml index d203d8a7b..e8b4a674f 100644 --- a/implants/lib/host_unique/Cargo.toml +++ b/implants/lib/host_unique/Cargo.toml @@ -21,3 +21,6 @@ serde_json = { workspace = true } [dev-dependencies] pretty_env_logger = "0.5.0" tempfile = { workspace = true } + +[features] +verbose-logging = ["netstat/verbose-logging"] diff --git a/implants/lib/host_unique/src/env.rs b/implants/lib/host_unique/src/env.rs index 6bcab7aff..68179a6a8 100644 --- a/implants/lib/host_unique/src/env.rs +++ b/implants/lib/host_unique/src/env.rs @@ -15,7 +15,7 @@ impl HostIDSelector for Env { let host_id_env = match env::var("IMIX_HOST_ID") { Ok(res) => res, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("No environment variable set {:?}", _err); return None; } @@ -23,7 +23,7 @@ impl HostIDSelector for Env { match Uuid::parse_str(&host_id_env) { Ok(res) => Some(res), Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Failed to deploy {:?}", _err); None } diff --git a/implants/lib/host_unique/src/file.rs b/implants/lib/host_unique/src/file.rs index 62b394086..41ba60478 100644 --- a/implants/lib/host_unique/src/file.rs +++ b/implants/lib/host_unique/src/file.rs @@ -69,7 +69,7 @@ impl HostIDSelector for File { match f.read_exact(&mut host_id) { Ok(_) => {} Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Failed to read host_id {:?}", _err); } } @@ -77,7 +77,7 @@ impl HostIDSelector for File { match Uuid::parse_str(uuid_str) { Ok(res) => return Some(res), Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Failed to deploy {:?}", _err); } }; @@ -96,12 +96,12 @@ impl HostIDSelector for File { return Some(host_id); } Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("failed to write host id file: {_err}"); } }, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("failed to create host id file: {_err}"); } }; diff --git a/implants/lib/host_unique/src/lib.rs b/implants/lib/host_unique/src/lib.rs index 18df69cbd..bce4f300b 100644 --- a/implants/lib/host_unique/src/lib.rs +++ b/implants/lib/host_unique/src/lib.rs @@ -114,7 +114,7 @@ pub fn get_id_with_selectors(selectors: Vec>) -> Uuid { return res; } None => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Unique selector {} failed", selector.get_name()); } } diff --git a/implants/lib/host_unique/src/registry.rs b/implants/lib/host_unique/src/registry.rs index 32356e35d..8c4a6576c 100644 --- a/implants/lib/host_unique/src/registry.rs +++ b/implants/lib/host_unique/src/registry.rs @@ -61,14 +61,14 @@ impl HostIDSelector for Registry { match hklm.create_subkey(self.key_path()) { Ok((k, _disp)) => k, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("failed to create registry key: {:?}", _err); return None; } } } Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("failed to open registry key: {:?}", _err); return None; } @@ -79,7 +79,7 @@ impl HostIDSelector for Registry { if let Ok(uuid) = Uuid::parse_str(&stored) { return Some(uuid); } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("invalid UUID in registry: {:?}", stored); } } @@ -88,7 +88,7 @@ impl HostIDSelector for Registry { let new_uuid = Uuid::new_v4(); let s = new_uuid.to_string(); if let Err(_err) = key.set_value(self.val_name(), &s) { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("failed to write registry value: {:?}", _err); } Some(new_uuid) diff --git a/implants/lib/netstat/Cargo.toml b/implants/lib/netstat/Cargo.toml index 7b8912ee3..1554fcf76 100644 --- a/implants/lib/netstat/Cargo.toml +++ b/implants/lib/netstat/Cargo.toml @@ -32,3 +32,6 @@ byteorder = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true, features = ["full"] } tokio-test = { workspace = true } + +[features] +verbose-logging = [] diff --git a/implants/lib/pb/Cargo.toml b/implants/lib/pb/Cargo.toml index c755b0b04..807a0aa38 100644 --- a/implants/lib/pb/Cargo.toml +++ b/implants/lib/pb/Cargo.toml @@ -4,6 +4,7 @@ version = "0.0.5" edition = "2021" [features] +verbose-logging = ["host_unique/verbose-logging", "guardrails/verbose-logging"] default = [] imix = [] grpc = [] diff --git a/implants/lib/pb/src/config.rs b/implants/lib/pb/src/config.rs index 3439831cf..9a098f30d 100644 --- a/implants/lib/pb/src/config.rs +++ b/implants/lib/pb/src/config.rs @@ -149,7 +149,7 @@ pub fn parse_dsn(uri: &str) -> anyhow::Result { .with_context(|| format!("Failed to parse jitter parameter '{}'", value))?; } _ => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Ignoring unknown query parameter: {}", key); } } @@ -186,7 +186,7 @@ fn parse_host_unique_selectors() -> Vec> { if let Some(res) = host_unique::from_imix_unique(json.to_owned()) { return res; } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "Error parsing uniqueness string (should have been caught at build time" ); @@ -204,7 +204,7 @@ fn parse_guardrails() -> Vec> { if let Some(res) = guardrails::from_imix_guardrails(json.to_owned()) { return res; } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "Error parsing guardrails string (should have been caught at build time)" ); @@ -249,7 +249,7 @@ impl Config { let guardrails = parse_guardrails(); if !guardrails::check_guardrails(guardrails) { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Guardrails failed, exiting"); std::process::exit(0); } @@ -280,12 +280,12 @@ impl Config { h.primary_ip = fresh_ip; } None => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("host struct was never initialized, failed to set primary ip"); } }, None => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("beacon struct was never initialized, failed to set primary ip"); } } @@ -331,7 +331,7 @@ fn get_primary_ip() -> String { None => String::from(""), }, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to get primary ip: {_err}"); String::from("") diff --git a/implants/lib/pb/src/xchacha.rs b/implants/lib/pb/src/xchacha.rs index d9a8665dd..02c4cfa3f 100644 --- a/implants/lib/pb/src/xchacha.rs +++ b/implants/lib/pb/src/xchacha.rs @@ -81,7 +81,7 @@ fn encrypt_impl(pt_vec: Vec) -> Result> { let ciphertext: Vec = match cipher.encrypt(&nonce, pt_vec.as_slice()) { Ok(ct) => ct, Err(err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "encode error unable to read bytes while encrypting: {:?}", err @@ -145,7 +145,7 @@ pub struct ChachaCodec(PhantomData<(T, U)>, ChaChaSvc); impl Default for ChachaCodec { fn default() -> Self { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Loaded custom codec with xchacha encryption"); Self(PhantomData, ChaChaSvc::default()) } @@ -186,7 +186,7 @@ where fn encode(&mut self, item: Self::Item, buf: &mut EncodeBuf<'_>) -> Result<(), Self::Error> { if !buf.has_remaining_mut() { // This should never happen but if it does the agent will be unable to queue new messages to the buffer until it's drained. - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("DANGER can't add to the buffer."); } @@ -220,7 +220,7 @@ where let bytes_read = match reader.read_to_end(&mut bytes_in) { Ok(n) => n, Err(err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "decode error unable to read bytes from decode reader: {:?}", err diff --git a/implants/lib/portals/portal-stream/Cargo.toml b/implants/lib/portals/portal-stream/Cargo.toml index b546ece68..94fb3a875 100644 --- a/implants/lib/portals/portal-stream/Cargo.toml +++ b/implants/lib/portals/portal-stream/Cargo.toml @@ -4,6 +4,7 @@ version = "0.3.4" edition = "2024" [features] +verbose-logging = ["pb/verbose-logging"] default = ["tokio"] tokio = ["dep:tokio"] diff --git a/implants/lib/transport/Cargo.toml b/implants/lib/transport/Cargo.toml index 4c5d2dd71..f0f804b3e 100644 --- a/implants/lib/transport/Cargo.toml +++ b/implants/lib/transport/Cargo.toml @@ -4,6 +4,7 @@ version = "0.0.5" edition = "2021" [features] +verbose-logging = ["pb/verbose-logging"] default = [] grpc = ["pb/grpc"] doh = ["dep:hickory-resolver"] diff --git a/implants/lib/transport/src/dns.rs b/implants/lib/transport/src/dns.rs index c2193b1bb..32e6eb00d 100644 --- a/implants/lib/transport/src/dns.rs +++ b/implants/lib/transport/src/dns.rs @@ -143,7 +143,7 @@ impl DNS { /// Send packet and get response async fn send_packet(&self, packet: ConvPacket) -> Result> { let subdomain = self.build_subdomain(&packet).map_err(|e| { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "DNS: Failed to build subdomain for packet type={}, seq={}: {}", packet.r#type, @@ -158,7 +158,7 @@ impl DNS { self.try_dns_query(&self.dns_server, &query, txid) .await .map_err(|e| { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "DNS: Query failed for packet type={}, seq={}, conv_id={}: {}", packet.r#type, @@ -403,7 +403,7 @@ impl DNS { let data_crc = conv::calculate_crc32(request_data); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "DNS: Request size={} bytes, chunks={}, chunk_size={} bytes, crc32={:#x}", request_data.len(), @@ -433,7 +433,7 @@ impl DNS { let mut init_payload_bytes = Vec::new(); init_payload.encode(&mut init_payload_bytes)?; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "DNS: INIT packet - conv_id={}, method={}, total_chunks={}, file_size={}, data_crc32={:#x}", conv_id, method_code, total_chunks, data_size, data_crc @@ -485,7 +485,7 @@ impl DNS { } } } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "DNS: Unknown response format ({} bytes), retrying chunk", response_data.len() @@ -589,7 +589,7 @@ impl DNS { } (seq_num, Err(e)) => { let err_msg = e.to_string(); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to send chunk {}: {}", seq_num, err_msg); // If packet is too long, this is a fatal error @@ -635,7 +635,7 @@ impl DNS { } *retries += 1; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "DNS: Retrying chunk {} (attempt {}/{}) for conv_id={}", nack_seq, @@ -682,7 +682,7 @@ impl DNS { } } Err(e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "DNS: Retry failed for chunk {} in conv_id={}: {}", nack_seq, @@ -702,7 +702,7 @@ impl DNS { /// Send COMPLETE packet to server to confirm successful receipt and cleanup conversation async fn send_complete_packet(&mut self, conv_id: &str) -> Result<()> { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("DNS: Sending COMPLETE packet for conv_id={}", conv_id); let complete_packet = ConvPacket { @@ -724,7 +724,7 @@ impl DNS { /// Fetch response from server, handling potentially chunked responses async fn fetch_response(&mut self, conv_id: &str, total_chunks: usize) -> Result> { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "DNS: All {} chunks acknowledged, sending FETCH", total_chunks @@ -747,7 +747,7 @@ impl DNS { ) })?; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "DNS: FETCH response received ({} bytes)", end_response.len() @@ -784,7 +784,7 @@ impl DNS { let expected_crc = metadata.data_crc32; let mut full_response = Vec::new(); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "DNS: Fetching chunked response - {} chunks, expected_crc={:#x}, conv_id={}", total_chunks, @@ -984,7 +984,7 @@ impl Transport for DNS { record_type, }; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!( "DNS transport initialized - server={}, domain={}, record_type={:?}", dns_server, diff --git a/implants/lib/transport/src/grpc.rs b/implants/lib/transport/src/grpc.rs index 69a127398..acc96963c 100644 --- a/implants/lib/transport/src/grpc.rs +++ b/implants/lib/transport/src/grpc.rs @@ -226,7 +226,7 @@ impl Transport for GRPC { request: FetchAssetRequest, tx: Sender, ) -> Result<()> { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] let filename = request.name.clone(); let resp = self.fetch_asset_impl(request).await?; let mut stream = resp.into_inner(); @@ -241,7 +241,7 @@ impl Transport for GRPC { } }, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to download file: {}: {}", filename, _err); return; @@ -250,7 +250,7 @@ impl Transport for GRPC { match tx.send(msg) { Ok(_) => {} Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "failed to send downloaded file chunk: {}: {}", filename, @@ -316,7 +316,7 @@ impl Transport for GRPC { while let Some(msg) = match resp_stream.message().await { Ok(m) => m, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to receive gRPC stream response: {}", _err); None @@ -325,7 +325,7 @@ impl Transport for GRPC { match tx.send(msg).await { Ok(_) => {} Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to queue pty input: {}", _err); return; @@ -354,7 +354,7 @@ impl Transport for GRPC { while let Some(msg) = match resp_stream.message().await { Ok(m) => m, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to receive gRPC stream response: {}", _err); None @@ -363,7 +363,7 @@ impl Transport for GRPC { match tx.send(msg).await { Ok(_) => {} Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to queue portal input: {}", _err); return; @@ -428,13 +428,13 @@ impl Transport for GRPC { while let Some(msg) = match resp_stream.message().await { Ok(m) => m, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to receive gRPC stream response: {}", _err); None } } { if tx.send(msg).await.is_err() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("failed to queue remote input"); return; } diff --git a/implants/lib/transport/src/http.rs b/implants/lib/transport/src/http.rs index 3e1989248..74e0fa996 100644 --- a/implants/lib/transport/src/http.rs +++ b/implants/lib/transport/src/http.rs @@ -212,7 +212,7 @@ impl HTTP { let request_bytes = match marshal_with_codec::(msg) { Ok(bytes) => bytes, Err(err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to marshal streaming message: {}", err); continue; } @@ -238,13 +238,13 @@ impl HTTP { { Ok(Ok(resp)) => resp, Ok(Err(err)) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to send short poll HTTP request: {}", err); tokio::time::sleep(std::time::Duration::from_secs(1)).await; continue; } Err(_) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Short poll HTTP request timed out after 30s"); tokio::time::sleep(std::time::Duration::from_secs(1)).await; continue; @@ -258,7 +258,7 @@ impl HTTP { let mut data_received = false; let result: Result<()> = match body_bytes { Ok(bytes) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] if !bytes.is_empty() { log::debug!("Received short poll response body: {} bytes", bytes.len()); } @@ -270,7 +270,7 @@ impl HTTP { { frame_count += 1; data_received = true; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "Extracted frame {} from short poll response ({} bytes)", frame_count, @@ -279,7 +279,7 @@ impl HTTP { match unmarshal_with_codec::(&encrypted_message) { Ok(response_msg) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Unmarshaled message {} from short poll response, sending to channel", frame_count); if let Err(err) = tx.send(response_msg).await { @@ -305,7 +305,7 @@ impl HTTP { }; if let Err(err) = result { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to process response frames: {}", err); break; } @@ -408,7 +408,7 @@ impl HTTP { while let Some((_header, encrypted_message)) = grpc_frame::FrameHeader::extract_frame(&mut buffer) { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!( "Received complete encrypted message: compression={}, {} bytes", _header.compression_flag, @@ -425,7 +425,7 @@ impl HTTP { // Read more data from HTTP body match body.data().await { Some(Ok(chunk)) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Received HTTP chunk: {} bytes", chunk.len()); buffer.extend_from_slice(&chunk); @@ -445,14 +445,14 @@ impl HTTP { // Check if there's leftover data in the buffer if !buffer.is_empty() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::warn!( "Incomplete data remaining in buffer: {} bytes", buffer.len() ); } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Completed streaming messages"); Ok(()) @@ -472,7 +472,7 @@ impl HTTP { let request_bytes = match marshal_with_codec::(req_chunk) { Ok(bytes) => bytes, Err(_err) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to marshal chunk: {}", _err); return; } @@ -489,7 +489,7 @@ impl HTTP { .await .is_err() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to send frame header for chunk"); return; } @@ -500,13 +500,13 @@ impl HTTP { .await .is_err() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("Failed to send chunk"); return; } } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("Completed sending chunks"); }); @@ -612,7 +612,7 @@ impl Transport for HTTP { request: FetchAssetRequest, tx: Sender, ) -> Result<()> { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] let filename = request.name.clone(); // Marshal and encrypt the request @@ -632,7 +632,7 @@ impl Transport for HTTP { response, |response_msg| { tx.send(response_msg).map_err(|_err| { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!( "Failed to send downloaded file chunk: {}: {}", filename, @@ -705,7 +705,7 @@ impl Transport for HTTP { .handle_short_poll_streaming(rx, tx, REVERSE_SHELL_PATH) .await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("reverse_shell short poll streaming ended: {}", _err); } }); @@ -725,7 +725,7 @@ impl Transport for HTTP { .handle_short_poll_streaming(rx, tx, CREATE_PORTAL_PATH) .await { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("create_portal short poll streaming ended: {}", _err); } }); diff --git a/implants/lib/transport/src/tcp_bind.rs b/implants/lib/transport/src/tcp_bind.rs index 0432bd7e9..d0348ae35 100644 --- a/implants/lib/transport/src/tcp_bind.rs +++ b/implants/lib/transport/src/tcp_bind.rs @@ -59,7 +59,7 @@ impl Transport for TcpBindTransport { .map(|t| t.uri.clone()) .ok_or_else(|| anyhow!("No transports configured"))?; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("[tcp-bind] new() with uri: {}", uri); // Expect URI to look like tcp://0.0.0.0:8443 @@ -75,13 +75,13 @@ impl Transport for TcpBindTransport { )); }; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("[tcp-bind] bind address: {}", addr); // If we already have a cached channel for this addr, reuse it. if let Some((cached_addr, _stream, cached_grpc)) = TCP_BIND_CACHE.get() { if cached_addr == &addr { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("[tcp-bind] reusing cached gRPC channel for {}", addr); return Ok(Self { grpc: Some(cached_grpc.clone()), @@ -96,7 +96,7 @@ impl Transport for TcpBindTransport { } // First call: bind the listener using synchronous std API (safe to call outside async context). - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!( "[tcp-bind] binding TCP listener at {} — waiting for Agent A to connect", addr @@ -112,24 +112,24 @@ impl Transport for TcpBindTransport { let channel = endpoint.connect_with_connector_lazy(tower::service_fn( move |uri: tonic::transport::Uri| { let stream_clone = stream_for_connector.clone(); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("[tcp-bind] connector called for uri: {}", uri); async move { use tokio_stream::StreamExt; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("[tcp-bind] connector: waiting for next TCP connection..."); let mut guard = stream_clone.lock().await; if let Some(conn) = guard.next().await { match conn { Ok(c) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!( "[tcp-bind] connector: accepted connection from Agent A" ); Ok(hyper_util::rt::TokioIo::new(c)) } Err(e) => { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("[tcp-bind] connector: accept error: {}", e); Err(std::io::Error::new( std::io::ErrorKind::Other, @@ -138,7 +138,7 @@ impl Transport for TcpBindTransport { } } } else { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("[tcp-bind] connector: TCP listener stream closed"); Err(std::io::Error::new( std::io::ErrorKind::BrokenPipe, @@ -150,7 +150,7 @@ impl Transport for TcpBindTransport { )); let grpc = tonic::client::Grpc::new(channel); - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::info!("[tcp-bind] gRPC channel created, transport ready"); // Cache the stream + channel for future cycles. @@ -160,7 +160,7 @@ impl Transport for TcpBindTransport { } async fn claim_tasks(&mut self, request: ClaimTasksRequest) -> Result { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("[tcp-bind] claim_tasks()"); let resp = self.claim_tasks_impl(request).await?; Ok(resp.into_inner()) @@ -217,7 +217,7 @@ impl Transport for TcpBindTransport { &mut self, request: ReportOutputRequest, ) -> Result { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("[tcp-bind] report_output()"); let resp = self.report_output_impl(request).await?; Ok(resp.into_inner()) @@ -300,24 +300,24 @@ impl Transport for TcpBindTransport { impl TcpBindTransport { async fn check_ready(&mut self) -> Result<(), tonic::Status> { if self.grpc.is_none() { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("[tcp-bind] check_ready: grpc client is None"); return Err(tonic::Status::new( tonic::Code::FailedPrecondition, "grpc client not created".to_string(), )); } - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("[tcp-bind] check_ready: waiting for gRPC channel to be ready..."); self.grpc.as_mut().unwrap().ready().await.map_err(|e| { - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::error!("[tcp-bind] check_ready: channel not ready: {}", e); tonic::Status::new( tonic::Code::Unknown, format!("Service was not ready: {}", e), ) })?; - #[cfg(debug_assertions)] + #[cfg(feature = "verbose-logging")] log::debug!("[tcp-bind] check_ready: channel ready"); Ok(()) }