#rdp #security #networking #windows

bin+lib rdp-rs-2

纯 Rust 实现的远程桌面协议

2 个版本

使用旧的 Rust 2015

0.1.2 2023 年 3 月 15 日
0.1.1 2022 年 9 月 21 日

#1 in #rdp

MIT 许可证

300KB
5K SLoC

rdp-rs

RUST 中的远程桌面协议

API Docs Build Status LICENSE Downloads

rdp-rs 是 Microsoft 远程桌面协议的纯 Rust 实现。 rdp-rsmstsc-rs 客户端实现一起提供。

此软件包侧重于安全性,面向希望使用安全客户端的用户或想要研究 RDP 的安全研究人员。

为什么?

一方面,远程桌面协议是一个复杂的协议,很难轻松地与之交互。我已经在 PythonJavaScript 中实现了 RDP,并使用事件驱动模式。这种模式似乎增加了库的复杂性,最终出现了许多错误,没有 PR,没有人能够深入地玩 RDP。

另一方面,没有开源的 RDP 协议安全实现。

最终,我想要构建一个高度安全、跨平台且高度可定制的客户端。

安装

要在项目中使用 rdp-rs 作为库,请在 Cargo.toml 中添加以下内容:

[dependencies]
rdp-rs = "0.1.0"

您可以通过 cargo 安装二进制文件

cargo install rdp-rs --features=mstsc-rs
mstsc-rs --help

对于 Windows 平台,在 发布 会话中提供了一些预构建的二进制文件。

使用 mstsc-rs

mstsc-rs 是基于 rdp-rs 软件包的 RDP 客户端。它是跨平台且高度可定制的。

mstsc-rs 0.1.0
Sylvain Peyrefitte <citronneur@gmail.com>
Secure Remote Desktop Client in RUST

USAGE:
    mstsc-rs.exe [FLAGS] [OPTIONS]

FLAGS:
        --admin      Restricted admin mode
        --auto       AutoLogon mode in case of SSL nego
        --blank      Do not send credentials at the last CredSSP payload
        --check      Check the target SSL certificate
        --ssl        Disable Netwoek Level Authentication and only use SSL
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --dom <domain>       Windows domain [default: ]
        --hash <hash>        NTLM Hash
        --height <height>    Screen height [default: 600]
        --layout <layout>    Keyboard layout: us or fr [default: us]
        --name <name>        Name of the client send to the server [default: mstsc-rs]
        --pass <password>    Password [default: ]
        --port <port>        Destination Port [default: 3389]
        --target <target>    Target IP of the server
        --user <username>    Username [default: ]
        --width <width>      Screen width [default: 800]

mstsc-rs 已测试过连接到从 Windows 7 到 Windows 10 运行的服务器。

基本连接(使用 SSL 之上的网络级别身份验证)

默认情况下,mstsc-rs 使用 NLA 作为身份验证协议

mstsc-rs --target IP --user foo --pass bar --dom enterprise

基本连接(使用无 NLA 的 SSL)

您可以使用 ssl 选项禁用 nla,但如果您想使用凭据登录,则需要指定 auto 选项

mstsc-rs --target IP --user foo --pass bar --ssl --auto

传递哈希(使用受限管理员模式)

微软最近为 NLA 身份验证添加了一些新功能。其中之一是受限管理员模式。此模式允许管理员使用 Network 身份验证作为 Interactive 身份验证。此模式允许管理员仅通过其 NTLM 哈希进行身份验证。

mstsc-rs --target IP --user foo --hash a4c37e22527cc1479a8d620d2953b6c0 --admin

检查已登录的用户

在某些情况下,为了进行NLA(网络登录身份验证),使用SSL非常有用。当服务器不强制执行NLA时,使用SSL可以查看哪些用户已连接到服务器,而不会窃取会话。

mstsc-rs --target IP --ssl

当强制执行NLA时,您可以通过使用blank选项发送空白凭据来检查已打开或可用的会话,通过Interactive身份验证发送空白凭据。

mstsc-rs --target IP --user foo --pass bar --blank

篡改客户端名称

RDP客户端发送客户端名称。`mstsc-rs`允许用户自定义它。

mstsc-rs --target IP --user foo --pass bar --name mstsc

将LogonType=10篡改为LogonType=7

当您在一个NLA会话中将blank选项和auto选项混合时,这将导致在没有发出4624的情况下进行登录,使用LogonType=10,但使用LogonType=7

mstsc-rs --target IP --user foo --pass bar --blank --auto

玩转`rdp-rs`组件

`rdp-rs`被设计成可以轻松集成到Rust环境中。

如果您想使用常规凭据和NLA进行连接

use std::net::{SocketAddr, TcpStream};
use rdp::core::client::Connector;
use rdp::core::event::{RdpEvent, PointerEvent, PointerButton};
let addr = "192.168.0.1:3389".parse::<SocketAddr>().unwrap();
let tcp = TcpStream::connect(&addr).unwrap();
let mut connector = Connector::new()
    .screen(800, 600)
    .credentials("domain".to_string(), "username".to_string(), "password".to_string());
let mut client = connector.connect(tcp).unwrap();

现在您想发送一个输入,例如鼠标。

client.write(RdpEvent::Pointer(
    // Send a mouse click down at 100x100
    PointerEvent {
        x: 100 as u16,
        y: 100 as u16,
        button: PointerButton::Left,
        down: true
    }
 )).unwrap()

现在您想从服务器接收一个事件,例如位图事件。

client.read(|rdp_event| {
    match rdp_event {
        RdpEvent::Bitmap(bitmap) => {
            // do something with bitmap
        }
         _ => println!("Unhandled event")
    }
}).unwrap()

依赖项

~8-19MB
~276K SLoC