Added Windows support for the bind shell
Brings in support from winpcap as npcap has a restrictive license
This commit is contained in:
parent
862dc3e743
commit
af5ceb66ab
32
flake.nix
32
flake.nix
@ -62,12 +62,13 @@
|
|||||||
|
|
||||||
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
|
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
|
||||||
|
|
||||||
src = craneLib.path ./.;
|
src = craneLib.cleanCargoSource (craneLib.path ./.);
|
||||||
|
windowsSrc = craneLib.path ./.;
|
||||||
|
|
||||||
commonArgs = {
|
commonArgs = {
|
||||||
inherit src;
|
inherit src;
|
||||||
|
|
||||||
strictDeps = true;
|
strictDeps = false;
|
||||||
|
|
||||||
CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
|
CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
|
||||||
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
||||||
@ -82,8 +83,12 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
commonWindowsArgs = commonArgs // {
|
commonWindowsArgs = commonArgs // {
|
||||||
|
src = windowsSrc;
|
||||||
|
|
||||||
CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu";
|
CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu";
|
||||||
|
|
||||||
|
SPARSE_BUILD_WINPCAP = "${winpcap}/Lib";
|
||||||
|
|
||||||
nativeBuildInputs = windowsBuildTools;
|
nativeBuildInputs = windowsBuildTools;
|
||||||
buildInputs = windowsBuildTools;
|
buildInputs = windowsBuildTools;
|
||||||
};
|
};
|
||||||
@ -94,17 +99,29 @@
|
|||||||
sparse-05-linux-server = craneLib.buildPackage (commonArgs // {
|
sparse-05-linux-server = craneLib.buildPackage (commonArgs // {
|
||||||
inherit artifacts;
|
inherit artifacts;
|
||||||
|
|
||||||
pname = "sparse-05-server";
|
pname = "sparse-05-linux-server";
|
||||||
cargoExtraArgs = "-p sparse-05-server --locked";
|
cargoExtraArgs = "-p sparse-05-server --locked";
|
||||||
});
|
});
|
||||||
|
|
||||||
sparse-05-windows-server = craneLib.buildPackage (commonWindowsArgs // {
|
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";
|
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 // {
|
sparse-c2-linux-beacon = craneLib.buildPackage (commonArgs // {
|
||||||
inherit artifacts;
|
inherit artifacts;
|
||||||
|
|
||||||
@ -117,15 +134,18 @@
|
|||||||
|
|
||||||
buildInputs = windowsBuildTools ++ [ rust-analyzer ];
|
buildInputs = windowsBuildTools ++ [ rust-analyzer ];
|
||||||
|
|
||||||
|
SPARSE_BUILD_WINPCAP = "${winpcap}/Lib";
|
||||||
SPARSE_BUILD_LIBPCAP = "${libpcap-src}";
|
SPARSE_BUILD_LIBPCAP = "${libpcap-src}";
|
||||||
SPARSE_BUILD_LIBNL = "${libnl}";
|
SPARSE_BUILD_LIBNL = "${libnl}";
|
||||||
};
|
};
|
||||||
|
|
||||||
packages = {
|
packages = {
|
||||||
inherit sparse-05-linux-server sparse-05-windows-server;
|
inherit sparse-05-linux-server sparse-05-windows-server;
|
||||||
|
inherit sparse-05-client;
|
||||||
|
|
||||||
inherit sparse-c2-linux-beacon;
|
inherit sparse-c2-linux-beacon;
|
||||||
|
|
||||||
default = sparse-c2-linux-beacon;
|
default = sparse-05-client;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
let mut options = CopyOptions::new();
|
let mut options = CopyOptions::new();
|
||||||
options.copy_inside = true;
|
options.copy_inside = true;
|
||||||
options.skip_exist = 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();
|
let dst = autotools::Config::new(libnl_src).reconf("-vi").build();
|
||||||
|
|
||||||
|
|||||||
@ -17,14 +17,16 @@ use fs_extra::dir::{copy, CopyOptions};
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" {
|
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 {
|
} else {
|
||||||
let libpcap_src = format!("{}/pcap_src", std::env::var("OUT_DIR").unwrap());
|
let libpcap_src = format!("{}/pcap_src", std::env::var("OUT_DIR").unwrap());
|
||||||
|
|
||||||
let mut options = CopyOptions::new();
|
let mut options = CopyOptions::new();
|
||||||
options.copy_inside = true;
|
options.copy_inside = true;
|
||||||
options.skip_exist = 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)
|
let dst = cmake::Config::new(&libpcap_src)
|
||||||
.define("BUILD_SHARED_LIBS", "OFF")
|
.define("BUILD_SHARED_LIBS", "OFF")
|
||||||
|
|||||||
@ -228,7 +228,7 @@ impl<T: Disabled> Interface<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn activate(mut self) -> error::Result<Interface<DevActivated>> {
|
pub fn activate(mut self) -> error::Result<Interface<DevActivated>> {
|
||||||
if unsafe { ffi::pcap_activate(self.dev) } != 0 {
|
if unsafe { dbg!(ffi::pcap_activate(self.dev)) } != 0 {
|
||||||
Err(unsafe { ffi::pcap_geterr(self.dev) })?;
|
Err(unsafe { ffi::pcap_geterr(self.dev) })?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ serde = { version = "1.0.188", features = ["derive"] }
|
|||||||
sparse-05-common = { version = "0.1.0", path = "../sparse-05-common" }
|
sparse-05-common = { version = "0.1.0", path = "../sparse-05-common" }
|
||||||
structopt = { version = "0.3.26", features = ["paw"] }
|
structopt = { version = "0.3.26", features = ["paw"] }
|
||||||
tempfile = "3.8.0"
|
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]
|
[target.'cfg(unix)'.dependencies]
|
||||||
raw_tty = "0.1.0"
|
raw_tty = "0.1.0"
|
||||||
|
|||||||
@ -11,13 +11,13 @@ pub const SPARSE_LINUX_SERVER_BINARY: &'static [u8] =
|
|||||||
include_bytes!("../../../../target/debug/sparse-05-server");
|
include_bytes!("../../../../target/debug/sparse-05-server");
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
pub const SPARSE_LINUX_SERVER_BINARY: &'static [u8] =
|
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)]
|
#[cfg(debug_assertions)]
|
||||||
pub const SPARSE_WINDOWS_SERVER_BINARY: &'static [u8] =
|
pub const SPARSE_WINDOWS_SERVER_BINARY: &'static [u8] =
|
||||||
include_bytes!("../../../../target/x86_64-pc-windows-gnu/debug/sparse-05-server.exe");
|
include_bytes!("../../../../target/x86_64-pc-windows-gnu/debug/sparse-05-server.exe");
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
pub const SPARSE_WINDOWS_SERVER_BINARY: &'static [u8] =
|
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<()> {
|
pub async fn generate(mut name: PathBuf, port: u16, target: TargetOs) -> anyhow::Result<()> {
|
||||||
let mut csprng = rand::thread_rng();
|
let mut csprng = rand::thread_rng();
|
||||||
|
|||||||
1
sparse-05/sparse-05-server/os
Normal file
1
sparse-05/sparse-05-server/os
Normal file
@ -0,0 +1 @@
|
|||||||
|
windows
|
||||||
@ -4,6 +4,7 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use sparse_05_common::messages::{Capabilities, OperatingSystem, TransportType};
|
use sparse_05_common::messages::{Capabilities, OperatingSystem, TransportType};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SrvCapabilities {
|
pub struct SrvCapabilities {
|
||||||
pub operating_system: OperatingSystem,
|
pub operating_system: OperatingSystem,
|
||||||
pub docker_container: bool,
|
pub docker_container: bool,
|
||||||
@ -140,8 +141,12 @@ fn get_current_capabilities() -> anyhow::Result<SrvCapabilities> {
|
|||||||
docker_breakout: false,
|
docker_breakout: false,
|
||||||
setuid: false,
|
setuid: false,
|
||||||
root: userent.as_deref() == Some("Administrator"),
|
root: userent.as_deref() == Some("Administrator"),
|
||||||
userent,
|
userent: userent.clone(),
|
||||||
transport: TransportType::Udp,
|
transport: TransportType::RawUdp, /*if userent.as_deref() == Some("Administrator") {
|
||||||
|
TransportType::RawUdp
|
||||||
|
} else {
|
||||||
|
TransportType::Udp
|
||||||
|
},*/
|
||||||
hostname: None,
|
hostname: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,10 +19,24 @@ impl Interface {
|
|||||||
match ttype {
|
match ttype {
|
||||||
#[cfg(feature = "pcap")]
|
#[cfg(feature = "pcap")]
|
||||||
TransportType::RawUdp => {
|
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 mut interfaces = pcap_sys::PcapDevIterator::new()?;
|
||||||
let interface_name = interfaces
|
|
||||||
.find(|eth| eth.starts_with("eth") || eth.starts_with("en"))
|
let interface_name = if cfg!(windows) {
|
||||||
.ok_or(anyhow!("could not get an ethernet interface"))?;
|
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 {
|
let interface = loop {
|
||||||
thread::sleep(std::time::Duration::from_millis(250));
|
thread::sleep(std::time::Duration::from_millis(250));
|
||||||
@ -47,14 +61,24 @@ impl Interface {
|
|||||||
&interface_name
|
&interface_name
|
||||||
));
|
));
|
||||||
|
|
||||||
retry!(interface.set_buffer_size(8192));
|
retry!(interface.set_buffer_size(1024));
|
||||||
retry!(interface.set_non_blocking(false));
|
retry!(interface.set_non_blocking(false));
|
||||||
retry!(interface.set_promisc(false));
|
retry!(interface.set_promisc(false));
|
||||||
retry!(interface.set_timeout(10));
|
retry!(interface.set_timeout(10));
|
||||||
|
|
||||||
|
log::debug!("Configured raw listener interface");
|
||||||
|
|
||||||
let interface = retry!(interface.activate());
|
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 {
|
if interface.datalink() != pcap_sys::consts::DLT_EN10MB {
|
||||||
bail!("interface does not properly support ethernet");
|
bail!("interface does not properly support ethernet");
|
||||||
@ -79,11 +103,11 @@ impl Interface {
|
|||||||
pub fn split(self) -> anyhow::Result<(InterfaceSender, InterfaceReceiver)> {
|
pub fn split(self) -> anyhow::Result<(InterfaceSender, InterfaceReceiver)> {
|
||||||
match self {
|
match self {
|
||||||
#[cfg(feature = "pcap")]
|
#[cfg(feature = "pcap")]
|
||||||
Self::RawUdp(interface, _) => {
|
Self::RawUdp(interface, port) => {
|
||||||
let arc = Arc::new(interface);
|
let arc = Arc::new(interface);
|
||||||
Ok((
|
Ok((
|
||||||
InterfaceSender::RawUdp(Arc::clone(&arc)),
|
InterfaceSender::RawUdp(Arc::clone(&arc)),
|
||||||
InterfaceReceiver::RawUdp(arc),
|
InterfaceReceiver::RawUdp(arc, port),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Self::Udp(interface, port) => {
|
Self::Udp(interface, port) => {
|
||||||
@ -129,7 +153,7 @@ impl InterfaceSender {
|
|||||||
|
|
||||||
pub enum InterfaceReceiver {
|
pub enum InterfaceReceiver {
|
||||||
#[cfg(feature = "pcap")]
|
#[cfg(feature = "pcap")]
|
||||||
RawUdp(Arc<pcap_sys::Interface<pcap_sys::DevActivated>>),
|
RawUdp(Arc<pcap_sys::Interface<pcap_sys::DevActivated>>, u16),
|
||||||
Udp(UdpSocket, u16),
|
Udp(UdpSocket, u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,8 +164,19 @@ impl InterfaceReceiver {
|
|||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
#[cfg(feature = "pcap")]
|
#[cfg(feature = "pcap")]
|
||||||
Self::RawUdp(interf) => interf.listen(
|
Self::RawUdp(interf, port) => interf.listen(
|
||||||
move |_, packet| {
|
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());
|
let _ = (f)(packet.to_owned());
|
||||||
Ok(false)
|
Ok(false)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -20,12 +20,18 @@ mod interface;
|
|||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
simple_logger::SimpleLogger::new()
|
simple_logger::SimpleLogger::new()
|
||||||
.with_level(log::LevelFilter::Off)
|
.with_level(log::LevelFilter::Debug)
|
||||||
.with_module_level("sparse-05-server", log::LevelFilter::Info)
|
.with_module_level("sparse-05-server", log::LevelFilter::Debug)
|
||||||
.init()?;
|
.init()?;
|
||||||
|
|
||||||
|
log::debug!("Debug logging enabled");
|
||||||
|
log::info!("Informational logging enabled");
|
||||||
|
log::warn!("Warning logging enabled");
|
||||||
|
|
||||||
let capabilities = Arc::new(capabilities::get_capabilities()?);
|
let capabilities = Arc::new(capabilities::get_capabilities()?);
|
||||||
|
|
||||||
|
log::debug!("Capabilities: {:?}", capabilities);
|
||||||
|
|
||||||
let config_bytes = catconf::read_from_exe(CONFIG_SEPARATOR, 512)?;
|
let config_bytes = catconf::read_from_exe(CONFIG_SEPARATOR, 512)?;
|
||||||
if config_bytes.len() != 66 {
|
if config_bytes.len() != 66 {
|
||||||
bail!("could not load configuration");
|
bail!("could not load configuration");
|
||||||
@ -74,6 +80,8 @@ fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let pkt = pkt.pkt();
|
let pkt = pkt.pkt();
|
||||||
|
|
||||||
|
log::debug!("Received packet!");
|
||||||
|
|
||||||
let Layer3Pkt::IPv4Pkt(ip_pkt) = pkt.get_layer3_pkt()? else {
|
let Layer3Pkt::IPv4Pkt(ip_pkt) = pkt.get_layer3_pkt()? else {
|
||||||
todo!()
|
todo!()
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user