mirror of
https://github.com/Astatin3/unshell-nodes-rs.git
synced 2026-06-08 16:18:08 -06:00
Move files around, add UI
This commit is contained in:
+9
-2
@@ -1,10 +1,17 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "unshell-rs"
|
name = "server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.22.1"
|
clap = { version = "4.5.39", features = ["derive"] }
|
||||||
log = "0.4.27"
|
log = "0.4.27"
|
||||||
|
pretty_env_logger = "0.5.0"
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_json = "1.0.140"
|
serde_json = "1.0.140"
|
||||||
|
slint = "1.11.0"
|
||||||
|
unshell-rs-lib = { path = "./unshell-rs-lib" }
|
||||||
|
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
slint-build = "1.11.0"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
- Probably out of scope
|
- Probably out of scope
|
||||||
- Build targets
|
- Build targets
|
||||||
- To achieve a minimal size, there should probably be a way to pack diffrent features with the actual result binary.
|
- To achieve a minimal size, there should probably be a way to pack diffrent features with the actual result binary.
|
||||||
|
- There should also be a way to update one of the hosts with the new functionality.
|
||||||
|
|
||||||
### Network
|
### Network
|
||||||
- Diffrent traffic obfuscators:
|
- Diffrent traffic obfuscators:
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
slint_build::compile("ui/app-window.slint").expect("Slint build failed");
|
||||||
|
}
|
||||||
+2
-1
@@ -4,5 +4,6 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
serde_json = "1.0.140"
|
||||||
# libc = "0.2.172"
|
# libc = "0.2.172"
|
||||||
unshell-rs = { path = "../" }
|
unshell-rs-lib = { path = "../unshell-rs-lib" }
|
||||||
|
|||||||
+55
-11
@@ -2,20 +2,64 @@
|
|||||||
// mod execute;
|
// mod execute;
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use unshell_rs::{
|
|
||||||
networkers::{TCPClient, TCPConnection},
|
use std::{
|
||||||
payload::run_client,
|
sync::{Arc, Mutex},
|
||||||
|
thread,
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
// /// Pipe streams are blocking, we need separate threads to monitor them without blocking the primary thread.
|
use unshell_rs_lib::{
|
||||||
// fn child_stream_to_vec<R>(mut stream: R) -> Arc<Mutex<Vec<u8>>>
|
networkers::{ClientTrait, Connection, TCPClient, TCPConnection},
|
||||||
// where
|
packets::Packet,
|
||||||
// R: Read + Send + 'static,
|
};
|
||||||
// {
|
|
||||||
// let out = Arc::new(Mutex::new(Vec::new()));
|
|
||||||
// let vec = out.clone();
|
|
||||||
|
|
||||||
// }
|
// Generic client function
|
||||||
|
pub fn run_client<C, Cl>(address: &str) -> Result<(), Box<dyn std::error::Error>>
|
||||||
|
where
|
||||||
|
Cl: ClientTrait<C>,
|
||||||
|
C: Connection + 'static,
|
||||||
|
Cl::Error: std::error::Error + 'static,
|
||||||
|
C::Error: std::error::Error + 'static,
|
||||||
|
{
|
||||||
|
let recv_conn = Arc::new(Mutex::new(Cl::connect(address)?));
|
||||||
|
let transmit_vec: Arc<Mutex<Vec<Packet>>> = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
|
||||||
|
let transmit_conn = Arc::clone(&recv_conn);
|
||||||
|
let transmit_vec_clone = Arc::clone(&transmit_vec);
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
let mut transmit_vec_lock = transmit_vec.lock().unwrap();
|
||||||
|
if transmit_vec_lock.len() > 0 {
|
||||||
|
let mut conn_lock = recv_conn.lock().unwrap();
|
||||||
|
if let Ok(json) = serde_json::to_string(&transmit_vec_lock.pop().unwrap()) {
|
||||||
|
conn_lock.write(&json).expect("Failed to send packet!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
thread::sleep(Duration::from_millis(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut conn_lock = transmit_conn.lock().unwrap();
|
||||||
|
let data = conn_lock.read();
|
||||||
|
drop(conn_lock);
|
||||||
|
match data {
|
||||||
|
Ok(data_json) => {
|
||||||
|
if data_json.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let packet = serde_json::from_str::<Packet>(data_json.as_str());
|
||||||
|
println!("{:?}", packet);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error reading, {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
run_client::<TCPConnection, TCPClient>("127.0.0.1:3000")?;
|
run_client::<TCPConnection, TCPClient>("127.0.0.1:3000")?;
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "server"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
unshell-rs = { path = "../" }
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
use std::error::Error;
|
|
||||||
|
|
||||||
use unshell_rs::{
|
|
||||||
listeners::Listener,
|
|
||||||
networkers::{ServerTrait, TCPServer},
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
|
||||||
let mut server = Listener::new(TCPServer::bind("0.0.0.0:3000")?);
|
|
||||||
|
|
||||||
server.run_listener()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
use slint::{ModelRc, VecModel};
|
||||||
|
use std::error::Error;
|
||||||
|
use unshell_rs_lib::config::listeners::ListenerConfig;
|
||||||
|
|
||||||
|
pub struct Unshell_Gui;
|
||||||
|
|
||||||
|
slint::include_modules!();
|
||||||
|
impl Unshell_Gui {
|
||||||
|
pub fn start() -> Result<Self, Box<dyn Error>> {
|
||||||
|
let ui = AppWindow::new()?;
|
||||||
|
|
||||||
|
// ui.
|
||||||
|
|
||||||
|
let ui_handle = ui.as_weak();
|
||||||
|
ui.on_tab_clicked(move |index| {
|
||||||
|
let ui = ui_handle.unwrap();
|
||||||
|
ui.set_current_tab(index);
|
||||||
|
trace!("Tab {} selected", index);
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.set_app_info({
|
||||||
|
(String::new()
|
||||||
|
+ "Unshell\n"
|
||||||
|
+ "Version "
|
||||||
|
+ env!("CARGO_PKG_VERSION")
|
||||||
|
+ "\n\n View the source code at:\n https://github.com/astatin3/unshell-rs")
|
||||||
|
.into()
|
||||||
|
});
|
||||||
|
|
||||||
|
let listeners: Vec<ListenerConfig> = vec![ListenerConfig::Tcp {
|
||||||
|
enabled: true,
|
||||||
|
name: "test".to_string(),
|
||||||
|
remote_host: "127.0.0.1".to_string(),
|
||||||
|
port: 25565,
|
||||||
|
layers: Vec::new(),
|
||||||
|
}];
|
||||||
|
|
||||||
|
ui.set_listeners(ModelRc::new(VecModel::from(
|
||||||
|
listeners
|
||||||
|
.iter()
|
||||||
|
.map(|l| match l {
|
||||||
|
ListenerConfig::Tcp {
|
||||||
|
enabled,
|
||||||
|
name,
|
||||||
|
remote_host,
|
||||||
|
port,
|
||||||
|
layers,
|
||||||
|
} => UITcpListener {
|
||||||
|
enabled: *enabled,
|
||||||
|
name: name.clone().into(),
|
||||||
|
remote_host: remote_host.clone().into(),
|
||||||
|
port: *port as i32,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.collect::<Vec<UITcpListener>>(),
|
||||||
|
)));
|
||||||
|
|
||||||
|
ui.run()?;
|
||||||
|
|
||||||
|
Ok(Self {})
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
pub mod layers;
|
#[macro_use]
|
||||||
pub mod listeners;
|
extern crate log;
|
||||||
pub mod networkers;
|
|
||||||
pub mod packets;
|
mod gui;
|
||||||
pub mod payload;
|
mod server;
|
||||||
|
|||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use clap::{Parser, Subcommand};
|
||||||
|
use log::trace;
|
||||||
|
use slint::{ModelRc, VecModel};
|
||||||
|
use unshell_rs_lib::{
|
||||||
|
config::listeners::ListenerConfig,
|
||||||
|
listeners::Listener,
|
||||||
|
networkers::{ServerTrait, TCPServer},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The default port that this program looks for
|
||||||
|
pub static DEFAULT_SERVICE_PORT: u16 = 13370;
|
||||||
|
/// The default website port that this program looks for
|
||||||
|
pub static DEFAULT_WEB_PORT: u16 = 8082;
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
#[command(name = "unshell-rs")]
|
||||||
|
#[command(about = "Slick reverse shell tool in rust", long_about = None)]
|
||||||
|
struct Args {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: Commands,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Subcommand)]
|
||||||
|
enum Commands {
|
||||||
|
/// Run as a service, and potentially hosting a website
|
||||||
|
#[command(arg_required_else_help = true)]
|
||||||
|
Serve {
|
||||||
|
/// Only listen for command clients locally
|
||||||
|
#[arg(short, long, default_value_t = false)]
|
||||||
|
local: bool,
|
||||||
|
|
||||||
|
/// Port listen to for command clients
|
||||||
|
#[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
|
||||||
|
service_port: u16,
|
||||||
|
// /// Port to listen for website traffic (0 is disabled)
|
||||||
|
// #[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
|
||||||
|
// web_port: u16,
|
||||||
|
},
|
||||||
|
Gui {
|
||||||
|
/// Listen for command clients remotely aswell
|
||||||
|
#[arg(short, long, default_value_t = true)]
|
||||||
|
remote: bool,
|
||||||
|
|
||||||
|
/// Port listen to for command clients
|
||||||
|
#[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
|
||||||
|
service_port: u16,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
pretty_env_logger::init();
|
||||||
|
let args = Args::parse();
|
||||||
|
|
||||||
|
match args.command {
|
||||||
|
Commands::Gui {
|
||||||
|
remote,
|
||||||
|
service_port,
|
||||||
|
} => {}
|
||||||
|
Commands::Serve {
|
||||||
|
local,
|
||||||
|
service_port,
|
||||||
|
// web_port,
|
||||||
|
} => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// let mut server = Listener::new(TCPServer::bind("0.0.0.0:3000")?);
|
||||||
|
|
||||||
|
// server.run_listener()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
use std::{
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
thread,
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
networkers::{ClientTrait, Connection},
|
|
||||||
packets::Packet,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generic client function
|
|
||||||
pub fn run_client<C, Cl>(address: &str) -> Result<(), Box<dyn std::error::Error>>
|
|
||||||
where
|
|
||||||
Cl: ClientTrait<C>,
|
|
||||||
C: Connection + 'static,
|
|
||||||
Cl::Error: std::error::Error + 'static,
|
|
||||||
C::Error: std::error::Error + 'static,
|
|
||||||
{
|
|
||||||
let recv_conn = Arc::new(Mutex::new(Cl::connect(address)?));
|
|
||||||
let transmit_vec: Arc<Mutex<Vec<Packet>>> = Arc::new(Mutex::new(Vec::new()));
|
|
||||||
|
|
||||||
let transmit_conn = Arc::clone(&recv_conn);
|
|
||||||
let transmit_vec_clone = Arc::clone(&transmit_vec);
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
loop {
|
|
||||||
let mut transmit_vec_lock = transmit_vec.lock().unwrap();
|
|
||||||
if transmit_vec_lock.len() > 0 {
|
|
||||||
let mut conn_lock = recv_conn.lock().unwrap();
|
|
||||||
if let Ok(json) = serde_json::to_string(&transmit_vec_lock.pop().unwrap()) {
|
|
||||||
conn_lock.write(&json).expect("Failed to send packet!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
thread::sleep(Duration::from_millis(10));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let mut conn_lock = transmit_conn.lock().unwrap();
|
|
||||||
let data = conn_lock.read();
|
|
||||||
drop(conn_lock);
|
|
||||||
match data {
|
|
||||||
Ok(data_json) => {
|
|
||||||
if data_json.is_empty() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let packet = serde_json::from_str::<Packet>(data_json.as_str());
|
|
||||||
println!("{:?}", packet);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error reading, {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop {
|
|
||||||
// let mut input = String::new();
|
|
||||||
// stdin.read_line(&mut input)?;
|
|
||||||
// let input = input.trim();
|
|
||||||
|
|
||||||
// if input == "quit" {
|
|
||||||
// conn.write(input)?;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if !input.is_empty() {
|
|
||||||
// conn.write(input)?;
|
|
||||||
|
|
||||||
// match conn.read() {
|
|
||||||
// Ok(response) => println!("Server: {}", response),
|
|
||||||
// Err(e) => {
|
|
||||||
// eprintln!("Failed to read response: {:?}", e);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
import { Button, HorizontalBox, VerticalBox, Slider, StandardButton } from "std-widgets.slint";
|
||||||
|
import { DashboardPage } from "pages/dashboard.slint";
|
||||||
|
import { ListenersPage } from "pages/listeners.slint";
|
||||||
|
import { ClientsPage } from "pages/clients.slint";
|
||||||
|
import { ToolsPage } from "pages/tools.slint";
|
||||||
|
import { UITcpListener } from "structs.slint";
|
||||||
|
import { BorderedRectangle } from "components.slint";
|
||||||
|
|
||||||
|
component SideButton inherits Button {
|
||||||
|
in property <length> sidebar_size: 40px;
|
||||||
|
|
||||||
|
preferred-width: sidebar_size;
|
||||||
|
height: sidebar_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
export component AppWindow inherits Window {
|
||||||
|
|
||||||
|
in-out property <int> current-tab: 0;
|
||||||
|
in-out property <[UITcpListener]> listeners;
|
||||||
|
|
||||||
|
in-out property <string> app-info;
|
||||||
|
|
||||||
|
callback tab-clicked(int);
|
||||||
|
|
||||||
|
tab-clicked(index) => {
|
||||||
|
current-tab = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// background: @linear-gradient(20deg, #1a161d 0%, #27222a 100%);
|
||||||
|
MenuBar {
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
title: @tr("File");
|
||||||
|
MenuItem {
|
||||||
|
title: @tr("New");
|
||||||
|
activated => {
|
||||||
|
// file-new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
title: @tr("Open");
|
||||||
|
activated => {
|
||||||
|
// file-open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
title: @tr("Edit");
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
title: @tr("Copy");
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
title: @tr("Paste");
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuSeparator { }
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
title: @tr("Find");
|
||||||
|
MenuItem {
|
||||||
|
title: @tr("Find in document...");
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
title: @tr("Find Next");
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
title: @tr("Find Previous");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback request-increase-value();
|
||||||
|
HorizontalLayout {
|
||||||
|
|
||||||
|
BorderedRectangle {
|
||||||
|
VerticalLayout {
|
||||||
|
spacing: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Unshell";
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 1000;
|
||||||
|
horizontal-alignment: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
for entry[i] in [
|
||||||
|
{ name: "Dashboard" },
|
||||||
|
{ name: "Listeners" },
|
||||||
|
{ name: "Clients" },
|
||||||
|
{ name: "Tools" },
|
||||||
|
]: SideButton {
|
||||||
|
text: entry.name;
|
||||||
|
|
||||||
|
clicked => {
|
||||||
|
root.tab-clicked(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Strechy
|
||||||
|
Rectangle { }
|
||||||
|
|
||||||
|
SideButton {
|
||||||
|
text: "Info";
|
||||||
|
|
||||||
|
clicked => {
|
||||||
|
info-window.visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text {
|
||||||
|
// text: "Counter: \{root.counter}";
|
||||||
|
// }
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
|
||||||
|
if current-tab == 0: DashboardPage { }
|
||||||
|
if current-tab == 1: ListenersPage {
|
||||||
|
listeners: listeners;
|
||||||
|
}
|
||||||
|
if current-tab == 2: ClientsPage { }
|
||||||
|
if current-tab == 3: ToolsPage { }
|
||||||
|
}
|
||||||
|
|
||||||
|
callback file-new();
|
||||||
|
callback file-open();
|
||||||
|
}
|
||||||
|
|
||||||
|
info-window := Dialog {
|
||||||
|
visible: false;
|
||||||
|
|
||||||
|
BorderedRectangle {
|
||||||
|
VerticalLayout {
|
||||||
|
padding: 10px;
|
||||||
|
spacing: 10px;
|
||||||
|
|
||||||
|
Text {
|
||||||
|
font-size: 20px;
|
||||||
|
text: app-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardButton {
|
||||||
|
kind: ok;
|
||||||
|
clicked => {
|
||||||
|
info-window.visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
export component BorderedRectangle inherits Rectangle {
|
||||||
|
background: #2a232a;
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: darkslateblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
export component BoolText inherits Text {
|
||||||
|
in property <bool> state;
|
||||||
|
|
||||||
|
text: state ? "TRUE" : "FALSE";
|
||||||
|
color: state ? #00ff00 : #ff0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
export component TitleText inherits HorizontalLayout {
|
||||||
|
in property <string> text;
|
||||||
|
|
||||||
|
alignment: start;
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: text;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@children
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { VerticalBox } from "std-widgets.slint";
|
||||||
|
export component Page inherits VerticalBox {
|
||||||
|
padding: 20px;
|
||||||
|
alignment: start;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { Page } from "../page.slint";
|
||||||
|
|
||||||
|
export component ClientsPage inherits Page {
|
||||||
|
Text {
|
||||||
|
text: "Clients";
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { Page } from "../page.slint";
|
||||||
|
|
||||||
|
export component DashboardPage inherits Page { }
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { Page } from "../page.slint";
|
||||||
|
import { UITcpListener } from "../structs.slint";
|
||||||
|
import { ScrollView, GridBox, Button } from "std-widgets.slint";
|
||||||
|
import { BorderedRectangle, BoolText, TitleText } from "../components.slint";
|
||||||
|
|
||||||
|
|
||||||
|
component ListenerCard inherits BorderedRectangle {
|
||||||
|
in property <UITcpListener> listener;
|
||||||
|
|
||||||
|
VerticalLayout {
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: listener.name;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
TitleText {
|
||||||
|
text: "Enabled: ";
|
||||||
|
BoolText {
|
||||||
|
state: listener.enabled;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TitleText {
|
||||||
|
text: "Remote Host: ";
|
||||||
|
Text {
|
||||||
|
text: listener.remote-host;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TitleText {
|
||||||
|
text: "Port: ";
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: listener.port;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export component ListenersPage inherits Page {
|
||||||
|
in-out property <[UITcpListener]> listeners;
|
||||||
|
|
||||||
|
ScrollView {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
VerticalLayout {
|
||||||
|
|
||||||
|
for listener[i] in listeners: ListenerCard {
|
||||||
|
listener: listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { Page } from "../page.slint";
|
||||||
|
|
||||||
|
export component ToolsPage inherits Page { }
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export struct UITcpListener {
|
||||||
|
enabled: bool,
|
||||||
|
name: string,
|
||||||
|
remote_host: string,
|
||||||
|
port: int,
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
[package]
|
||||||
|
name = "unshell-rs-lib"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
base64 = "0.22.1"
|
||||||
|
log = "0.4.27"
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
serde_json = "1.0.140"
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct CampignConfig {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum LayerConfig {}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::config::layers::LayerConfig;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum ListenerConfig {
|
||||||
|
Tcp {
|
||||||
|
enabled: bool,
|
||||||
|
name: String,
|
||||||
|
remote_host: String,
|
||||||
|
port: u16,
|
||||||
|
layers: Vec<LayerConfig>,
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod campaign;
|
||||||
|
pub mod layers;
|
||||||
|
pub mod listeners;
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
use crate::layers::Layer;
|
use crate::layers::Layer;
|
||||||
use base64;
|
use base64;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default, Serialize, Deserialize)]
|
||||||
pub struct Base64;
|
pub struct Base64;
|
||||||
|
|
||||||
impl Layer for Base64 {
|
impl Layer for Base64 {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
pub trait Layer {
|
pub trait Layer: Serialize + Deserialize<'static> + Sized {
|
||||||
fn encode(&mut self, data: &[u8]) -> Vec<u8>;
|
fn encode(&mut self, data: &[u8]) -> Vec<u8>;
|
||||||
fn decode(&mut self, data: &[u8]) -> Vec<u8>;
|
fn decode(&mut self, data: &[u8]) -> Vec<u8>;
|
||||||
}
|
}
|
||||||
@@ -6,3 +6,4 @@ pub trait Layer {
|
|||||||
pub mod base64;
|
pub mod base64;
|
||||||
|
|
||||||
pub use base64::Base64;
|
pub use base64::Base64;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
|
pub mod config;
|
||||||
|
pub mod layers;
|
||||||
|
pub mod listeners;
|
||||||
|
pub mod networkers;
|
||||||
|
pub mod packets;
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::layers::Layer;
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
mod server;
|
mod server;
|
||||||
|
|
||||||
@@ -1,15 +1,8 @@
|
|||||||
use log::{info, trace, warn};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use std::{
|
|
||||||
io::{self, Write},
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
thread,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
listeners::client::{self, Client},
|
listeners::client::Client,
|
||||||
networkers::{Connection, ServerTrait},
|
networkers::{Connection, ServerTrait},
|
||||||
packets::Packet,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Listener<S, C> {
|
pub struct Listener<S, C> {
|
||||||
@@ -41,7 +34,7 @@ impl<S, C> Listener<S, C> {
|
|||||||
clients_lock.push(Client::new(conn));
|
clients_lock.push(Client::new(conn));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Failed to accept connection: {:?}", e);
|
error!("Failed to accept connection: {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user