From 2dfa296b417f24923b8108dd10769b8fa48d0c1c Mon Sep 17 00:00:00 2001
From: Hulto <7121375+hulto@users.noreply.github.com>
Date: Sat, 22 Jul 2023 16:16:46 -0400
Subject: [PATCH] Implement sys.get_os (#238)
* Implemented, tested, documented.
* Fix lib test.
---
docs/_docs/user-guide/eldritch.md | 14 +++++
implants/lib/eldritch/Cargo.toml | 1 +
implants/lib/eldritch/src/lib.rs | 2 +-
implants/lib/eldritch/src/sys.rs | 5 ++
implants/lib/eldritch/src/sys/get_os_impl.rs | 58 ++++++++++++++++++++
5 files changed, 79 insertions(+), 1 deletion(-)
create mode 100644 implants/lib/eldritch/src/sys/get_os_impl.rs
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