97 lines
3.5 KiB
Rust
97 lines
3.5 KiB
Rust
/// Standalone binary that simulates a polymorphic IPC evasion event
|
|
/// for verification testing. Connects to the running Stave IPC daemon
|
|
/// and sends a sequence of payloads that mimic a process shifting its
|
|
/// communication channels.
|
|
///
|
|
/// Usage:
|
|
/// Terminal 1: cargo run --bin environment_check && ./build.sh
|
|
/// Terminal 2: cargo run --bin simulate_evasion_telemetry
|
|
|
|
use std::io::Write;
|
|
use std::net::TcpStream;
|
|
use std::os::unix::net::UnixStream;
|
|
|
|
fn main() {
|
|
println!("=== Warlock's Stave: Evasion Telemetry Simulator ===");
|
|
println!("Simulating polymorphic IPC evasion pattern...\n");
|
|
|
|
// Stage 1: Attempt Unix socket connection (normal path)
|
|
let socket_path = "/tmp/stave_bridge_ipc.sock";
|
|
if std::path::Path::new(socket_path).exists() {
|
|
println!("[STAGE 1] Connecting via Unix socket...");
|
|
match UnixStream::connect(socket_path) {
|
|
Ok(mut stream) => {
|
|
send_test_payload(&mut stream, 0x7FFFFFFE0000, 0x202);
|
|
println!("[STAGE 1] Unix socket payload delivered.\n");
|
|
}
|
|
Err(e) => {
|
|
println!("[STAGE 1] Unix socket failed: {}. Falling back to TCP.", e);
|
|
}
|
|
}
|
|
} else {
|
|
println!("[STAGE 1] Unix socket not found. Skipping to TCP.");
|
|
}
|
|
|
|
// Stage 2: TCP fallback (containerized / evasion scenario)
|
|
println!("[STAGE 2] Connecting via TCP fallback (port 21860)...");
|
|
match TcpStream::connect("127.0.0.1:21860") {
|
|
Ok(mut stream) => {
|
|
stream
|
|
.set_nodelay(true)
|
|
.expect("Failed to set TCP_NODELAY");
|
|
|
|
let test_rips = [
|
|
0x7FFFF7A01000u64,
|
|
0x7FFFF7A01003,
|
|
0x7FFFF7A01005,
|
|
0x7FFFF7A0100A,
|
|
0x7FFFF7A0100C,
|
|
];
|
|
|
|
for (i, rip) in test_rips.iter().enumerate() {
|
|
send_test_payload(&mut stream, *rip, 0x202);
|
|
println!(
|
|
"[STAGE 2] Evasion payload {}/{} delivered (RIP: {:#018X})",
|
|
i + 1,
|
|
test_rips.len(),
|
|
rip
|
|
);
|
|
}
|
|
|
|
send_test_payload(&mut stream, 0x7FFFF7A01010, 0x246);
|
|
println!("[STAGE 2] Final payload with altered EFLAGS delivered.");
|
|
}
|
|
Err(e) => {
|
|
println!(
|
|
"[STAGE 2] TCP connection failed: {}",
|
|
e
|
|
);
|
|
println!("Is the Stave daemon running? Try: ./build.sh first.");
|
|
return;
|
|
}
|
|
}
|
|
|
|
println!("\n=== Simulation complete. ===");
|
|
println!("Check the Stave dashboard for:");
|
|
println!(" - Hex heatmap updates at the delivered RIP coordinates");
|
|
println!(" - Branch evaluation results in the telemetry output");
|
|
println!(" - Dictionary scanner hits for embedded patterns");
|
|
}
|
|
|
|
/// Constructs and sends a payload matching the WineIpcPayload layout.
|
|
/// Layout: u64 rip (8) + u32 eflags (4) + u32 buf_len (4) + u8[15] = 31 bytes
|
|
fn send_test_payload<W: Write>(
|
|
stream: &mut W,
|
|
rip: u64,
|
|
eflags: u32,
|
|
) {
|
|
let mut payload = Vec::with_capacity(31);
|
|
payload.extend_from_slice(&rip.to_le_bytes());
|
|
payload.extend_from_slice(&eflags.to_le_bytes());
|
|
payload.extend_from_slice(&5u32.to_le_bytes());
|
|
payload.extend_from_slice(&[0x48, 0x31, 0xC0, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
|
stream
|
|
.write_all(&payload)
|
|
.expect("Failed to write payload");
|
|
stream.flush().expect("Failed to flush");
|
|
} |