diff --git a/flake.nix b/flake.nix index 6416ba5..f10c683 100644 --- a/flake.nix +++ b/flake.nix @@ -62,12 +62,13 @@ craneLib = (crane.mkLib pkgs).overrideToolchain toolchain; - src = craneLib.path ./.; + src = craneLib.cleanCargoSource (craneLib.path ./.); + windowsSrc = craneLib.path ./.; commonArgs = { inherit src; - strictDeps = true; + strictDeps = false; CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static"; CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl"; @@ -82,8 +83,12 @@ }; commonWindowsArgs = commonArgs // { + src = windowsSrc; + CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu"; + SPARSE_BUILD_WINPCAP = "${winpcap}/Lib"; + nativeBuildInputs = windowsBuildTools; buildInputs = windowsBuildTools; }; @@ -94,17 +99,29 @@ sparse-05-linux-server = craneLib.buildPackage (commonArgs // { inherit artifacts; - pname = "sparse-05-server"; + pname = "sparse-05-linux-server"; cargoExtraArgs = "-p sparse-05-server --locked"; }); sparse-05-windows-server = craneLib.buildPackage (commonWindowsArgs // { - inherit windowsArtifacts; + artifacts = windowsArtifacts; - pname = "sparse-05-server"; + pname = "sparse-05-windows-server"; cargoExtraArgs = "-p sparse-05-server --locked"; }); + sparse-05-client = craneLib.buildPackage (commonArgs // { + inherit artifacts; + + SPARSE_WINDOWS_SERVER = + "${sparse-05-windows-server}/bin/sparse-05-server.exe"; + SPARSE_LINUX_SERVER = + "${sparse-05-linux-server}/bin/sparse-05-server"; + + pname = "sparse-05-client"; + cargoExtraArgs = "-p sparse-05-client --locked"; + }); + sparse-c2-linux-beacon = craneLib.buildPackage (commonArgs // { inherit artifacts; @@ -117,15 +134,18 @@ buildInputs = windowsBuildTools ++ [ rust-analyzer ]; + SPARSE_BUILD_WINPCAP = "${winpcap}/Lib"; SPARSE_BUILD_LIBPCAP = "${libpcap-src}"; SPARSE_BUILD_LIBNL = "${libnl}"; }; packages = { inherit sparse-05-linux-server sparse-05-windows-server; + inherit sparse-05-client; + inherit sparse-c2-linux-beacon; - default = sparse-c2-linux-beacon; + default = sparse-05-client; }; }); } diff --git a/nl-sys/build.rs b/nl-sys/build.rs index c682f07..6c698e6 100644 --- a/nl-sys/build.rs +++ b/nl-sys/build.rs @@ -23,7 +23,7 @@ fn main() -> std::io::Result<()> { let mut options = CopyOptions::new(); options.copy_inside = true; options.skip_exist = true; - copy(std::env!("SPARSE_BUILD_LIBNL"), &libnl_src, &options).expect("could not copy nl"); + copy(std::env::var("SPARSE_BUILD_LIBNL").unwrap(), &libnl_src, &options).expect("could not copy nl"); let dst = autotools::Config::new(libnl_src).reconf("-vi").build(); diff --git a/pcap-sys/build.rs b/pcap-sys/build.rs index a01b364..d7bc2da 100644 --- a/pcap-sys/build.rs +++ b/pcap-sys/build.rs @@ -17,14 +17,16 @@ use fs_extra::dir::{copy, CopyOptions}; fn main() { if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" { - println!("cargo:rustc-lib-lib=pcap"); + println!("cargo:rustc-link-search=native={}", std::env::var("SPARSE_BUILD_WINPCAP").unwrap()); + println!("cargo:rustc-link-search=native={}/x64", std::env::var("SPARSE_BUILD_WINPCAP").unwrap()); + println!("cargo:rustc-link-lib=wpcap"); } else { let libpcap_src = format!("{}/pcap_src", std::env::var("OUT_DIR").unwrap()); let mut options = CopyOptions::new(); options.copy_inside = true; options.skip_exist = true; - copy(std::env!("SPARSE_BUILD_LIBPCAP"), &libpcap_src, &options).expect("could not copy libpcap source code to build"); + copy(std::env::var("SPARSE_BUILD_LIBPCAP").unwrap(), &libpcap_src, &options).expect("could not copy libpcap source code to build"); let dst = cmake::Config::new(&libpcap_src) .define("BUILD_SHARED_LIBS", "OFF") diff --git a/pcap-sys/src/lib.rs b/pcap-sys/src/lib.rs index c41403e..10a9cdc 100644 --- a/pcap-sys/src/lib.rs +++ b/pcap-sys/src/lib.rs @@ -228,7 +228,7 @@ impl Interface { } pub fn activate(mut self) -> error::Result> { - if unsafe { ffi::pcap_activate(self.dev) } != 0 { + if unsafe { dbg!(ffi::pcap_activate(self.dev)) } != 0 { Err(unsafe { ffi::pcap_geterr(self.dev) })?; } diff --git a/sparse-05/sparse-05-client/Cargo.toml b/sparse-05/sparse-05-client/Cargo.toml index 2338b36..d0071c4 100644 --- a/sparse-05/sparse-05-client/Cargo.toml +++ b/sparse-05/sparse-05-client/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0.188", features = ["derive"] } sparse-05-common = { version = "0.1.0", path = "../sparse-05-common" } structopt = { version = "0.3.26", features = ["paw"] } tempfile = "3.8.0" -tokio = { version = "1.32.0", features = ["io-std", "net", "fs", "macros", "rt"] } +tokio = { version = "1.32.0", features = ["full"] } [target.'cfg(unix)'.dependencies] raw_tty = "0.1.0" diff --git a/sparse-05/sparse-05-client/src/commands/generate.rs b/sparse-05/sparse-05-client/src/commands/generate.rs index 30217c4..83422bc 100644 --- a/sparse-05/sparse-05-client/src/commands/generate.rs +++ b/sparse-05/sparse-05-client/src/commands/generate.rs @@ -11,13 +11,13 @@ pub const SPARSE_LINUX_SERVER_BINARY: &'static [u8] = include_bytes!("../../../../target/debug/sparse-05-server"); #[cfg(not(debug_assertions))] pub const SPARSE_LINUX_SERVER_BINARY: &'static [u8] = - include_bytes!("../../../../target/release/sparse-05-server"); + include_bytes!(std::env!("SPARSE_LINUX_SERVER")); #[cfg(debug_assertions)] pub const SPARSE_WINDOWS_SERVER_BINARY: &'static [u8] = include_bytes!("../../../../target/x86_64-pc-windows-gnu/debug/sparse-05-server.exe"); #[cfg(not(debug_assertions))] pub const SPARSE_WINDOWS_SERVER_BINARY: &'static [u8] = - include_bytes!("../../../../target/x86_64-pc-windows-gnu/release/sparse-05-server.exe"); + include_bytes!(std::env!("SPARSE_WINDOWS_SERVER")); pub async fn generate(mut name: PathBuf, port: u16, target: TargetOs) -> anyhow::Result<()> { let mut csprng = rand::thread_rng(); diff --git a/sparse-05/sparse-05-server/os b/sparse-05/sparse-05-server/os new file mode 100644 index 0000000..8e1a559 --- /dev/null +++ b/sparse-05/sparse-05-server/os @@ -0,0 +1 @@ +windows diff --git a/sparse-05/sparse-05-server/src/capabilities.rs b/sparse-05/sparse-05-server/src/capabilities.rs index 9793c75..0b08b42 100644 --- a/sparse-05/sparse-05-server/src/capabilities.rs +++ b/sparse-05/sparse-05-server/src/capabilities.rs @@ -4,6 +4,7 @@ use std::path::PathBuf; use sparse_05_common::messages::{Capabilities, OperatingSystem, TransportType}; +#[derive(Debug)] pub struct SrvCapabilities { pub operating_system: OperatingSystem, pub docker_container: bool, @@ -140,8 +141,12 @@ fn get_current_capabilities() -> anyhow::Result { docker_breakout: false, setuid: false, root: userent.as_deref() == Some("Administrator"), - userent, - transport: TransportType::Udp, + userent: userent.clone(), + transport: TransportType::RawUdp, /*if userent.as_deref() == Some("Administrator") { + TransportType::RawUdp + } else { + TransportType::Udp + },*/ hostname: None, }) } diff --git a/sparse-05/sparse-05-server/src/interface.rs b/sparse-05/sparse-05-server/src/interface.rs index e50d808..a96dd20 100644 --- a/sparse-05/sparse-05-server/src/interface.rs +++ b/sparse-05/sparse-05-server/src/interface.rs @@ -19,10 +19,24 @@ impl Interface { match ttype { #[cfg(feature = "pcap")] TransportType::RawUdp => { + if cfg!(target_os = "windows") { + let interfaces = pcap_sys::PcapDevIterator::new()?; + for interface in interfaces { + log::debug!("Found interface: {}", interface); + } + } + let mut interfaces = pcap_sys::PcapDevIterator::new()?; - let interface_name = interfaces - .find(|eth| eth.starts_with("eth") || eth.starts_with("en")) - .ok_or(anyhow!("could not get an ethernet interface"))?; + + let interface_name = if cfg!(windows) { + interfaces + .next() + .ok_or(anyhow!("could not get an ethernet interface"))? + } else { + interfaces + .find(|eth| eth.starts_with("eth") || eth.starts_with("en")) + .ok_or(anyhow!("could not get an ethernet interface"))? + }; let interface = loop { thread::sleep(std::time::Duration::from_millis(250)); @@ -47,14 +61,24 @@ impl Interface { &interface_name )); - retry!(interface.set_buffer_size(8192)); + retry!(interface.set_buffer_size(1024)); retry!(interface.set_non_blocking(false)); retry!(interface.set_promisc(false)); retry!(interface.set_timeout(10)); + log::debug!("Configured raw listener interface"); + let interface = retry!(interface.activate()); - retry!(interface.set_filter(&format!("inbound and port {port}"), true, None)); + log::debug!("Activated raw listener interface"); + + if cfg!(windows) { + retry!(interface.set_filter(&format!("udp port {port}"), true, None)); + } else { + retry!(interface.set_filter(&format!("inbound and udp port {port}"), true, None)); + } + + log::debug!("Updated filter for listener interface"); if interface.datalink() != pcap_sys::consts::DLT_EN10MB { bail!("interface does not properly support ethernet"); @@ -79,11 +103,11 @@ impl Interface { pub fn split(self) -> anyhow::Result<(InterfaceSender, InterfaceReceiver)> { match self { #[cfg(feature = "pcap")] - Self::RawUdp(interface, _) => { + Self::RawUdp(interface, port) => { let arc = Arc::new(interface); Ok(( InterfaceSender::RawUdp(Arc::clone(&arc)), - InterfaceReceiver::RawUdp(arc), + InterfaceReceiver::RawUdp(arc, port), )) } Self::Udp(interface, port) => { @@ -129,7 +153,7 @@ impl InterfaceSender { pub enum InterfaceReceiver { #[cfg(feature = "pcap")] - RawUdp(Arc>), + RawUdp(Arc>, u16), Udp(UdpSocket, u16), } @@ -140,8 +164,19 @@ impl InterfaceReceiver { { match self { #[cfg(feature = "pcap")] - Self::RawUdp(interf) => interf.listen( + Self::RawUdp(interf, port) => interf.listen( move |_, packet| { + use packets::*; + let Ok(Layer3Pkt::IPv4Pkt(ip_pkt)) = packet.get_layer3_pkt() else { + return Ok(false); + }; + let Ok(Layer4Pkt::UDP(udp_pkt)) = ip_pkt.get_layer4_packet() else { + return Ok(false); + }; + log::debug!("Received packet bound for {}!", udp_pkt.dstport()); + if udp_pkt.dstport() != *port { + return Ok(false); + } let _ = (f)(packet.to_owned()); Ok(false) }, diff --git a/sparse-05/sparse-05-server/src/main.rs b/sparse-05/sparse-05-server/src/main.rs index 46f59df..a0df0b6 100644 --- a/sparse-05/sparse-05-server/src/main.rs +++ b/sparse-05/sparse-05-server/src/main.rs @@ -20,12 +20,18 @@ mod interface; fn main() -> anyhow::Result<()> { simple_logger::SimpleLogger::new() - .with_level(log::LevelFilter::Off) - .with_module_level("sparse-05-server", log::LevelFilter::Info) + .with_level(log::LevelFilter::Debug) + .with_module_level("sparse-05-server", log::LevelFilter::Debug) .init()?; + log::debug!("Debug logging enabled"); + log::info!("Informational logging enabled"); + log::warn!("Warning logging enabled"); + let capabilities = Arc::new(capabilities::get_capabilities()?); + log::debug!("Capabilities: {:?}", capabilities); + let config_bytes = catconf::read_from_exe(CONFIG_SEPARATOR, 512)?; if config_bytes.len() != 66 { bail!("could not load configuration"); @@ -74,6 +80,8 @@ fn main() -> anyhow::Result<()> { let pkt = pkt.pkt(); + log::debug!("Received packet!"); + let Layer3Pkt::IPv4Pkt(ip_pkt) = pkt.get_layer3_pkt()? else { todo!() };