mirror of
https://github.com/Astatin3/unshell.git
synced 2026-06-08 22:38:01 -06:00
Rename things to ush for brevity. Add Tree system.
This commit is contained in:
Generated
+78
-78
@@ -3945,85 +3945,8 @@ dependencies = [
|
|||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"unshell-obfuscate",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unshell-gui"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"chrono",
|
|
||||||
"eframe",
|
|
||||||
"egui",
|
|
||||||
"egui-async",
|
|
||||||
"egui_extras",
|
|
||||||
"egui_tiles",
|
|
||||||
"log",
|
|
||||||
"reqwest",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"unshell",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
"web-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unshell-manager"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"bincode",
|
|
||||||
"libc",
|
|
||||||
"libloading",
|
|
||||||
"rand 0.9.2",
|
|
||||||
"unshell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unshell-obfuscate"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"aes",
|
|
||||||
"block-padding 0.4.2",
|
|
||||||
"cbc",
|
|
||||||
"getrandom 0.3.4",
|
|
||||||
"hex",
|
|
||||||
"hex-literal",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rand 0.9.2",
|
|
||||||
"regex",
|
|
||||||
"sha2",
|
|
||||||
"static_init",
|
"static_init",
|
||||||
"syn 2.0.114",
|
"ush-obfuscate",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unshell-payload"
|
|
||||||
version = "0.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"server2",
|
|
||||||
"unshell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unshell-server"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"axum",
|
|
||||||
"axum-extra",
|
|
||||||
"bcrypt",
|
|
||||||
"chrono",
|
|
||||||
"clap",
|
|
||||||
"jsonwebtoken",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"sled",
|
|
||||||
"static_init",
|
|
||||||
"tokio",
|
|
||||||
"toml",
|
|
||||||
"unshell",
|
|
||||||
"unshell-manager",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4056,6 +3979,83 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ush-gui"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"eframe",
|
||||||
|
"egui",
|
||||||
|
"egui-async",
|
||||||
|
"egui_extras",
|
||||||
|
"egui_tiles",
|
||||||
|
"log",
|
||||||
|
"reqwest",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"unshell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ush-manager"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bincode",
|
||||||
|
"libc",
|
||||||
|
"libloading",
|
||||||
|
"rand 0.9.2",
|
||||||
|
"unshell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ush-obfuscate"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"aes",
|
||||||
|
"block-padding 0.4.2",
|
||||||
|
"cbc",
|
||||||
|
"getrandom 0.3.4",
|
||||||
|
"hex",
|
||||||
|
"hex-literal",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rand 0.9.2",
|
||||||
|
"regex",
|
||||||
|
"sha2",
|
||||||
|
"static_init",
|
||||||
|
"syn 2.0.114",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ush-payload"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde_json",
|
||||||
|
"unshell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ush-server"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"axum",
|
||||||
|
"axum-extra",
|
||||||
|
"bcrypt",
|
||||||
|
"chrono",
|
||||||
|
"clap",
|
||||||
|
"jsonwebtoken",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"sled",
|
||||||
|
"static_init",
|
||||||
|
"tokio",
|
||||||
|
"toml",
|
||||||
|
"unshell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8_iter"
|
name = "utf8_iter"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
|||||||
+8
-6
@@ -14,13 +14,15 @@ include = ["LICENSE-APACHE", "LICENSE-MIT", "**/*.rs", "Cargo.toml"]
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
# Binaries
|
# Binaries
|
||||||
"unshell-gui",
|
"ush-gui",
|
||||||
|
|
||||||
# UnShell Binaries
|
# UnShell Binaries
|
||||||
"unshell-server", "unshell-payload",
|
"ush-server",
|
||||||
|
"ush-payload",
|
||||||
|
|
||||||
# Libraries
|
# Libraries
|
||||||
"unshell-manager", "unshell-obfuscate"
|
"ush-manager",
|
||||||
|
"ush-obfuscate"
|
||||||
, "core-modules/server2"]
|
, "core-modules/server2"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@@ -29,7 +31,7 @@ default = []
|
|||||||
log = []
|
log = []
|
||||||
log_debug = ["log"]
|
log_debug = ["log"]
|
||||||
|
|
||||||
obfuscate = ["unshell-obfuscate/obfuscate"]
|
obfuscate = ["ush-obfuscate/obfuscate"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
@@ -38,7 +40,8 @@ serde_json = { workspace = true }
|
|||||||
|
|
||||||
crossbeam-channel = "0.5.15"
|
crossbeam-channel = "0.5.15"
|
||||||
|
|
||||||
unshell-obfuscate = { path = "./unshell-obfuscate" }
|
ush-obfuscate = { path = "./ush-obfuscate" }
|
||||||
|
static_init.workspace = true
|
||||||
# unshell-crypt = {path = "./unshell-crypt"}
|
# unshell-crypt = {path = "./unshell-crypt"}
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
@@ -53,7 +56,6 @@ static_init = "1.0.4"
|
|||||||
toml = "0.9.9"
|
toml = "0.9.9"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 2
|
opt-level = 2
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
# -Z build-std-features= \
|
# -Z build-std-features= \
|
||||||
# --profile minimize -p unshell-payload -- $@
|
# --profile minimize -p unshell-payload -- $@
|
||||||
|
|
||||||
cargo build --profile minimize -p unshell-payload
|
cargo build --profile minimize -p ush-payload $@
|
||||||
|
|
||||||
export BINARY=./target/minimize/unshell-payload
|
export BINARY=./target/minimize/ush-payload
|
||||||
|
|
||||||
declare -a headers=(
|
declare -a headers=(
|
||||||
".gnu_debuglink" # - Debug information link
|
".gnu_debuglink" # - Debug information link
|
||||||
@@ -54,3 +54,7 @@ do
|
|||||||
strip --remove-section="$section" $BINARY
|
strip --remove-section="$section" $BINARY
|
||||||
echo "Removed section header $section"
|
echo "Removed section header $section"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
echo "## STARTING "
|
||||||
|
|
||||||
|
$BINARY
|
||||||
|
|||||||
@@ -7,9 +7,14 @@ pub type Result<T> = std::result::Result<T, ModuleError>;
|
|||||||
pub enum ModuleError {
|
pub enum ModuleError {
|
||||||
NoError,
|
NoError,
|
||||||
|
|
||||||
|
// Tree errors
|
||||||
TreeNotExist,
|
TreeNotExist,
|
||||||
TreeMessageError(String),
|
TreeMessageError(String),
|
||||||
|
|
||||||
|
// Object errors
|
||||||
|
UnsupportedMethod,
|
||||||
|
InvalidType,
|
||||||
|
|
||||||
LibLoadingError(String),
|
LibLoadingError(String),
|
||||||
// LogError(log::SetLoggerError),
|
// LogError(log::SetLoggerError),
|
||||||
LinkError(String),
|
LinkError(String),
|
||||||
|
|||||||
+3
-17
@@ -3,7 +3,7 @@
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
mod error;
|
mod error;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
pub mod manager;
|
pub mod tree;
|
||||||
|
|
||||||
mod announcement;
|
mod announcement;
|
||||||
|
|
||||||
@@ -12,19 +12,5 @@ pub use error::{ModuleError, Result};
|
|||||||
pub use announcement::Announcement;
|
pub use announcement::Announcement;
|
||||||
|
|
||||||
// Re-exports
|
// Re-exports
|
||||||
// pub use unshell_crypt;
|
pub use serde_json::{Value, json};
|
||||||
pub use unshell_obfuscate;
|
pub use ush_obfuscate as obfuscate;
|
||||||
|
|
||||||
// pub trait Component {
|
|
||||||
// fn name(&self) -> &'static str;
|
|
||||||
// // fn start_runtime(&self, manager: Arc<Mutex<Manager>>) -> Option<Box<dyn ModuleRuntime>>;
|
|
||||||
|
|
||||||
// fn get_interface(&self) -> Box<dyn Interface>;
|
|
||||||
// fn clone_box(&self) -> Box<dyn Component>;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl Clone for Box<dyn Component> {
|
|
||||||
// fn clone(&self) -> Box<dyn Component> {
|
|
||||||
// self.clone_box()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|||||||
+23
-117
@@ -1,15 +1,14 @@
|
|||||||
#[cfg(feature = "log_debug")]
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! debug {
|
macro_rules! log {
|
||||||
($fmt:tt) => {{
|
($level:expr, $fmt:tt) => {{
|
||||||
use $crate::unshell_obfuscate;
|
use $crate::obfuscate;
|
||||||
let log_result = unshell_obfuscate::format_obs!($fmt);
|
let log_result = obfuscate::format_obs!($fmt);
|
||||||
|
|
||||||
$crate::logger::add_record(
|
$crate::logger::add_record(
|
||||||
$crate::logger::LogLevel::Debug,
|
$level,
|
||||||
|
|
||||||
#[cfg(feature = "log_debug")]
|
#[cfg(feature = "log_debug")]
|
||||||
Some(String::from(unshell_obfuscate::file_symbol!())),
|
Some(String::from(obfuscate::file_symbol!())),
|
||||||
#[cfg(not(feature = "log_debug"))]
|
#[cfg(not(feature = "log_debug"))]
|
||||||
None,
|
None,
|
||||||
|
|
||||||
@@ -17,15 +16,15 @@ macro_rules! debug {
|
|||||||
log_result
|
log_result
|
||||||
);
|
);
|
||||||
}};
|
}};
|
||||||
($fmt:tt, $($arg:expr),*) => {{
|
($level:expr, $fmt:tt, $($arg:expr),*) => {{
|
||||||
use $crate::unshell_obfuscate;
|
use $crate::obfuscate;
|
||||||
let log_result = unshell_obfuscate::format_obs!($fmt, $($arg),*);
|
let log_result = obfuscate::format_obs!($fmt, $($arg),*);
|
||||||
|
|
||||||
$crate::logger::add_record(
|
$crate::logger::add_record(
|
||||||
$crate::logger::LogLevel::Debug,
|
$level,
|
||||||
|
|
||||||
#[cfg(feature = "log_debug")]
|
#[cfg(feature = "log_debug")]
|
||||||
Some(String::from(unshell_obfuscate::file_symbol!())),
|
Some(String::from(obfuscate::file_symbol!())),
|
||||||
#[cfg(not(feature = "log_debug"))]
|
#[cfg(not(feature = "log_debug"))]
|
||||||
None,
|
None,
|
||||||
|
|
||||||
@@ -35,123 +34,30 @@ macro_rules! debug {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "log_debug"))]
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! debug {
|
macro_rules! debug {
|
||||||
($fmt:tt) => {{
|
($($arg:tt)*) => {
|
||||||
let _ = $fmt;
|
$crate::log!($crate::logger::LogLevel::Debug, $($arg)*)
|
||||||
}};
|
};
|
||||||
($fmt:tt, $($arg:expr),*) => {{
|
|
||||||
let _ = $fmt;
|
|
||||||
$(let _ = $arg;)*
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! info {
|
macro_rules! info {
|
||||||
($fmt:tt) => {{
|
($($arg:tt)*) => {
|
||||||
use $crate::unshell_obfuscate;
|
$crate::log!($crate::logger::LogLevel::Info, $($arg)*)
|
||||||
let log_result = unshell_obfuscate::format_obs!($fmt);
|
};
|
||||||
|
|
||||||
$crate::logger::add_record(
|
|
||||||
$crate::logger::LogLevel::Info,
|
|
||||||
|
|
||||||
#[cfg(feature = "log_debug")]
|
|
||||||
Some(String::from(unshell_obfuscate::file_symbol!())),
|
|
||||||
#[cfg(not(feature = "log_debug"))]
|
|
||||||
None,
|
|
||||||
|
|
||||||
std::time::SystemTime::now(),
|
|
||||||
log_result
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
($fmt:tt, $($arg:expr),*) => {{
|
|
||||||
use $crate::unshell_obfuscate;
|
|
||||||
let log_result = unshell_obfuscate::format_obs!($fmt, $($arg),*);
|
|
||||||
|
|
||||||
$crate::logger::add_record(
|
|
||||||
$crate::logger::LogLevel::Info,
|
|
||||||
|
|
||||||
#[cfg(feature = "log_debug")]
|
|
||||||
Some(String::from(unshell_obfuscate::file_symbol!())),
|
|
||||||
#[cfg(not(feature = "log_debug"))]
|
|
||||||
None,
|
|
||||||
|
|
||||||
std::time::SystemTime::now(),
|
|
||||||
log_result
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! warn {
|
macro_rules! warn {
|
||||||
($fmt:tt) => {{
|
($($arg:tt)*) => {
|
||||||
use $crate::unshell_obfuscate;
|
$crate::log!($crate::logger::LogLevel::Warn, $($arg)*)
|
||||||
|
};
|
||||||
let log_result = unshell_obfuscate::format_obs!($fmt);
|
|
||||||
|
|
||||||
$crate::logger::add_record(
|
|
||||||
$crate::logger::LogLevel::Warn,
|
|
||||||
|
|
||||||
#[cfg(feature = "log_debug")]
|
|
||||||
Some(String::from(unshell_obfuscate::file_symbol!())),
|
|
||||||
#[cfg(not(feature = "log_debug"))]
|
|
||||||
None,
|
|
||||||
|
|
||||||
std::time::SystemTime::now(),
|
|
||||||
log_result
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
($fmt:tt, $($arg:expr),*) => {{
|
|
||||||
use $crate::unshell_obfuscate;
|
|
||||||
|
|
||||||
let log_result = unshell_obfuscate::format_obs!($fmt, $($arg),*);
|
|
||||||
|
|
||||||
$crate::logger::add_record(
|
|
||||||
$crate::logger::LogLevel::Warn,
|
|
||||||
|
|
||||||
#[cfg(feature = "log_debug")]
|
|
||||||
Some(String::from(unshell_obfuscate::file_symbol!())),
|
|
||||||
#[cfg(not(feature = "log_debug"))]
|
|
||||||
None,
|
|
||||||
|
|
||||||
std::time::SystemTime::now(),
|
|
||||||
log_result
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! error {
|
macro_rules! error {
|
||||||
($fmt:tt) => {{
|
($($arg:tt)*) => {
|
||||||
let log_result = unshell_obfuscate::format_obs!($fmt);
|
$crate::log!($crate::logger::LogLevel::Error, $($arg)*)
|
||||||
|
};
|
||||||
$crate::logger::add_record(
|
|
||||||
$crate::logger::LogLevel::Error,
|
|
||||||
|
|
||||||
#[cfg(feature = "log_debug")]
|
|
||||||
Some(String::from(unshell_obfuscate::file_symbol!())),
|
|
||||||
#[cfg(not(feature = "log_debug"))]
|
|
||||||
None,
|
|
||||||
|
|
||||||
std::time::SystemTime::now(),
|
|
||||||
log_result
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
($fmt:tt, $($arg:expr),*) => {{
|
|
||||||
use $crate::unshell_obfuscate;
|
|
||||||
let log_result = unshell_obfuscate::format_obs!($fmt, $($arg),*);
|
|
||||||
|
|
||||||
$crate::logger::add_record(
|
|
||||||
$crate::logger::LogLevel::Error,
|
|
||||||
|
|
||||||
#[cfg(feature = "log_debug")]
|
|
||||||
Some(String::from(unshell_obfuscate::file_symbol!())),
|
|
||||||
#[cfg(not(feature = "log_debug"))]
|
|
||||||
None,
|
|
||||||
|
|
||||||
std::time::SystemTime::now(),
|
|
||||||
log_result
|
|
||||||
);
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ mod pretty_logger;
|
|||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
pub use pretty_logger::PrettyLogger;
|
pub use pretty_logger::PrettyLogger;
|
||||||
|
pub use pretty_logger::log;
|
||||||
|
|
||||||
static mut LOGGER: &dyn Logger = &DefaultLogger;
|
static mut LOGGER: &dyn Logger = &DefaultLogger;
|
||||||
|
|
||||||
|
|||||||
+24
-16
@@ -23,25 +23,33 @@ impl Logger for PrettyLogger {
|
|||||||
(*func)(&message)
|
(*func)(&message)
|
||||||
}
|
}
|
||||||
|
|
||||||
let log_level = match message.log_level {
|
log(&message);
|
||||||
LogLevel::Debug => format!("{DEBUG_COLOR}DBUG"),
|
|
||||||
LogLevel::Info => format!("{INFO_COLOR}INFO"),
|
|
||||||
LogLevel::Warn => format!("{WARN_COLOR}WARN"),
|
|
||||||
LogLevel::Error => format!("{ERROR_COLOR}ERR!"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let date: DateTime<Utc> = message.time.into();
|
|
||||||
let date = date.to_rfc2822().to_string();
|
|
||||||
|
|
||||||
let location = message.location.unwrap_or("".to_string());
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"{OFF_WHITE}[{TIME_COLOR}{}{OFF_WHITE}] {} {WHITE}{} {GREY}{}{WHITE}",
|
|
||||||
date, log_level, message.message, location
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn log(message: &Record) {
|
||||||
|
let log_level = match message.log_level {
|
||||||
|
LogLevel::Debug => format!("{DEBUG_COLOR}DBUG"),
|
||||||
|
LogLevel::Info => format!("{INFO_COLOR}INFO"),
|
||||||
|
LogLevel::Warn => format!("{WARN_COLOR}WARN"),
|
||||||
|
LogLevel::Error => format!("{ERROR_COLOR}ERR!"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let date: DateTime<Utc> = message.time.into();
|
||||||
|
let date = date.to_rfc2822().to_string();
|
||||||
|
|
||||||
|
let location = if let Some(ref location) = message.location {
|
||||||
|
location
|
||||||
|
} else {
|
||||||
|
&String::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"{OFF_WHITE}[{TIME_COLOR}{}{OFF_WHITE}] {} {WHITE}{} {GREY}{}{WHITE}",
|
||||||
|
date, log_level, message.message, location
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
impl PrettyLogger {
|
impl PrettyLogger {
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
crate::logger::set_logger_box(Box::new(PrettyLogger { output: None }));
|
crate::logger::set_logger_box(Box::new(PrettyLogger { output: None }));
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
/// Implement logging for the manager
|
|
||||||
use crossbeam_channel::Sender;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
logger::{Logger, Record},
|
|
||||||
manager::Tree,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct ManagerLogger {
|
|
||||||
tx: Sender<Record>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ManagerLogger {
|
|
||||||
pub fn new(tx: Sender<Record>) -> Self {
|
|
||||||
Self { tx }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl Manager {
|
|
||||||
// /// Initiate the unshell logger, piped through the manager
|
|
||||||
// /// This will allow access to the logs through the tree
|
|
||||||
// pub fn init_logger(&self) {
|
|
||||||
// // Create the logger through the TX element of the manager
|
|
||||||
// let logger = ManagerLogger::new(self.logs_tx.clone());
|
|
||||||
|
|
||||||
// // Set the logger through unshell
|
|
||||||
// crate::logger::set_logger_box(Box::new(logger));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl Logger for ManagerLogger {
|
|
||||||
fn log(&self, log: crate::logger::Record) {
|
|
||||||
// This will never panic if the program is operating properly
|
|
||||||
self.tx.send(log).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
ModuleError,
|
|
||||||
manager::tree_structs::{TreeMessage, TreeType},
|
|
||||||
};
|
|
||||||
|
|
||||||
mod log;
|
|
||||||
mod tree_structs;
|
|
||||||
|
|
||||||
pub trait TreeElement {
|
|
||||||
fn get_children(&self) -> HashMap<String, TreeType>;
|
|
||||||
fn get_type(&self) -> TreeType;
|
|
||||||
fn send_message(&mut self, message: TreeMessage) -> TreeMessage;
|
|
||||||
fn send_message_child(&mut self, element: String, message: TreeMessage) -> TreeMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Tree {
|
|
||||||
elements: HashMap<String, Box<dyn TreeElement>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Tree {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
elements: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_element(&mut self, name: String, element: Box<dyn TreeElement>) {
|
|
||||||
self.elements.insert(name, element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TreeElement for Tree {
|
|
||||||
fn get_children(&self) -> HashMap<String, TreeType> {
|
|
||||||
self.elements
|
|
||||||
.iter()
|
|
||||||
.map(|c| (c.0.clone(), c.1.get_type()))
|
|
||||||
.into_iter()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_type(&self) -> TreeType {
|
|
||||||
TreeType::RootTree
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_message_child(&mut self, element_name: String, message: TreeMessage) -> TreeMessage {
|
|
||||||
if let Some(element) = self.elements.get_mut(&element_name) {
|
|
||||||
element.send_message(message)
|
|
||||||
} else {
|
|
||||||
TreeMessage::Result(ModuleError::TreeNotExist)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send_message(&mut self, _message: TreeMessage) -> TreeMessage {
|
|
||||||
TreeMessage::Response
|
|
||||||
// if let Some(element) = self.elements.get_mut(&element_name) {
|
|
||||||
// element.send_message(message)
|
|
||||||
// } else {
|
|
||||||
// TreeMessage::Result(ModuleError::TreeNotExist)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
pub enum TreeMessage {
|
|
||||||
Request,
|
|
||||||
Response,
|
|
||||||
Result(crate::error::ModuleError),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum TreeType {
|
|
||||||
RootTree,
|
|
||||||
|
|
||||||
TypeA,
|
|
||||||
TypeB,
|
|
||||||
TypeC,
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/// Implement logging for the manager
|
||||||
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
|
use serde_json::{Value, json};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
logger::{Logger, Record},
|
||||||
|
tree::{Tree, TreeElement, symbols},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LoggerTX(Sender<Record>);
|
||||||
|
struct LoggerRX(Receiver<Record>);
|
||||||
|
|
||||||
|
impl Tree {
|
||||||
|
/// Initiate the unshell logger for the local binary, piped through the manager
|
||||||
|
/// This will allow access to the logs through the tree
|
||||||
|
pub fn init_logger(&mut self) {
|
||||||
|
// Create the logger through the TX element of the manager
|
||||||
|
|
||||||
|
let (tx, rx) = crossbeam_channel::unbounded();
|
||||||
|
let (tx, rx) = (LoggerTX(tx), LoggerRX(rx));
|
||||||
|
|
||||||
|
// Set the logger through unshell
|
||||||
|
crate::logger::set_logger_box(Box::new(tx));
|
||||||
|
// Add the logger to the tree
|
||||||
|
self.add_element(symbols::LOGGER.to_string(), Box::new(rx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Logger for LoggerTX {
|
||||||
|
fn log(&self, log: crate::logger::Record) {
|
||||||
|
// This will never panic if the program is operating properly
|
||||||
|
self.0.send(log).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TreeElement for LoggerRX {
|
||||||
|
fn get_type(&self) -> Value {
|
||||||
|
json!(symbols::TYPE_QUEUE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_message(&mut self, target: Value, message: Value) -> Value {
|
||||||
|
match (target, message) {
|
||||||
|
(Value::Null, Value::String(message)) => match message.as_ref() {
|
||||||
|
symbols::CMD_GET => {
|
||||||
|
if !self.0.is_empty() {
|
||||||
|
json!(self.0.recv().unwrap())
|
||||||
|
} else {
|
||||||
|
json!(Value::Null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
symbols::CMD_GET_LENGTH => {
|
||||||
|
json!(self.0.len())
|
||||||
|
}
|
||||||
|
_ => json!(symbols::ERR_INVALID_COMMAND),
|
||||||
|
},
|
||||||
|
_ => json!(symbols::ERR_INVALID_CHILD),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde_json::{Value, json};
|
||||||
|
|
||||||
|
mod log;
|
||||||
|
pub mod symbols;
|
||||||
|
|
||||||
|
pub trait TreeElement {
|
||||||
|
// fn get_children(&self) -> HashMap<TreeType, TreeType>;
|
||||||
|
fn get_type(&self) -> Value;
|
||||||
|
fn send_message(&mut self, target: Value, message: Value) -> Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Tree {
|
||||||
|
elements: HashMap<String, Box<dyn TreeElement>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tree {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
elements: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_element(&mut self, name: String, element: Box<dyn TreeElement>) {
|
||||||
|
self.elements.insert(name, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TreeElement for Tree {
|
||||||
|
fn get_type(&self) -> Value {
|
||||||
|
json!(symbols::TYPE_TREE)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn send_message_child(&mut self, element: Value, message: TreeMessage) -> TreeMessage {
|
||||||
|
// let name = if let TreeType::String(name) = element {
|
||||||
|
// name
|
||||||
|
// } else {
|
||||||
|
// return TreeMessage::Error(ModuleError::InvalidType);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// if let Some(element) = self.elements.get_mut(&name) {
|
||||||
|
// element.send_message(message)
|
||||||
|
// } else {
|
||||||
|
// TreeMessage::Error(ModuleError::TreeNotExist)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn send_message(&mut self, target: Value, message: Value) -> Value {
|
||||||
|
match target {
|
||||||
|
Value::Null => {
|
||||||
|
if let Some(message) = message.as_str() {
|
||||||
|
match message {
|
||||||
|
"GetChildren" => {
|
||||||
|
let children = self
|
||||||
|
.elements
|
||||||
|
.iter()
|
||||||
|
.map(|c| (Value::String(c.0.clone()), c.1.get_type()))
|
||||||
|
.into_iter()
|
||||||
|
.collect::<HashMap<Value, Value>>();
|
||||||
|
|
||||||
|
json!(children)
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => Value::String("UnsupportedMethod".to_owned()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Value::String("UnsupportedMethod".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::String(target) => {
|
||||||
|
if let Some(child) = self.elements.get_mut(&target) {
|
||||||
|
child.send_message(Value::Null, message)
|
||||||
|
} else {
|
||||||
|
Value::String("UnsupportedMethod".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Value::String("UnsupportedMethod".to_owned()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
use crate::obfuscate::symbol;
|
||||||
|
|
||||||
|
pub const LOGGER: &'static str = symbol!("Logger");
|
||||||
|
|
||||||
|
pub const TYPE_TREE: &'static str = symbol!("Tree");
|
||||||
|
pub const TYPE_QUEUE: &'static str = symbol!("Queue");
|
||||||
|
|
||||||
|
pub const CMD_GET: &'static str = symbol!("Get");
|
||||||
|
pub const CMD_POLL: &'static str = symbol!("Poll");
|
||||||
|
pub const CMD_GET_LENGTH: &'static str = symbol!("GetLength");
|
||||||
|
pub const CMD_GET_CHILDREN: &'static str = symbol!("GetChildren");
|
||||||
|
|
||||||
|
pub const ERR_UNSUPPORTED_METHOD: &'static str = symbol!("UnsupportedMethod");
|
||||||
|
pub const ERR_INVALID_COMMAND: &'static str = symbol!("InvalidCommand");
|
||||||
|
pub const ERR_INVALID_CHILD: &'static str = symbol!("InvalidChild");
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
cargo-features = ["trim-paths"]
|
|
||||||
|
|
||||||
[package]
|
|
||||||
name = "unshell-payload"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
# [lib]
|
|
||||||
# crate-type = ["cdylib"]
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["log"]
|
|
||||||
log = ["unshell/log", "server2/log"]
|
|
||||||
log_debug = ["unshell/log_debug", "server2/log_debug"]
|
|
||||||
|
|
||||||
|
|
||||||
# obfuscate = ["unshell-obfuscate/obfuscate"]
|
|
||||||
# log = ["unshell-lib/log"]
|
|
||||||
# log_debug = ["unshell-lib/log_debug"]
|
|
||||||
|
|
||||||
# client = ["unshell-lib/client"]
|
|
||||||
# server = ["unshell-lib/server"]
|
|
||||||
# # server = ["unshell-lib/server"]
|
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
unshell.path = "../"
|
|
||||||
server2.path = "../core-modules/server2"
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# OBFUSCATION_KEY=abc123abc \
|
|
||||||
# RUST_LOG=info \
|
|
||||||
# cargo run --no-default-features $@ --release # $(ls ../*/target/release/*.so)
|
|
||||||
|
|
||||||
OBFUSCATION_KEY=abc123abc \
|
|
||||||
|
|
||||||
cargo build $@ --profile release
|
|
||||||
|
|
||||||
# RUSTFLAGS="-Zlocation-detail=none -Zfmt-debug=none" \
|
|
||||||
# cargo +nightly build \
|
|
||||||
# -Z build-std=std,panic_abort \
|
|
||||||
# -Z build-std-features="optimize_for_size" \
|
|
||||||
# $@ \
|
|
||||||
# --profile release
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "unshell-gui"
|
name = "ush-gui"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "unshell-manager"
|
name = "ush-manager"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
@@ -8,7 +8,7 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use unshell::unshell_obfuscate::symbol;
|
use unshell::obfuscate::symbol;
|
||||||
use unshell::{Result, config::RuntimeConfig, debug, warn};
|
use unshell::{Result, config::RuntimeConfig, debug, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "unshell-obfuscate"
|
name = "ush-obfuscate"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::crypt::{base62::Base62, hash};
|
use crate::crypt::{base62::Base62, hash};
|
||||||
use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
|
use aes::cipher::{BlockEncryptMut, KeyIvInit};
|
||||||
use cbc::cipher::block_padding::Pkcs7;
|
use cbc::cipher::block_padding::Pkcs7;
|
||||||
use regex::Regex;
|
|
||||||
|
|
||||||
fn pkcs7_padded_length(input_len: usize) -> usize {
|
fn pkcs7_padded_length(input_len: usize) -> usize {
|
||||||
let block_size = 16;
|
let block_size = 16;
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod aes_encrypt;
|
pub mod aes_encrypt;
|
||||||
|
#[allow(dead_code)]
|
||||||
pub mod base62;
|
pub mod base62;
|
||||||
|
|
||||||
pub const ENV_KEY_NAME: &str = "OBFUSCATION_KEY";
|
pub const ENV_KEY_NAME: &str = "OBFUSCATION_KEY";
|
||||||
@@ -25,17 +25,17 @@ use obfuscate as obs;
|
|||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn obs(input: TokenStream) -> TokenStream {
|
pub fn obs(input: TokenStream) -> TokenStream {
|
||||||
obs::obs(input)
|
obs::xor(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn obfuscated_symbol(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn obfuscated_symbol(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
obs::obfuscated_symbol(_attr, item)
|
obs::aes_fn_name(_attr, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn symbol(input: TokenStream) -> TokenStream {
|
pub fn symbol(input: TokenStream) -> TokenStream {
|
||||||
obs::symbol(input)
|
obs::aes_str(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
@@ -56,7 +56,7 @@ pub fn file_symbol(_input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
// Return as a string literal
|
// Return as a string literal
|
||||||
let output = quote! {
|
let output = quote! {
|
||||||
unshell_obfuscate::symbol!(#concatted)
|
obfuscate::symbol!(#concatted)
|
||||||
};
|
};
|
||||||
// let output = quote! {
|
// let output = quote! {
|
||||||
// #concatted
|
// #concatted
|
||||||
@@ -83,7 +83,7 @@ pub fn format_obs(input: TokenStream) -> TokenStream {
|
|||||||
match segment {
|
match segment {
|
||||||
FormatSegment::Static(text) => {
|
FormatSegment::Static(text) => {
|
||||||
parts.push(quote! {
|
parts.push(quote! {
|
||||||
unshell_obfuscate::symbol!(#text).to_string()
|
obfuscate::symbol!(#text).to_string()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
FormatSegment::Dynamic(spec, idx) => {
|
FormatSegment::Dynamic(spec, idx) => {
|
||||||
@@ -2,7 +2,7 @@ use proc_macro::TokenStream;
|
|||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{ItemFn, LitStr, parse_macro_input};
|
use syn::{ItemFn, LitStr, parse_macro_input};
|
||||||
|
|
||||||
pub fn obs(input: TokenStream) -> TokenStream {
|
pub fn xor(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as LitStr);
|
let input = parse_macro_input!(input as LitStr);
|
||||||
|
|
||||||
(quote::quote! {
|
(quote::quote! {
|
||||||
@@ -10,7 +10,7 @@ pub fn obs(input: TokenStream) -> TokenStream {
|
|||||||
})
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
pub fn obfuscated_symbol(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn aes_fn_name(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let func = parse_macro_input!(item as ItemFn);
|
let func = parse_macro_input!(item as ItemFn);
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
@@ -18,7 +18,7 @@ pub fn obfuscated_symbol(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn symbol(input: TokenStream) -> TokenStream {
|
pub fn aes_str(input: TokenStream) -> TokenStream {
|
||||||
input
|
input
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3,6 +3,7 @@ mod obs_xor;
|
|||||||
mod sym_aes_strings;
|
mod sym_aes_strings;
|
||||||
|
|
||||||
pub use obs_junk_asm::junk_asm;
|
pub use obs_junk_asm::junk_asm;
|
||||||
|
pub use obs_xor::xor;
|
||||||
pub use sym_aes_strings::*;
|
pub use sym_aes_strings::*;
|
||||||
|
|
||||||
use crate::crypt::{BACKUP_ENV_KEY, ENV_KEY_NAME};
|
use crate::crypt::{BACKUP_ENV_KEY, ENV_KEY_NAME};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
cargo-features = ["trim-paths"]
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "ush-payload"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["log"]
|
||||||
|
log = ["unshell/log"]
|
||||||
|
log_debug = ["unshell/log_debug"]
|
||||||
|
obfuscate = ["unshell/obfuscate"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
unshell.path = "../"
|
||||||
|
serde_json.workspace = true
|
||||||
@@ -1,23 +1,43 @@
|
|||||||
use unshell::{info, manager::Tree};
|
use unshell::{
|
||||||
|
Value, info,
|
||||||
// use std::dyn
|
logger::{Record, log},
|
||||||
|
obfuscate::{junk_asm, symbol},
|
||||||
|
tree::{Tree, TreeElement, symbols},
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let manager = Tree::new();
|
let mut manager = Tree::new();
|
||||||
manager.init_logger();
|
manager.init_logger();
|
||||||
|
|
||||||
|
info!("Test thing!");
|
||||||
info!("Test thing!");
|
info!("Test thing!");
|
||||||
|
|
||||||
println!("Recieved logs: {}", manager.log_count());
|
loop {
|
||||||
|
if test123(&mut manager) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// unshell::logger::
|
// println!("Test");
|
||||||
|
|
||||||
// server2::log_test_fn();
|
|
||||||
// info!("This is a string!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test23() -> (i32, i32) {
|
fn test123(manager: &mut Tree) -> bool {
|
||||||
(6, 3)
|
let result = manager.send_message(
|
||||||
|
Value::String(symbol!("Logger").to_string()),
|
||||||
|
Value::String(symbols::CMD_GET.to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
|
junk_asm!(20.);
|
||||||
|
|
||||||
|
let is_null = result.is_null();
|
||||||
|
|
||||||
|
if let Ok(result) = serde_json::from_value::<Record>(result) {
|
||||||
|
log(&result);
|
||||||
|
}
|
||||||
|
|
||||||
|
is_null
|
||||||
|
|
||||||
|
// println!("Logger: {}", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// use std::{any::Any, collections::HashMap, fs::File, io::Read};
|
// use std::{any::Any, collections::HashMap, fs::File, io::Read};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "unshell-server"
|
name = "ush-server"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
@@ -7,12 +7,12 @@ include.workspace = true
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["log_debug"]
|
default = ["log_debug"]
|
||||||
log = ["unshell/log", "unshell-manager/log"]
|
log = ["unshell/log"]
|
||||||
log_debug = ["unshell/log_debug", "unshell-manager/log_debug"]
|
log_debug = ["unshell/log_debug"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
unshell = { path = "../" }
|
unshell = { path = "../" }
|
||||||
unshell-manager = { path = "../unshell-manager" }
|
# ush-manager = { path = "../unshell-manager" }
|
||||||
|
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
toml = { workspace = true }
|
toml = { workspace = true }
|
||||||
Reference in New Issue
Block a user