用于Python的RDP中间人(mitm)攻击库,能够实时或事后查看连接
PyRDP 是一个使用 Python 编写的远程桌面协议 (RDP) 中间人 (MITM) 工具和库。
它包含以下几个工具:
PyRDP 于 2018 年推出,当时我们演示了能够捕获真实的威胁行为者。该工具的开发同时考虑了渗透测试和恶意软件研究的使用场景。

PyRDP 应适用于 Python 3.7 及以上版本,支持 x86-64、ARM 和 ARM64 平台。
该工具已在 Linux(Ubuntu 20.04、22.04)、Raspberry Pi 和 Windows 上的 Python 3.7 上测试通过。尚未在 macOS 上测试。
推荐两种安装方式:使用 pipx 或使用 Docker 容器。从源码安装或自行构建 Docker 容器的方法在开发文档中有介绍。
首先,确保安装必要的包(以下针对 Ubuntu 22.04 列出,其他发行版可能需要调整)。我们提供两种类型的安装:完整版和精简版。根据您的使用场景安装相应的依赖项。```sh
sudo apt install python3 python3-pip python3-venv
build-essential python3-dev openssl
libegl1 libxcb-cursor0 libxkbcommon-x11-0 libxcb-icccm4 libxcb-keysyms1
libnotify-bin
libavcodec58 libavdevice58
sudo apt install python3 python3-pip python3-venv
build-essential python3-dev git openssl
这将安装运行PyRDP所需的依赖项。如果选择不安装GUI或视频转换依赖项,则将无法使用
`pyrdp-player`(除非使用无头模式 `--headless`)或通过 `pyrdp-convert` 生成视频输出。
请确保已安装 `pipx`。在Ubuntu 22.04上:```sh
python3 -m pip install --user pipx
python3 -m pipx ensurepath
请确保已安装 Python。 在 Windows 11 上,Windows 商店版 Python 对我而言无法正常工作。 我们建议通过 Scoop 安装 Python。```sh scoop install python # if not installed already scoop install pipx pipx ensurepath
注销并重新登录(以更新您的PATH)。
##### 其他操作系统
要在其他操作系统上安装 `pipx`,请参见此处:<https://github.com/pypa/pipx#install-pipx>
#### 安装
为了获得完整的PyRDP体验,包括QT图形界面以及将捕获转换为视频的能力:```sh
pipx install pyrdp-mitm[full]
对于设计在无头环境(服务器、树莓派)中运行的紧凑版本:```sh pipx install pyrdp-mitm
准备好开始吧!请参阅[使用说明](#using-pyrdp)。
### 使用 Docker 镜像
如果已安装并正常使用 Docker,这是最简单的安装方法。```sh
docker pull gosecure/pyrdp:latest
作为替代,我们提供了一个更精简的镜像,不含GUI和ffmpeg依赖项。这是在ARM平台上唯一提供的镜像。```sh docker pull gosecure/pyrdp:latest-slim
您可以在 [gosecure/pyrdp DockerHub 页面](https://hub.docker.com/r/gosecure/pyrdp/tags) 上找到我们所有 Docker 镜像的列表。
`latest` 标签指向最新的发布版本,而 `devel` 标签是根据我们的 `main` 分支构建的 Docker 镜像。
## 使用 PyRDP
### 使用 PyRDP 中间人攻击工具
使用 `pyrdp-mitm <ServerIP>` 或 `pyrdp-mitm <ServerIP>:<ServerPort>` 运行 MITM。
假设您有一个 RDP 服务器运行在 `192.168.1.10`,并在端口 3389 上侦听,您将运行:```sh
pyrdp-mitm 192.168.1.10
首次运行MITM时,会在当前工作目录下创建一个名为 pyrdp_output/ 的目录。
以下是该目录的示例布局:```sh
pyrdp_output/
├── certs
│ ├── WinDev2108Eval.crt
│ └── WinDev2108Eval.pem
├── files
│ ├── e91c6a5eb3ca15df5a5cb4cf4ebb6f33b2d379a3a12d7d6de8c412d4323feb4c
│ ├── b14b26b7d02c85e74ab4f0d847553b2fdfaf8bc616f7c3efcc4771aeddd55700
├── filesystems
│ ├── romantic_kalam_8214773
│ │ └── device1
│ │ └── clipboard
| └── priv-esc.exe -> ../../../files/b14b26b7d02c85e74ab4f0d847553b2fdfaf8bc616f7c3efcc4771aeddd55700
│ └── happy_stonebraker_1992243
│ ├── device1
│ └── device2
| └── Users/User/3D Objects/desktop.ini -> ../../../../../../e91c6a5eb3ca15df5a5cb4cf4ebb6f33b2d379a3a12d7d6de8c412d4323feb4c
├── logs
│ ├── crawl.json
│ ├── crawl.log
│ ├── mitm.json
│ ├── mitm.log
│ ├── mitm.log.2021-08-26
│ ├── ntlmssp.log
│ ├── player.log
│ └── ssl.log
└── replays
├── rdp_replay_20231214_01-20-28_965_happy_stonebraker_1992243.pyrdp
└── rdp_replay_20231214_00-42-24_295_romantic_kalam_8214773.pyrdp
* `certs/` 包含生成的证书,这些证书以证书的 `CN` 作为文件名存储
* `files/` 包含所有捕获的文件,并通过使用内容的 SHA-256 哈希作为文件名进行去重存储
* `filesystems/` 包含按会话 ID 分类的目标文件系统的重建。
为了节省相似会话的空间,文件是指向 `files/` 下实际文件的符号链接
* `logs/` 包含各种日志,大多数以 JSON 和纯文本两种格式存储:
* `crawl`: 文件爬虫日志
* `mitm`: 主 MITM 日志
* `ntlmssp.log`: 捕获的 NetNTLM 哈希
* `player.log`: 播放器日志
* `ssl.log`: 以与 Wireshark 兼容的格式存储的 TLS 主密钥
* `replays/` 包含所有先前记录的 PyRDP 会话,文件名中包含时间戳和会话 ID
#### 指定私钥和证书
如果密钥生成失败,或者您想使用自定义密钥和证书,您可以使用
`-c` 和 `-k` 参数:```sh
pyrdp-mitm 192.168.1.10 -k private_key.pem -c certificate.pem
网络级别身份验证(NLA)是自 Windows Vista 起可用的一项安全功能,它为 RDP 连接增加了安全性。 NLA 依赖于新的安全支持提供程序 CredSSP,有时也以该名称称呼。 强制实施 NLA 的服务器更难受到攻击。 有三种不同的策略可供使用:
如果我们拥有服务器的证书和私钥,即使强制实施了 NLA,我们也能成功地对 RDP 进行中间人攻击(MITM)。 我们在 1.0 版本发布博客文章中记录了此攻击。 提取 RDP 证书和私钥的说明可在我们的 GitHub 上找到。
拥有证书和私钥后,您只需在 pyrdp-mitm 命令行中添加以下内容,将身份验证设置为 ssp:```sh
--auth ssp -c <certificate.pem> -k <private-key.pem>
这将使得拦截启用NLA的连接成为可能。
###### 当服务器强制NLA时的备用主机重定向

当PyRDP连接到目标RDP服务器时(1),如果该服务器强制NLA,则PyRDP(2)会替换连接,转而连接到您选择的另一台主机(3)。
例如,这可用于重定向到一个已知不强制NLA的服务器,甚至重定向到攻击者控制的虚拟机。
要启用此功能,请按如下方式指定备用主机的地址和端口:```sh
--nla-redirection-host 192.168.1.12 --nla-redirection-port 3389
该功能在 PyRDP 1.1.0 中引入。
NetNTLMv2 哈希对攻击者很有用,因为它们相对容易破解,从而使攻击者能够利用合法的 RDP 访问或尝试凭证填充。
从 1.1.0 版本开始,PyRDP 能够通过 NLA (CredSSP) 连接捕获客户端的 NetNTLMv2 哈希,方法是进行协商并捕获 NTLMSSP 认证消息。
在 1.2.0 版本中,该支持得到扩展,即使我们没有服务器的证书和私钥也能工作,这意味着连接无法成功进行中间人攻击 (MITM)。
这与 Responder 对 RDP 所做的类似。
捕获到的 NetNTLMv2 哈希可以在 ntlmssp.log 日志文件中找到,其格式使得 John The Ripper 或 hashcat 等破解工具可以读取它。
该技术已在一篇博客文章中详细描述:捕获 RDP NetNTLMv2 哈希:攻击细节与技术操作指南
此功能与 --auth ssp 兼容,但与 --nla-redirection-host 不兼容。
如果你想通过 PyRDP 播放器查看实时的 RDP 连接,你需要使用 -i 和 -d 参数指定播放器监听的 IP 地址和端口。注意:端口参数是可选的,默认端口为 3000。```sh
pyrdp-mitm 192.168.1.10 -i 127.0.0.1 -d 3000
##### 当MITM在服务器上运行时连接到PyRDP查看器
如果你在服务器上运行MITM并且仍然希望查看实时的RDP连接,你应该使用
[SSH远程端口转发](https://www.booleanworld.com/guide-ssh-port-forwarding-tunnelling/)
将服务器上的一个端口转发到你机器上查看器的端口。完成后,你将`127.0.0.1`和转发的
端口作为参数传递给MITM。例如,如果服务器上的端口4000被转发到你机器上查看器的端口,
那么使用的命令将是:```sh
pyrdp-mitm 192.168.1.10 -i 127.0.0.1 -d 4000
PyRDP 支持在新连接建立时自动运行控制台命令或 PowerShell 载荷。 由于 RDP 的特性,该过程有些取巧,并非总是 100% 可靠。工作原理如下:
cmd.exe。powershell -enc <PAYLOAD> 运行。要使其工作,需要设置 3 个参数:
可以使用以下任一参数来设置要运行的载荷:
--payload,包含控制台命令的字符串--payload-powershell,包含 PowerShell 命令的字符串--payload-powershell-file,PowerShell 脚本的路径目前,PyRDP 无法检测用户何时登录。
你必须为其提供一个等待时间,之后才运行载荷。
在该时间过后,它会发送假的按键序列,并期望载荷正常运行。
为此,使用 --payload-delay 参数。延迟时间以毫秒为单位。
例如,如果你期望用户在最初 5 秒内登录,则可以使用以下参数:```sh
--payload-delay 5000
通过利用RDPDR初始化过程中交换的一些消息,可以提高准确性。
如果您有兴趣让这个功能更好用,请查看[此问题](https://github.com/GoSecure/pyrdp/issues/98)。
##### 选择何时恢复正常活动
由于没有直接的方法知道控制台何时停止运行,您必须告诉PyRDP您希望客户端的输入/输出被阻塞多长时间。我们建议您将此时间设置为预计运行有效负载的控制台可见的最大时长。换句话说,就是您预计有效负载完成所需的时间。
要设置有效负载持续时间,请使用 `--payload-duration` 参数,并指定以毫秒为单位的时间长度。
例如,如果您预计有效负载最多需要5秒才能完成,则应使用以下参数:```sh
--payload-duration 5000
这将阻止客户端的输入/输出5秒钟,以隐藏控制台并防止干扰。5秒后,输入/输出恢复正常。
运行 pyrdp-mitm --help 获取完整参数列表。
--no-downgrade该参数在蜜罐场景下运行PyRDP以避免扫描器指纹识别时很有用。当启用此开关时,PyRDP不会降级不支持的扩展,并让流量透明地通过。播放器可能无法成功重放视频流量,但以下支持的通道仍可访问:
该功能仍在开发中,目前为了建立连接,某些降级是不可避免的。以下内容当前不受此开关影响,仍将被禁用:
注意:如果最终能够重放完整会话很重要,一个好的解决方案是使用Wireshark记录原始RDP流量并保留TLS主密钥。当PyRDP增加对其他扩展的支持时,就可以从原始网络捕获中提取有效的RDP重放文件。
--transparent告诉PyRDP尝试伪造客户端的源IP地址,使服务器看到真实的IP地址而不是MITM的IP地址。此选项仅在MITM物理上充当客户端和服务器之间的网关并看到所有流量的某些场景中有用。具体示例参见此处。
注意:这需要root权限,仅在Linux上工作,并且需要手动配置防火墙以确保流量正确路由。
--no-gdi: 禁用加速图形管道PyRDP将视频降级到其支持的最新图形管道。此开关明确告诉MITM不要使用图形设备接口加速扩展来流式传输视频。此模式的优势在于显著减少高分辨率连接所需的带宽。
请注意,某些GDI绘图顺序目前尚未实现,因为它们似乎未被使用。如果您有包含任何不受支持或未测试顺序的重放,请随时与项目维护者分享,以便根据需要添加支持。(确保跟踪不包含敏感信息)
使用 pyrdp-player 运行播放器。
您可以使用菜单打开新的重放文件:文件 > 打开。
您也可以在启动播放器时打开重放文件:```sh pyrdp-player ...
#### 监听实时连接
播放器始终监听实时连接。默认情况下,监听端口为3000,但可以更改:```sh
pyrdp-player -p <PORT>
默认情况下,播放器只监听来自本地机器的连接。我们不建议将播放器
开放给其他机器。如果您仍想更改监听地址,可以使用 -b:```sh
pyrdp-player -b
#### 其他播放器参数
运行 `pyrdp-player --help` 获取完整参数列表。
### 使用 PyRDP 证书克隆工具
注意:此工具是可选的。
从 1.0 版本开始,PyRDP 会像此工具一样即时生成证书。
PyRDP 证书克隆工具通过使用现有 RDP 服务器证书的值创建一个全新的 X509 证书。
它连接到一个 RDP 服务器,下载其证书,生成一个新的私钥,并使用新私钥替换证书的公钥和签名。
例如,在渗透测试中,如果你试图欺骗合法用户通过你的中间人攻击,这可能会用到。
使用看起来像合法证书的证书可以提高你的成功率。
#### 克隆证书
你可以通过使用 `pyrdp-clonecert`:```sh
pyrdp-clonecert 192.168.1.10 cert.pem -o key.pem
-o 参数定义了用于生成的私钥的路径名称。
如果你想使用自己的私钥而不是生成一个新的:```sh pyrdp-clonecert 192.168.1.10 cert.pem -i input_key.pem
#### 其他克隆器参数
运行 `pyrdp-clonecert --help` 查看完整参数列表。
### 使用 PyRDP Convert
`pyrdp-convert` 是一个辅助脚本,可将多种输入格式转换为多种输出格式。
由于非拦截连接中可能使用不支持的 RDP 协议特性,该脚本对 PyRDP 捕获的流量处理效果最佳。
支持以下输入:
- 网络抓包(PCAP)与 TLS 主密钥(可靠性较低)
- 网络抓包(PCAP)以导出 PDU 第 7 层格式(可靠性更高)
- PyRDP 生成的重放文件
支持以下输出:
- MP4 视频文件
- JSON:以 JSON 格式序列化的低层级事件序列
- 与 `pyrdp-player` 兼容的重放文件
加密(TLS)网络抓包需要使用 `--secrets ssl.log` 提供 TLS 主密钥。```sh
# Export the session coming client 10.2.0.198 to a .pyrdp file.
pyrdp-convert --src 10.2.0.198 --secrets ssl.log -o path/to/output capture.pcap
# Or as an MP4 video
pyrdp-convert --src 10.2.0.198 --secrets ssl.log -o path/to/output -f mp4 capture.pcap
# List the sessions in a network trace, along with the decryptable ones.
pyrdp-convert --list-only capture.pcap
请注意,MP4转换需要libavcodec和ffmpeg,因此在Windows上可能需要额外的步骤。
手动解密的网络跟踪可以通过选择 File > Export PDUs 并选择 OSI Layer 7 从Wireshark导出。
首先,确保你配置了Wireshark以加载TLS密钥:

