I have this code to listen on a port and get a reverse shell
fn pipe_thread<R, W>(mut r: R, mut w: W) -> std::thread::JoinHandle<()>
where
R: std::io::Read + Send + 'static,
W: std::io::Write + Send + 'static,
{
std::thread::spawn(move || {
let mut buffer = [0; 1024];
loop {
let len = r.read(&mut buffer).unwrap();
if len == 0 {
println!("Connection lost");
std::process::exit(0x0100);
}
w.write(&buffer[..len]).unwrap();
w.flush().unwrap();
}
})
}
fn listen() -> std::io::Result<()> {
let listener = std::net::TcpListener::bind(format!("{}:{}", "0.0.0.0", "55100"))?;
println!("Started listener");
let (stream, _) = listener.accept()?;
let t1 = pipe_thread(std::io::stdin(), stream.try_clone()?);
println!("Connection recieved");
let t2 = pipe_thread(stream, std::io::stdout());
t1.join().unwrap();
t2.join().unwrap();
return Ok(());
}
How would I implement rustyline in this code so if I press the up arrow inside the shell it will put the recent command as input
Basically like if I would run the program with rlwrap but have it built in inside the application
Try this:
Include this in your Cargo.toml
[dependencies]
rustyline = "8.2.0"
Main.rs
use rustyline::error::ReadlineError;
use rustyline::Cmd;
use rustyline::Editor;
use rustyline::KeyEvent;
use std::io::Write;
fn pipe_thread<R, W>(mut r: R, mut w: W) -> std::thread::JoinHandle<()>
where
R: std::io::Read + Send + 'static,
W: std::io::Write + Send + 'static,
{
std::thread::spawn(move || {
let mut buffer = [0; 1024];
loop {
let len = r.read(&mut buffer).unwrap();
if len == 0 {
println!("Connection lost");
std::process::exit(0x0100);
}
w.write(&buffer[..len]).unwrap();
w.flush().unwrap();
}
})
}
fn main() -> std::io::Result<()> {
let listener = std::net::TcpListener::bind(format!("{}:{}", "0.0.0.0", "55100"))?;
println!("Started listener");
let (mut stream, _) = listener.accept()?;
println!("Connection recieved");
let t = pipe_thread(stream.try_clone().unwrap(), std::io::stdout());
let mut rl = Editor::<()>::new();
rl.bind_sequence(KeyEvent::ctrl('R'), Cmd::HistorySearchBackward);
loop {
let readline = rl.readline(">> ");
match readline {
Ok(command) => {
rl.add_history_entry(command.as_str());
println!("{}", command);
// Clone command to increase its lifetime
let command = command.clone() + "\n";
// Send a TCP message
stream
.write(command.as_bytes())
.expect("Faild to send TCP.");
}
Err(ReadlineError::Interrupted) => {
println!("CTRL-C");
break;
}
Err(ReadlineError::Eof) => {
println!("CTRL-D");
break;
}
Err(err) => {
println!("Error: {:?}", err);
break;
}
}
}
return Ok(());
}