diff --git a/docs/_docs/user-guide/eldritch.md b/docs/_docs/user-guide/eldritch.md index cd5c020c3..88e63ea7a 100644 --- a/docs/_docs/user-guide/eldritch.md +++ b/docs/_docs/user-guide/eldritch.md @@ -330,6 +330,20 @@ The sys.get_ip method returns a list of network interfaces as a dictionar ] ``` +### sys.get_os +`sys.get_os() -> Dict` + +The sys.get_os method returns a dictionary that describes the current systems OS. +An example is below: + +```json +{ + "arch": "x86_64", + "desktop_env": "Unknown: Unknown", + "distro": "Debian GNU/Linux 10 (buster)", + "platform": "Linux" +} + ### sys.is_linux `sys.is_linux() -> bool` diff --git a/implants/lib/eldritch/Cargo.toml b/implants/lib/eldritch/Cargo.toml index 11dc9a78b..dc077880c 100644 --- a/implants/lib/eldritch/Cargo.toml +++ b/implants/lib/eldritch/Cargo.toml @@ -35,6 +35,7 @@ windows-sys = { workspace = true, features = [ "Win32_System_Diagnostics_Debug", "Win32_Security", ]} +whoami = { workspace = true } [dev-dependencies] httptest = { workspace = true } diff --git a/implants/lib/eldritch/src/lib.rs b/implants/lib/eldritch/src/lib.rs index 782cf1173..c61298a61 100644 --- a/implants/lib/eldritch/src/lib.rs +++ b/implants/lib/eldritch/src/lib.rs @@ -172,7 +172,7 @@ mod tests { r#" dir(file) == ["append", "compress", "copy", "download", "exists", "hash", "is_dir", "is_file", "mkdir", "read", "remove", "rename", "replace", "replace_all", "template", "timestomp", "write"] dir(process) == ["kill", "list", "name"] -dir(sys) == ["dll_inject", "exec", "get_ip", "is_linux", "is_macos", "is_windows", "shell"] +dir(sys) == ["dll_inject", "exec", "get_ip", "get_os", "is_linux", "is_macos", "is_windows", "shell"] dir(pivot) == ["arp_scan", "bind_proxy", "ncat", "port_forward", "port_scan", "smb_exec", "ssh_exec", "ssh_password_spray"] dir(assets) == ["copy","list"] "#, diff --git a/implants/lib/eldritch/src/sys.rs b/implants/lib/eldritch/src/sys.rs index 5e533360c..ecf819497 100644 --- a/implants/lib/eldritch/src/sys.rs +++ b/implants/lib/eldritch/src/sys.rs @@ -1,5 +1,6 @@ mod exec_impl; mod get_ip_impl; +mod get_os_impl; mod is_linux_impl; mod is_windows_impl; mod is_macos_impl; @@ -62,6 +63,10 @@ fn methods(builder: &mut MethodsBuilder) { if false { println!("Ignore unused this var. _this isn't allowed by starlark. {:?}", this); } exec_impl::exec(starlark_heap, path, args, disown) } + fn get_os<'v>(this: SysLibrary, starlark_heap: &'v Heap) -> anyhow::Result> { + if false { println!("Ignore unused this var. _this isn't allowed by starlark. {:?}", this); } + get_os_impl::get_os(starlark_heap) + } fn dll_inject(this: SysLibrary, dll_path: String, pid: u32) -> anyhow::Result { if false { println!("Ignore unused this var. _this isn't allowed by starlark. {:?}", this); } dll_inject_impl::dll_inject(dll_path, pid) diff --git a/implants/lib/eldritch/src/sys/get_os_impl.rs b/implants/lib/eldritch/src/sys/get_os_impl.rs new file mode 100644 index 000000000..23edac8a2 --- /dev/null +++ b/implants/lib/eldritch/src/sys/get_os_impl.rs @@ -0,0 +1,58 @@ +use anyhow::Result; +use starlark::collections::SmallMap; +use starlark::const_frozen_string; +use starlark::values::Heap; +use starlark::values::dict::Dict; + +#[derive(Debug)] +struct OsInfo { + arch: String, + desktop_env: String, + distro: String, + platform: String, +} + +pub fn get_os(starlark_heap: &Heap) -> Result { + + let cmd_res = handle_get_os()?; + + let res = SmallMap::new(); + let mut dict_res = Dict::new(res); + let arch_value = starlark_heap.alloc_str(&cmd_res.arch); + dict_res.insert_hashed(const_frozen_string!("arch").to_value().get_hashed().unwrap(), arch_value.to_value()); + + let desktop_env_value = starlark_heap.alloc_str(&cmd_res.desktop_env); + dict_res.insert_hashed(const_frozen_string!("desktop_env").to_value().get_hashed().unwrap(), desktop_env_value.to_value()); + + let distro = starlark_heap.alloc_str(&cmd_res.distro); + dict_res.insert_hashed(const_frozen_string!("distro").to_value().get_hashed().unwrap(), distro.to_value()); + + let platform = starlark_heap.alloc_str(&cmd_res.platform); + dict_res.insert_hashed(const_frozen_string!("platform").to_value().get_hashed().unwrap(), platform.to_value()); + + Ok(dict_res) +} + +fn handle_get_os() -> Result { + return Ok(OsInfo { + arch: whoami::arch().to_string(), + desktop_env: whoami::desktop_env().to_string(), + distro: whoami::distro().to_string(), + platform: whoami::platform().to_string(), + }); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sys_get_os() -> anyhow::Result<()>{ + + let test_heap = Heap::new(); + let res = get_os(&test_heap)?; + println!("{}", res.to_string()); + assert!(res.to_string().contains(r#""arch": "x86_64""#)); + Ok(()) + } +} \ No newline at end of file