binary data transfer, begin CLI, packet routing

This commit is contained in:
Michael Mikovsky
2025-06-12 05:44:54 -06:00
parent aea44b75a2
commit d7f350bd40
21 changed files with 457 additions and 260 deletions
+55 -25
View File
@@ -1,21 +1,29 @@
use std::{io::Write, net::SocketAddr};
use unshell_rs_lib::{
Error,
connection::{ConnectionConfig, Node},
nodes::{ConnectionConfig, Node},
};
use crate::C2Packet;
pub struct Cli;
impl Cli {
pub fn connect(
id: String,
clients: Vec<ConnectionConfig>,
listeners: Vec<ConnectionConfig>,
) -> Result<(), Error> {
pub fn connect(socket: SocketAddr) -> Result<(), Error> {
// let mut client = build_client(TCPClient::connect(&addr)?, vec![])?;
// let stdin = std::io::stdin();
// let mut stdout = std::io::stdout();
let stdin = std::io::stdin();
let mut stdout = std::io::stdout();
Node::run_node(id, clients, listeners)
let node = Node::<C2Packet>::run_node(
"Client".to_string(),
vec![ConnectionConfig {
socket,
layers: vec![],
}],
vec![],
)?;
// let mut client_clone = client.try_clone()?;
// thread::spawn(move || {
@@ -48,24 +56,46 @@ impl Cli {
// }
// });
// loop {
// print!("> ");
// stdout.flush()?;
let selected_node: Option<usize> = None;
// let mut input = String::new();
// stdin.read_line(&mut input)?;
// let input = input.trim();
loop {
print!("> ");
stdout.flush()?;
// match input.split(" ").nth(0).unwrap() {
// "ping" => {
// // client.write(Packets::GetConnections.encode()?.as_str())?;
// }
// _ => {
// warn!("Invalid command!")
// }
// }
let mut input = String::new();
stdin.read_line(&mut input)?;
let input = input.trim();
// // client.write(input)?;
// }
let mut node_state = node.state.lock().unwrap();
let mut split = input.split(" ");
match split.next().unwrap() {
"nodes" => {
for (i, node) in node_state.get_all_nodes().iter().enumerate() {
println!("{} -> {}", i, node);
}
}
"ping" => {
// if split.count().clone() <= 1 {
// warn!("You must specify an option");
// continue;
// }
if let Ok(i) = str::parse::<usize>(split.next().unwrap()) {
let nodes = node_state.get_all_nodes();
let node = nodes.get(i).unwrap().clone();
node_state.send_unrouted(node, &C2Packet::Aa).unwrap();
} else {
println!("");
}
}
_ => {
warn!("Invalid command!")
}
}
// client.write(input)?;
}
}
}
+33
View File
@@ -0,0 +1,33 @@
use std::net::SocketAddr;
use unshell_rs_lib::{
Error,
nodes::{ConnectionConfig, Node},
};
use crate::C2Packet;
pub fn run_endpoint(socket: SocketAddr) -> Result<(), Error> {
let node = Node::<C2Packet>::run_node(
"Server".to_string(),
vec![],
vec![ConnectionConfig {
socket,
layers: vec![],
}],
)?;
loop {
match node.rx.recv()? {
C2Packet::Aa => {
info!("1");
}
C2Packet::Bb => {
info!("2");
}
C2Packet::Cc => {
info!("3");
}
}
}
}
+3
View File
@@ -0,0 +1,3 @@
mod endpoint;
pub use endpoint::run_endpoint;
+6 -2
View File
@@ -1,11 +1,15 @@
// #[macro_use]
#[macro_use]
extern crate log;
mod client;
// mod server;
mod endpoint;
mod packets;
pub use client::Cli;
pub use endpoint::run_endpoint;
pub use packets::C2Packet;
// pub use client::UnshellClient;
// pub use client::UnshellGui;
// pub use server::UnshellServer;
+114 -115
View File
@@ -7,8 +7,8 @@ use std::{
use clap::{Parser, Subcommand};
use log::error;
use unshell_rs::Cli;
use unshell_rs_lib::connection::ConnectionConfig;
use unshell_rs::{Cli, run_endpoint};
use unshell_rs_lib::nodes::ConnectionConfig;
pub static DEFAULT_CONFIG_FILEPATH: &'static str = "server_config.json";
@@ -30,42 +30,32 @@ struct Args {
#[derive(Debug, Subcommand)]
enum Commands {
// Start,
// Middle,
// End,
//
Test1,
Test2,
Test3,
Test4,
Test5,
Test6,
// Run as a service, and potentially hosting a website
// #[command(arg_required_else_help = true)]
// Relay {
// /// IPv4 to listen for clients on.
// host: String,
Relay {
/// IPv4 to listen for clients on.
#[arg(short, long, default_value_t = ("0.0.0.0".to_string()))]
host: String,
// /// Port listen to for command clients
// #[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
// port: u16,
/// Port listen to for command clients
#[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
port: u16,
// /// Json file to store config
// #[arg(short, long, default_value_t = DEFAULT_CONFIG_FILEPATH.to_string())]
// config_filepath: String,
// // /// Port to listen for website traffic (0 is disabled)
// // #[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
// // web_port: u16,
// },
// /// Connect to remote server
// Connect {
// /// Remote server to connect to
// host: String,
/// Json file to store config
#[arg(short, long, default_value_t = DEFAULT_CONFIG_FILEPATH.to_string())]
config_filepath: String,
// /// Port to listen for website traffic (0 is disabled)
// #[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
// web_port: u16,
},
/// Connect to remote server
Connect {
/// Remote server to connect on
host: String,
// /// Port listen to for command clients
// #[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
// port: u16,
// },
#[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
/// Port listen to for command clients
port: u16,
},
}
fn main() -> Result<(), Box<dyn Error>> {
@@ -83,87 +73,96 @@ fn main() -> Result<(), Box<dyn Error>> {
// error!("{}", e);
// }
// }
Commands::Test1 {} => Cli::connect(
"Test1".to_string(),
vec![],
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13371")?,
layers: vec![],
}],
),
Commands::Test2 {} => Cli::connect(
"Test2".to_string(),
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13371")?,
layers: vec![],
}],
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13372")?,
layers: vec![],
}],
),
Commands::Test3 {} => Cli::connect(
"Test3".to_string(),
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13372")?,
layers: vec![],
}],
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13373")?,
layers: vec![],
}],
),
Commands::Test4 {} => Cli::connect(
"Test4".to_string(),
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13371")?,
layers: vec![],
}],
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13374")?,
layers: vec![],
}],
),
Commands::Test5 {} => Cli::connect(
"Test5".to_string(),
vec![
ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13372")?,
layers: vec![],
},
ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13374")?,
layers: vec![],
},
],
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13375")?,
layers: vec![],
}],
),
Commands::Test6 {} => Cli::connect(
"Test6".to_string(),
vec![
ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13373")?,
layers: vec![],
},
ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13375")?,
layers: vec![],
},
],
vec![],
),
// Commands::Connect { host, port } => {
// let addr = SocketAddr::from_str(format!("{}:{}", host, port).as_str());
// Cli::connect(if let Ok(addr) = addr {
// addr
// } else {
// error!("Could not parse address!");
// return Ok(());
// })
// }
// Commands::Test1 {} => Cli::connect(
// "Test1".to_string(),
// vec![],
// vec![ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13371")?,
// layers: vec![],
// }],
// ),
// Commands::Test2 {} => Cli::connect(
// "Test2".to_string(),
// vec![ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13371")?,
// layers: vec![],
// }],
// vec![ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13372")?,
// layers: vec![],
// }],
// ),
// Commands::Test3 {} => Cli::connect(
// "Test3".to_string(),
// vec![ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13372")?,
// layers: vec![],
// }],
// vec![],
// ), // Commands::Test4 {} => Cli::connect(
// "Test4".to_string(),
// vec![ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13371")?,
// layers: vec![],
// }],
// vec![ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13374")?,
// layers: vec![],
// }],
// ),
// Commands::Test5 {} => Cli::connect(
// "Test5".to_string(),
// vec![
// ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13372")?,
// layers: vec![],
// },
// ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13374")?,
// layers: vec![],
// },
// ],
// vec![ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13375")?,
// layers: vec![],
// }],
// ),
// Commands::Test6 {} => Cli::connect(
// "Test6".to_string(),
// vec![
// ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13373")?,
// layers: vec![],
// },
// ConnectionConfig {
// socket: SocketAddr::from_str("127.0.0.1:13375")?,
// layers: vec![],
// },
// ],
// vec![],
// ),
Commands::Connect { host, port } => {
let addr = SocketAddr::from_str(format!("{}:{}", host, port).as_str());
Cli::connect(if let Ok(addr) = addr {
addr
} else {
error!("Could not parse address!");
return Ok(());
})
}
Commands::Relay {
host,
port,
config_filepath,
} => {
let addr = SocketAddr::from_str(format!("{}:{}", host, port).as_str());
run_endpoint(if let Ok(addr) = addr {
addr
} else {
error!("Could not parse address!");
return Ok(());
})
}
} {
error!("{}", e);
};
-3
View File
@@ -1,3 +0,0 @@
mod cli;
pub use cli::Cli;
+8
View File
@@ -0,0 +1,8 @@
use bincode::{Decode, Encode};
#[derive(Debug, Encode, Decode, Clone)]
pub enum C2Packet {
Aa,
Bb,
Cc,
}