diff --git a/docs/_docs/user-guide/eldritch.md b/docs/_docs/user-guide/eldritch.md index dd4779872..575412af4 100644 --- a/docs/_docs/user-guide/eldritch.md +++ b/docs/_docs/user-guide/eldritch.md @@ -804,14 +804,14 @@ The sys.get_ip method returns a list of network interfaces as a dictionar { "name": "eth0", "ips": [ - "172.17.0.2" + "172.17.0.2/24" ], "mac": "02:42:ac:11:00:02" }, { "name": "lo", "ips": [ - "127.0.0.1" + "127.0.0.1/8" ], "mac": "00:00:00:00:00:00" } diff --git a/implants/lib/eldritch/Cargo.toml b/implants/lib/eldritch/Cargo.toml index 48819374c..f937f8956 100644 --- a/implants/lib/eldritch/Cargo.toml +++ b/implants/lib/eldritch/Cargo.toml @@ -35,10 +35,10 @@ notify = { workspace = true } object = { workspace = true } openssl = { workspace = true, features = ["vendored"] } pretty_env_logger = { workspace = true } -prost = { workspace = true} +prost = { workspace = true } prost-types = { workspace = true } regex = { workspace = true } -reqwest = { workspace = true , features = ["blocking", "stream"] } +reqwest = { workspace = true, features = ["blocking", "stream"] } russh = { workspace = true } russh-sftp = { workspace = true } russh-keys = { workspace = true } @@ -54,7 +54,7 @@ sysinfo = { workspace = true } tar = { workspace = true } tempfile = { workspace = true } tera = { workspace = true } -tokio = { workspace = true , features = ["macros", "rt-multi-thread"] } +tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } tokio-stream = { workspace = true } tonic = { workspace = true, features = ["tls-roots"] } windows-sys = { workspace = true, features = [ @@ -65,12 +65,13 @@ windows-sys = { workspace = true, features = [ "Win32_System_Diagnostics_Debug", "Win32_Security", "Win32_System_SystemInformation", - "Win32_System_SystemServices" -]} + "Win32_System_SystemServices", +] } whoami = { workspace = true } +network-interface = { workspace = true } + [target.'cfg(windows)'.dependencies] -network-interface = { workspace = true } winreg = { workspace = true } [target.'cfg(not(windows))'.dependencies] @@ -80,11 +81,11 @@ pnet = { workspace = true } netstat2 = { workspace = true } [dev-dependencies] -transport = { workspace = true, features = ["mock"]} +transport = { workspace = true, features = ["mock"] } httptest = { workspace = true } uuid = { workspace = true, features = ["v4"] } [build-dependencies] tonic-build = { workspace = true } anyhow = { workspace = true } -which = { workspace = true } +which = { workspace = true } diff --git a/implants/lib/eldritch/src/sys/get_ip_impl.rs b/implants/lib/eldritch/src/sys/get_ip_impl.rs index 11ce17dcc..be8d7ad1c 100644 --- a/implants/lib/eldritch/src/sys/get_ip_impl.rs +++ b/implants/lib/eldritch/src/sys/get_ip_impl.rs @@ -1,8 +1,7 @@ -use anyhow::Result; -#[cfg(target_os = "windows")] +use std::net::IpAddr; + +use anyhow::{Context, Result}; use network_interface::{NetworkInterface, NetworkInterfaceConfig}; -#[cfg(not(target_os = "windows"))] -use pnet::datalink::{interfaces, NetworkInterface}; use super::super::insert_dict_kv; use starlark::{ @@ -13,43 +12,61 @@ use starlark::{ const UNKNOWN: &str = "UNKNOWN"; -#[derive(Debug)] -#[cfg(target_os = "windows")] struct NetInterface { name: String, - ips: Vec, //IPv6 and IPv4 Addresses on the itnerface + ips: Vec, //IPv6 and IPv4 Addresses on the interface mac: String, } -#[cfg(target_os = "windows")] +fn netmask_to_cidr(netmask: IpAddr) -> Result { + let binding = netmask.to_string(); + let mut cidr_prefix = 0; + for octet in binding.split('.') { + cidr_prefix += match octet.parse::() { + Ok(x) => x.count_ones(), + Err(_err) => { + #[cfg(debug_assertions)] + eprintln!("Failed to convert {} in netmask {}", octet, netmask); + 0 + } + } + } + + Ok(cidr_prefix as u8) +} + fn handle_get_ip() -> Result> { let mut res = Vec::new(); for network_interface in NetworkInterface::show()? { - let mac_addr = match network_interface.mac_addr { + let mac = match network_interface.mac_addr { Some(local_mac) => local_mac, None => UNKNOWN.to_string(), }; - let mut ips: Vec = Vec::new(); + let name = network_interface.name; + + let mut ips: Vec = Vec::new(); for ip in network_interface.addr { - ips.push(ip.ip()); + if ip.ip().is_ipv4() { + match ip.netmask() { + Some(netmask) => { + let cidr = netmask_to_cidr(netmask)?; + ips.push(format!("{}/{}", ip.ip(), cidr)); + }, + None => { + ips.push(ip.ip().to_string()) + } + } + } else { + ips.push(ip.ip().to_string()) + } } - res.push(NetInterface { - name: network_interface.name, - ips: ips, - mac: mac_addr, - }); + res.push(NetInterface { name, ips, mac }); } Ok(res) } -#[cfg(not(target_os = "windows"))] -fn handle_get_ip() -> Result> { - Ok(interfaces()) -} - -#[cfg(target_os = "windows")] fn create_dict_from_interface(starlark_heap: &Heap, interface: NetInterface) -> Result { let res: SmallMap = SmallMap::new(); let mut tmp_res = Dict::new(res); @@ -66,32 +83,6 @@ fn create_dict_from_interface(starlark_heap: &Heap, interface: NetInterface) -> Ok(tmp_res) } -#[cfg(not(target_os = "windows"))] -fn create_dict_from_interface(starlark_heap: &Heap, interface: NetworkInterface) -> Result { - let res: SmallMap = SmallMap::new(); - let mut tmp_res = Dict::new(res); - - insert_dict_kv!(tmp_res, starlark_heap, "name", &interface.name, String); - - let mut tmp_value2_arr = Vec::::new(); - for ip in interface.ips { - tmp_value2_arr.push(starlark_heap.alloc_str(&ip.to_string()).to_value()); - } - insert_dict_kv!(tmp_res, starlark_heap, "ips", tmp_value2_arr, Vec<_>); - insert_dict_kv!( - tmp_res, - starlark_heap, - "mac", - &interface - .mac - .map(|mac| mac.to_string()) - .unwrap_or(UNKNOWN.to_string()), - String - ); - - Ok(tmp_res) -} - pub fn get_ip(starlark_heap: &Heap) -> Result> { let mut final_res: Vec = Vec::new(); for network_interface in handle_get_ip()? { @@ -110,6 +101,6 @@ mod tests { let starlark_heap = Heap::new(); let res = get_ip(&starlark_heap).unwrap(); println!("{:?}", res); - assert!(format!("{:?}", res).contains("127.0.0.1")); + assert!(format!("{:?}", res).contains("127.0.0.1/8")); } }