Networking hooks and state helpers for Cradle plugins
It is meant to be used by plugins that want to inspect connections, DNS lookups, transmitted buffers, and WinHTTP request metadata while the agent is running
- Winsock
connect,send,sendto,recv, andclosesocket - DNS lookups through
getaddrinfoandGetAddrInfoW - WinHTTP user-agent, host, request path, headers, request body, and pending reads
- Also tries to capture stack traces for captured data chunks
Because the current hook engine does not have return hooks yet, cradle-net records recv and WinHttpReadData
operations as pending reads with the destination address and requested length
instead of having the legit final bytes
use cradle_hooks::HookEngine;
use cradle_net::monitor::NetMonitor;
use cradle_plugin_api::{AgentEvent, CradleMutex, CradlePlugin, register_plugin};
use cradle_shared::CradleResult;
#[derive(Default)]
struct NetAwarePlugin {
monitor: Option<NetMonitor>,
hooked_winsock: bool,
}
impl CradlePlugin for NetAwarePlugin {
fn name(&self) -> &str {
"net-aware"
}
fn init(&mut self, engine: CradleMutex<HookEngine>) -> CradleResult {
self.monitor = Some(NetMonitor::new(engine));
Ok(())
}
fn on_event(&mut self, event: &AgentEvent) -> CradleResult {
if let AgentEvent::DllLoaded { name, .. } = event {
if name.to_lowercase().contains("ws2_32")
&& !self.hooked_winsock
&& let Some(monitor) = self.monitor.as_mut()
{
monitor.install_winsock()?;
self.hooked_winsock = true;
}
}
Ok(())
}
}
register_plugin!(NetAwarePlugin);NetMonitor::state() returns a shared NetState. You should inspect it from the plugin to decide when to return
an OK result
if let Some(monitor) = &self.monitor {
let state = monitor.state();
let state = state.lock();
for connection in state.connections.values() {
for chunk in &connection.tx_log {
if let Some(stack_trace) = &chunk.stack_trace {
// Return addresses captured from the target process
let _ = stack_trace;
}
}
}
}