diff --git a/docs/_docs/dev-guide/eldritch.md b/docs/_docs/dev-guide/eldritch.md
index 6ce506ab1..9dc3a617e 100644
--- a/docs/_docs/dev-guide/eldritch.md
+++ b/docs/_docs/dev-guide/eldritch.md
@@ -41,6 +41,7 @@ Currently Eldritch has the following libraries your function can be bound to:
* `http`: Is used for any web requests needed to be made.
* `pivot`: Is used to migrate to identify, and migrate between systems. The pivot library is also responsible for facilitating connectivity within an environment.
* `process`: Is used to manage running processes on a system.
+* `random` - Used to generate cryptographically secure random values.
* `regex`: Is used to preform regex operations on strings.
* `report`: Is used to report structured data to the caller of the eldritch environment (e.g. to the c2).
* `sys`: Is used to check system specific configurations and start new processes.
diff --git a/docs/_docs/user-guide/eldritch.md b/docs/_docs/user-guide/eldritch.md
index b30d4a9ca..f3b5e4e81 100644
--- a/docs/_docs/user-guide/eldritch.md
+++ b/docs/_docs/user-guide/eldritch.md
@@ -89,6 +89,7 @@ The standard library is the default functionality that eldritch provides. It con
- `http` - Used to make http(s) requests from the agent.
- `pivot` - Used to identify and move between systems.
- `process` - Used to interact with processes on the system.
+- `random` - Used to generate cryptographically secure random values.
- `regex` - Regular expression capabilities for operating on strings.
- `report` - Structured data reporting capabilities.
- `sys` - General system capabilities can include loading libraries, or information about the current context.
@@ -681,6 +682,18 @@ The process.netstat method returns all information on TCP, UDP, and Unix
---
+## Random
+
+The random library is designed to enable generation of cryptogrphically secure random vaules. None of these functions will be blocking.
+
+### random.bool
+
+`random.bool() -> bool`
+
+The random.bool method returns a randomly sourced boolean value.
+
+---
+
## Regex
The regex library is designed to enable basic regex operations on strings. Be aware as the underlying implementation is written
diff --git a/implants/Cargo.toml b/implants/Cargo.toml
index 07dedccc1..754915e08 100644
--- a/implants/Cargo.toml
+++ b/implants/Cargo.toml
@@ -47,6 +47,7 @@ pretty_env_logger = "0.5.0"
prost = "0.12"
prost-types = "0.12"
rand = "0.8.5"
+rand_chacha = "0.3.1"
regex = "1.5.5"
reqwest = "0.11.18"
russh = "0.37.1"
diff --git a/implants/lib/eldritch/Cargo.toml b/implants/lib/eldritch/Cargo.toml
index d15be8117..1d471c6e3 100644
--- a/implants/lib/eldritch/Cargo.toml
+++ b/implants/lib/eldritch/Cargo.toml
@@ -35,6 +35,8 @@ openssl = { workspace = true, features = ["vendored"] }
portable-pty = { workspace = true }
pretty_env_logger = { workspace = true }
prost-types = { workspace = true }
+rand = { workspace = true }
+rand_chacha = { workspace = true }
regex = { workspace = true }
reqwest = { workspace = true, features = ["blocking", "stream"] }
russh = { workspace = true }
diff --git a/implants/lib/eldritch/src/assets/list_impl.rs b/implants/lib/eldritch/src/assets/list_impl.rs
index fca856f80..3920b11d0 100644
--- a/implants/lib/eldritch/src/assets/list_impl.rs
+++ b/implants/lib/eldritch/src/assets/list_impl.rs
@@ -17,7 +17,7 @@ pub fn list(starlark_eval: &Evaluator<'_, '_>) -> Result> {
}
res.push(asset_path_string)
}
- if res.len() > 0 {
+ if !res.is_empty() {
return Ok(res);
}
}
diff --git a/implants/lib/eldritch/src/lib.rs b/implants/lib/eldritch/src/lib.rs
index 66aaa65a3..b602966ae 100644
--- a/implants/lib/eldritch/src/lib.rs
+++ b/implants/lib/eldritch/src/lib.rs
@@ -4,6 +4,7 @@ pub mod file;
pub mod http;
pub mod pivot;
pub mod process;
+pub mod random;
pub mod regex;
mod report;
pub mod runtime;
diff --git a/implants/lib/eldritch/src/random/bool_impl.rs b/implants/lib/eldritch/src/random/bool_impl.rs
new file mode 100644
index 000000000..a12b2e5bd
--- /dev/null
+++ b/implants/lib/eldritch/src/random/bool_impl.rs
@@ -0,0 +1,45 @@
+use anyhow::Result;
+use rand::Rng;
+use rand_chacha::rand_core::SeedableRng;
+
+pub fn bool() -> Result {
+ let mut rng = rand_chacha::ChaCha20Rng::from_entropy();
+ Ok(rng.gen::())
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ const NUM_ITERATION: i32 = 1000;
+
+ #[test]
+ fn test_bool() -> anyhow::Result<()> {
+ bool()?;
+ Ok(())
+ }
+
+ #[test]
+ fn test_bool_uniform() -> anyhow::Result<()> {
+ let mut num_true = 0;
+ for _ in 0..NUM_ITERATION {
+ let b = bool()?;
+ if b {
+ num_true += 1;
+ }
+ }
+
+ let lower_bound = 0.40 * NUM_ITERATION as f64;
+ let upper_bound = 0.60 * NUM_ITERATION as f64;
+ let high_enough = lower_bound < num_true as f64;
+ let low_enough = upper_bound > num_true as f64;
+ assert!(
+ high_enough && low_enough,
+ "{} was not between the acceptable bounds of ({},{})",
+ num_true,
+ lower_bound,
+ upper_bound
+ );
+ Ok(())
+ }
+}
diff --git a/implants/lib/eldritch/src/random/mod.rs b/implants/lib/eldritch/src/random/mod.rs
new file mode 100644
index 000000000..e0e5e0e0b
--- /dev/null
+++ b/implants/lib/eldritch/src/random/mod.rs
@@ -0,0 +1,22 @@
+mod bool_impl;
+
+use starlark::{environment::MethodsBuilder, starlark_module, values::starlark_value};
+
+/*
+ * Define our library for this module.
+ */
+crate::eldritch_lib!(RandomLibrary, "random_library");
+
+/*
+ * Below, we define starlark wrappers for all of our library methods.
+ * The functions must be defined here to be present on our library.
+ */
+#[starlark_module]
+#[rustfmt::skip]
+#[allow(clippy::needless_lifetimes, clippy::type_complexity, clippy::too_many_arguments)]
+fn methods(builder: &mut MethodsBuilder) {
+ #[allow(unused_variables)]
+ fn bool<'v>(this: &RandomLibrary) -> anyhow::Result {
+ bool_impl::bool()
+ }
+}
diff --git a/implants/lib/eldritch/src/runtime/eval.rs b/implants/lib/eldritch/src/runtime/eval.rs
index 912dd5970..9c5f20d84 100644
--- a/implants/lib/eldritch/src/runtime/eval.rs
+++ b/implants/lib/eldritch/src/runtime/eval.rs
@@ -6,6 +6,7 @@ use crate::{
http::HTTPLibrary,
pivot::PivotLibrary,
process::ProcessLibrary,
+ random::RandomLibrary,
regex::RegexLibrary,
report::ReportLibrary,
runtime::{
@@ -168,6 +169,7 @@ impl Runtime {
const assets: AssetsLibrary = AssetsLibrary;
const crypto: CryptoLibrary = CryptoLibrary;
const time: TimeLibrary = TimeLibrary;
+ const random: RandomLibrary = RandomLibrary;
const report: ReportLibrary = ReportLibrary;
const regex: RegexLibrary = RegexLibrary;
const http: HTTPLibrary = HTTPLibrary;
diff --git a/implants/lib/eldritch/src/runtime/mod.rs b/implants/lib/eldritch/src/runtime/mod.rs
index 482d88852..2dcf2054d 100644
--- a/implants/lib/eldritch/src/runtime/mod.rs
+++ b/implants/lib/eldritch/src/runtime/mod.rs
@@ -152,6 +152,16 @@ mod tests {
want_text: format!("{}\n", r#"["format_to_epoch", "format_to_readable", "now", "sleep"]"#),
want_error: None,
},
+ random_bindings: TestCase {
+ id: 123,
+ tome: Tome {
+ eldritch: String::from("print(dir(random))"),
+ parameters: HashMap::new(),
+ file_names: Vec::new(),
+ },
+ want_text: format!("{}\n", r#"["bool"]"#),
+ want_error: None,
+ },
report_bindings: TestCase {
id: 123,
tome: Tome {