From 920a0f78e9a883518a5803cc454754cfa1816ff7 Mon Sep 17 00:00:00 2001 From: Michael Mikovsky <77305074+Astatin3@users.noreply.github.com> Date: Wed, 12 Nov 2025 17:39:11 -0700 Subject: [PATCH] (Broken) Work on new dynamic runtime config system --- unshell-breakout-module/Cargo.lock | 35 +++++-- unshell-config/Cargo.lock | 7 ++ unshell-config/Cargo.toml | 6 ++ unshell-config/src/main.rs | 3 + unshell-lib/Cargo.lock | 35 +++++-- unshell-lib/Cargo.toml | 19 ++-- unshell-lib/src/client/mod.rs | 12 +-- unshell-lib/src/components.rs | 22 +++++ unshell-lib/src/config/mod.rs | 45 +++++++++ unshell-lib/src/lib.rs | 9 +- unshell-lib/src/module/manager.rs | 153 ++++++++++++++++++++--------- unshell-payload/Cargo.lock | 35 +++++-- unshell-payload/Cargo.toml | 1 + unshell-payload/src/main.rs | 30 ++++-- 14 files changed, 319 insertions(+), 93 deletions(-) create mode 100644 unshell-config/Cargo.lock create mode 100644 unshell-config/Cargo.toml create mode 100644 unshell-config/src/main.rs create mode 100644 unshell-lib/src/components.rs create mode 100644 unshell-lib/src/config/mod.rs diff --git a/unshell-breakout-module/Cargo.lock b/unshell-breakout-module/Cargo.lock index 0e4e1ac..6c2ed0b 100644 --- a/unshell-breakout-module/Cargo.lock +++ b/unshell-breakout-module/Cargo.lock @@ -256,6 +256,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + [[package]] name = "js-sys" version = "0.3.82" @@ -368,6 +374,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + [[package]] name = "serde" version = "1.0.228" @@ -375,6 +387,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -397,6 +410,19 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + [[package]] name = "sha2" version = "0.10.9" @@ -463,16 +489,11 @@ dependencies = [ name = "unshell-lib" version = "0.0.0" dependencies = [ - "aes", "bincode", - "block-padding 0.4.1", - "cbc", "chrono", - "getrandom", - "hex", - "hex-literal", "libloading", - "sha2", + "serde", + "serde_json", "unshell-obfuscate", ] diff --git a/unshell-config/Cargo.lock b/unshell-config/Cargo.lock new file mode 100644 index 0000000..fdbe8bb --- /dev/null +++ b/unshell-config/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "unshell-config" +version = "0.1.0" diff --git a/unshell-config/Cargo.toml b/unshell-config/Cargo.toml new file mode 100644 index 0000000..5afc118 --- /dev/null +++ b/unshell-config/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "unshell-config" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/unshell-config/src/main.rs b/unshell-config/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/unshell-config/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/unshell-lib/Cargo.lock b/unshell-lib/Cargo.lock index 320f3cd..24f83b1 100644 --- a/unshell-lib/Cargo.lock +++ b/unshell-lib/Cargo.lock @@ -256,6 +256,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + [[package]] name = "js-sys" version = "0.3.82" @@ -368,6 +374,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + [[package]] name = "serde" version = "1.0.228" @@ -375,6 +387,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -397,6 +410,19 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + [[package]] name = "sha2" version = "0.10.9" @@ -455,16 +481,11 @@ dependencies = [ name = "unshell-lib" version = "0.0.0" dependencies = [ - "aes", "bincode", - "block-padding 0.4.1", - "cbc", "chrono", - "getrandom", - "hex", - "hex-literal", "libloading", - "sha2", + "serde", + "serde_json", "unshell-obfuscate", ] diff --git a/unshell-lib/Cargo.toml b/unshell-lib/Cargo.toml index 3a008f5..ba8ce86 100644 --- a/unshell-lib/Cargo.toml +++ b/unshell-lib/Cargo.toml @@ -3,8 +3,15 @@ name = "unshell-lib" edition = "2024" [features] +default = ["client", "server"] + +# Components +client = [] +server = [] + log_debug = [] + [dependencies] # Base dependencies libloading = {version = "0.8.9"} @@ -12,13 +19,5 @@ bincode = "2.0.1" unshell-obfuscate = {path = "../unshell-obfuscate"} chrono = "0.4.42" -# Crypt dependencies -aes = "0.8.4" -block-padding = "0.4.1" -cbc = "0.1.2" -getrandom = "0.3.4" -hex = "0.4.3" -hex-literal = "1.1.0" -sha2 = "0.10.9" - -# +serde = {version = "1.0.228", features=["derive"]} +serde_json = "1.0.145" diff --git a/unshell-lib/src/client/mod.rs b/unshell-lib/src/client/mod.rs index 966ab87..07f12de 100644 --- a/unshell-lib/src/client/mod.rs +++ b/unshell-lib/src/client/mod.rs @@ -1,7 +1,5 @@ mod client_runtime; -use std::sync::{Arc, Mutex}; - pub const MODULE_NAME: &'static str = "client"; // pub use unshell_modules::setup_logger; @@ -10,9 +8,7 @@ pub const MODULE_NAME: &'static str = "client"; use crate::{ Component, - ModuleRuntime, - client::client_runtime::RuntimeTest, - module::{Interface, Manager}, + module::Interface, module_interface, warn, // module_interface, @@ -60,9 +56,9 @@ impl Component for ClientComponent { MODULE_NAME } - fn start_runtime(&self, manager: Arc>) -> Option> { - Some(Box::new(RuntimeTest::new(manager))) - } + // fn start_runtime(&self, manager: Arc>) -> Option> { + // Some(Box::new(RuntimeTest::new(manager))) + // } fn clone_box(&self) -> Box { Box::new(self.clone()) diff --git a/unshell-lib/src/components.rs b/unshell-lib/src/components.rs new file mode 100644 index 0000000..441d37c --- /dev/null +++ b/unshell-lib/src/components.rs @@ -0,0 +1,22 @@ +use unshell_obfuscate::obfuscated_symbol; + +use crate::{Component, config::NamedComponent}; + +use std::collections::HashMap; + +#[obfuscated_symbol] +pub fn get_components() -> Vec { + // let mut components: HashMap<&'static str, Box> = HashMap::new(); + + return vec![ + NamedComponent {name:,crate::client::MODULE_NAME, get_interface: crate::client::get_interface, start_runtime: todo!() }, + ]; + + // components + + // vec![ + // Feature::Client, + // #[cfg(feature = "server")] + // Feature::Server, + // ] +} diff --git a/unshell-lib/src/config/mod.rs b/unshell-lib/src/config/mod.rs new file mode 100644 index 0000000..2002343 --- /dev/null +++ b/unshell-lib/src/config/mod.rs @@ -0,0 +1,45 @@ +use std::collections::HashMap; + +// use bincode::{Decode, Encode}; +// use serde::{Deserialize, Serialize}; + +use crate::{ModuleError, ModuleRuntime}; + +// /// Payload config that is instantiated +// #[derive(Serialize, Deserialize)] +// pub struct Config { +// pub id: String, +// pub key: String, +// pub components: Vec, +// } + +pub struct PayloadConfig { + pub id: &'static str, + pub components: Vec, + pub runtime_config: Vec, +} + +#[derive(Debug, Clone)] +pub struct RuntimeConfig { + pub parent_component: &'static str, + pub name: &'static str, + pub config: HashMap, +} + +pub struct NamedComponent { + pub name: &'static str, + + // + Sync + Sync + Sync + Sync + Sync + Sync + Sync + Sync + pub get_interface: &'static (dyn Fn() -> Option<&'static (dyn InterfaceWrapper + Sync)> + Sync), + pub start_runtime: &'static ( + dyn Fn(&'static RuntimeConfig) -> Result<&'static dyn ModuleRuntime, ModuleError> + + Sync + ), +} + +/// Trait that wraps the get_interface() function inside of components +pub trait InterfaceWrapper: Send + Sync { + fn get_interface() -> Option + where + Self: Sized; +} diff --git a/unshell-lib/src/lib.rs b/unshell-lib/src/lib.rs index 1b19235..236b4f8 100644 --- a/unshell-lib/src/lib.rs +++ b/unshell-lib/src/lib.rs @@ -1,10 +1,14 @@ #![no_main] pub mod client; +pub mod config; pub mod logger; pub mod module; pub mod server; +mod components; +pub use components::get_components; + mod announcement; use std::{ fmt, @@ -46,7 +50,7 @@ impl fmt::Display for ModuleError { } /// Trait for defining modules that have a runtime. -pub trait ModuleRuntime: Send { +pub trait ModuleRuntime: Send + Sync { /// Returns true if the module is running. /// After returning false, the module will be dropped. fn is_running(&self) -> bool; @@ -56,7 +60,8 @@ pub trait ModuleRuntime: Send { pub trait Component { fn name(&self) -> &'static str; - fn start_runtime(&self, manager: Arc>) -> Option>; + // fn start_runtime(&self, manager: Arc>) -> Option>; + fn get_interface(&self) -> Box; fn clone_box(&self) -> Box; } diff --git a/unshell-lib/src/module/manager.rs b/unshell-lib/src/module/manager.rs index cdb839a..5e397ff 100644 --- a/unshell-lib/src/module/manager.rs +++ b/unshell-lib/src/module/manager.rs @@ -7,81 +7,142 @@ use std::{ use unshell_obfuscate::symbol; -use crate::*; +use crate::{ + config::{NamedComponent, PayloadConfig, RuntimeConfig}, + *, +}; use module::Module; // #[derive(Debug)] -pub struct Manager { +pub struct Manager<'a> { + id: &'static str, + modules: Vec, - components: HashMap<&'static str, Box>, + + active_runtimes: Vec<&'a dyn ModuleRuntime>, + // runtime_config: Vec, + components: HashMap, } // static mut MANAGER_RUNTIME: Option>> = None; -impl Manager { +impl<'a> Manager<'a> { + fn new(id: &'static str, config: &'a Vec, modules: Vec) -> Self { + Self { + id, + + // config, + modules, + + components: config.iter().map(|c| (c.name.to_string(), c)).collect(), + + active_runtimes: Vec::new(), + } + } + /// Create Manager, and run initilization for each Module #[allow(static_mut_refs)] - pub fn run<'a>(modules: Vec) { - let this: Self = Self::load_modules(modules); - let components = this.components.clone(); + pub fn run(config: &'static PayloadConfig, modules: Vec) { + // Construct self + let this = Self::new(&config.id, &config.components, modules); + + // Load each of the pre-prepared modules + // this.load_components(); let this = Arc::new(Mutex::new(this)); - let mut runtimes: Vec> = Vec::new(); + Self::start_runtimes(this.clone(), &config.runtime_config); - for (_name, component) in components { - let module_runtime = component.start_runtime(this.clone()); - if let Some(module_runtime) = module_runtime { - runtimes.push(module_runtime); - } - } + // let components = this.components.clone(); - Self::join(&mut runtimes); + // let mut runtimes: Vec> = Vec::new(); + + // for (_name, component) in components { + // let module_runtime = component.start_runtime(this.clone()); + // if let Some(module_runtime) = module_runtime { + // runtimes.push(module_runtime); + // } + // } + + Self::join(this); } - pub fn load_modules<'a>(modules: Vec) -> Self { - let module_count = modules.len(); - let mut this = Self { - modules, - components: HashMap::new(), - }; + // fn load_components(&mut self) { + // for i in 0..self.modules.len() { + // debug!("Importing module {}", i); + // // let this_lock = .unwrap(); + // let component_func = if let Ok(component_func) = self.modules[i] + // .get_symbol:: HashMap<&'static str, Box>>( + // symbol!("get_components").as_bytes(), + // ) { + // component_func + // } else { + // warn!("get_components function not found"); + // continue; + // }; - for i in 0..module_count { - debug!("Importing module {}", i); - // let this_lock = .unwrap(); - let component_func = if let Ok(component_func) = this.modules[i] - .get_symbol:: HashMap<&'static str, Box>>( - symbol!("get_components").as_bytes(), - ) { - component_func - } else { - warn!("get_components function not found"); - continue; + // let components = component_func(); + + // let len = components.len(); + // debug!("[{}] Loaded {} components", i, len); + + // self.components.extend(components); + // } + // } + + /// Start each runtime + fn start_runtimes(this: Arc>, runtimes: &'static Vec) { + for runtime in runtimes { + let mut this_lock = this.lock().unwrap(); + + let component = match this_lock.components.get(runtime.parent_component) { + Some(component) => component, + None => { + warn!( + "Could not find component {} which is referenced by runtime {}", + runtime.parent_component, runtime.name + ); + continue; + } }; - let components = component_func(); + let runtime = match (*component.start_runtime)(runtime) { + Ok(runtime) => runtime, + Err(e) => { + warn!("Failed to start runtime: {:?}", e); + continue; + } + }; - let len = components.len(); - debug!("[{}] Loaded {} components", i, len); - - this.components.extend(components); + this_lock.active_runtimes.push(runtime); } - - this } /// Iterateratively loop through all runtimes, until all are finished executing - pub fn join(runtimes: &mut Vec>) { - // let mut len = runtimes.len().clone(); - while runtimes.len() > 0 { - runtimes.retain(|runtime| runtime.is_running()); + fn join(this: Arc>) { + loop { + let mut this_lock = this.lock().unwrap(); - thread::sleep(Duration::from_micros(100)); + if this_lock.active_runtimes.len() <= 0 { + break; + } + + this_lock + .active_runtimes + .retain(|runtime| runtime.is_running()); + + drop(this_lock); + + thread::sleep(Duration::from_millis(500)); } } - pub fn get_component(&self) -> HashMap<&'static str, Box> { - self.components.clone() + // pub fn get_component(&self) -> HashMap<&'static str, Box> { + // self.components.clone() + // } + + pub fn get_name(&self) -> &str { + self.id } // pub extern "C" fn test1234(&self, float: f32) { diff --git a/unshell-payload/Cargo.lock b/unshell-payload/Cargo.lock index 13963e9..5a3edac 100644 --- a/unshell-payload/Cargo.lock +++ b/unshell-payload/Cargo.lock @@ -341,6 +341,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + [[package]] name = "jiff" version = "0.2.15" @@ -498,6 +504,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + [[package]] name = "serde" version = "1.0.228" @@ -505,6 +517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -527,6 +540,19 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + [[package]] name = "sha2" version = "0.10.9" @@ -585,16 +611,11 @@ dependencies = [ name = "unshell-lib" version = "0.0.0" dependencies = [ - "aes", "bincode", - "block-padding 0.4.1", - "cbc", "chrono", - "getrandom", - "hex", - "hex-literal", "libloading", - "sha2", + "serde", + "serde_json", "unshell-obfuscate", ] diff --git a/unshell-payload/Cargo.toml b/unshell-payload/Cargo.toml index 067a91f..db86bbc 100644 --- a/unshell-payload/Cargo.toml +++ b/unshell-payload/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" [features] obfuscate = ["unshell-obfuscate/obfuscate"] log_debug = ["unshell-lib/log_debug"] +# default = ["obfuscate"] [dependencies] env_logger = "0.11.8" diff --git a/unshell-payload/src/main.rs b/unshell-payload/src/main.rs index 6c8efb4..afa6b72 100644 --- a/unshell-payload/src/main.rs +++ b/unshell-payload/src/main.rs @@ -1,11 +1,28 @@ use unshell_lib::{ ModuleError, + config::{PayloadConfig, RuntimeConfig}, module::{Manager, Module}, }; +use unshell_obfuscate::symbol; #[macro_use] extern crate unshell_lib; +static PAYLOAD_CONFIG: PayloadConfig = PayloadConfig { + id: symbol!("Test ID"), + components: unshell_lib::get_components(), + runtime_config: vec![ + RuntimeConfig { + "client" + } + ], +}; + +// static RUNTIME_CONFIG: PayloadConfig = PayloadConfig { +// id: symbol!("Test ID"), +// components: Vec::new(), +// }; + fn main() { #[cfg(not(feature = "obfuscate"))] unshell_lib::logger::PrettyLogger::init(); @@ -15,12 +32,13 @@ fn main() { match || -> Result<(), ModuleError> { let args = std::env::args(); - let mut modules = Vec::new(); - for arg in args.skip(1) { - debug!("Loading module: {}", arg); - modules.push(Module::new(&arg)?) - } - Manager::run(modules); + // let mut modules = Vec::new(); + // for arg in args.skip(1) { + // debug!("Loading module: {}", arg); + // modules.push(Module::new(&arg)?) + // } + + Manager::run(&PAYLOAD_CONFIG, Vec::new()); Ok(()) }() {