From 490cd994c3b8908e4c1208b61526b992a1542185 Mon Sep 17 00:00:00 2001 From: Nicholas O'Brien Date: Fri, 19 Apr 2024 21:34:46 +0000 Subject: [PATCH] initial commit --- docs/_docs/dev-guide/eldritch.md | 1 + docs/_docs/user-guide/eldritch.md | 13 ++++++ implants/Cargo.toml | 1 + implants/lib/eldritch/Cargo.toml | 2 + implants/lib/eldritch/src/assets/list_impl.rs | 2 +- implants/lib/eldritch/src/lib.rs | 1 + implants/lib/eldritch/src/random/bool_impl.rs | 45 +++++++++++++++++++ implants/lib/eldritch/src/random/mod.rs | 22 +++++++++ implants/lib/eldritch/src/runtime/eval.rs | 2 + implants/lib/eldritch/src/runtime/mod.rs | 10 +++++ 10 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 implants/lib/eldritch/src/random/bool_impl.rs create mode 100644 implants/lib/eldritch/src/random/mod.rs 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 {