Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions implants/golem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
1 change: 1 addition & 0 deletions implants/imix/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
26 changes: 13 additions & 13 deletions implants/imix/src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl ImixAgent {
}
}

#[cfg(debug_assertions)]
#[cfg(feature = "verbose-logging")]
log::info!(
"Flushing {} task outputs and {} process list reports",
outputs.len(),
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -265,15 +265,15 @@ 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}");
}
}

// 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}");
}
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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());
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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(())
Expand Down
12 changes: 6 additions & 6 deletions implants/imix/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,27 @@ 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::<crate::assets::Asset>::new());

// Iterate through all embedded files using the Asset struct from assets.rs
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
Expand All @@ -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}");
}
}
Expand Down
4 changes: 2 additions & 2 deletions implants/imix/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand All @@ -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}");
}
}
Expand Down
28 changes: 14 additions & 14 deletions implants/imix/src/portal/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
});

Expand Down Expand Up @@ -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"
Expand All @@ -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;
}
Expand All @@ -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.
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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(())
}
Expand Down
20 changes: 10 additions & 10 deletions implants/imix/src/portal/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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,
Expand All @@ -53,20 +53,20 @@ 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 {
let mut buf = [0u8; BUF_SIZE];
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()
Expand All @@ -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
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down
Loading
Loading