接下来,导出OSI Layer 7 PDUs:

并且,可选地,通过应用显示过滤器并点击 File > Export Specified Packets... 将跟踪过滤为仅包含感兴趣的对话。

现在,这个跟踪可以直接在 pyrdp-convert 中使用。
大多数PyRDP配置是通过命令行开关完成的,但也可以使用配置文件进行某些设置,例如日志配置。
PyRDP使用的默认配置文件位于 mitm.default.ini 和 player.default.ini。这两个文件都有详细的文档记录,可以作为进一步配置的基础。
未来计划通过这些配置文件支持PyRDP配置的其他方面。
如果你有兴趣尝试RDP并制作自己的工具,请前往我们的 文档部分 获取更多信息。
PyRDP MITM组件也作为twistd插件实现。这使您可以在调试模式下运行它,并且如果您向twistd进程发送 SIGUSR2,则可以获得交互式调试repl(pdb)。有关更多信息,请参阅 twistd文档。
我们开发了自己的Bettercap模块 rdp.proxy,用于对给定LAN上的所有RDP连接进行中间人攻击。查看 此文档 了解更多信息。
由于Docker限制与主机系统(文件系统和网络)的交互,因此必须根据您的用例使用一些参数来运行PyRDP Docker镜像。本节记录了这些参数。
我们指的是公开提供的Docker镜像,但如果您 自己构建,请将 gosecure/pyrdp 替换为您本地构建的镜像名称。
在大多数中间人攻击场景中,您需要将主机的一个端口映射到Docker镜像中。这通过应用于 docker run 的 --publish(-p)参数实现。
例如,要监听所有接口上的3389(RDP的默认端口),请使用:
docker run --publish 3389:3389 gosecure/pyrdp pyrdp-mitm.py <target_ip>
``````sh
docker run -p 3389:3389 gosecure/pyrdp pyrdp-mitm 192.168.1.10
要永久存储 PyRDP 输出(日志、文件等),请在前面的命令中添加 --volume(-v)选项。在此示例中,我们将文件相对于当前目录存储在 pyrdp_output 中:```sh
docker run -v $PWD/pyrdp_output:/home/pyrdp/pyrdp_output -p 3389:3389 gosecure/pyrdp pyrdp-mitm 192.168.1.10
确保你的目标目录由一个UID为1000的用户拥有,否则你将遇到权限被拒绝的错误。
如果你是系统上唯一的非root用户,通常你的用户会被分配UID 1000。
#### 记录主机IP地址
如果你希望PyRDP在其日志中记录主机IP地址,可以在使用`docker run`时设置`HOST_IP`环境变量:```sh
docker run -p 3389:3389 -e HOST_IP=192.168.1.9 gosecure/pyrdp pyrdp-mitm 192.168.1.10
使用播放器需要将DISPLAY环境变量从主机导出到Docker容器中。
这会将播放器的GUI重定向到主机屏幕上。
您还需要暴露主机的网络,并防止Qt使用MIT-SHM X11共享内存扩展。
为此,请在运行命令中添加-e和--net选项:```sh
docker run -e DISPLAY=$DISPLAY -e QT_X11_NO_MITSHM=1 --net=host gosecure/pyrdp pyrdp-player
请记住,将主机的网络暴露给docker可能会损害容器与主机之间的隔离性。
如果您打算使用播放器,通过SSH连接进行X11转发会是更安全的方式。
#### 在Docker中转换视频
视频转换过程依赖于PyAV、ffmpeg和QT,因此您需要常规的docker镜像,而不是精简版。
您需要一个卷挂载(`-v`)来与容器共享文件。
这里我们将本地目录映射到容器中的`/shared/`。```sh
docker run -e QT_QPA_PLATFORM=offscreen -v $PWD/:/shared gosecure/pyrdp pyrdp-convert -f mp4 <filename-relative-to-volume-in-/shared/> -o /shared/
需要设置环境变量 QT_QPA_PLATFORM=offscreen,原因在于此处记录的一个 bug。它告诉 QT 没有可用的显示环境是正确的。
请参阅我们的贡献指南。
PyRDP 使用了以下开源软件的代码: