返回

Python RDP自动化:连接、认证及键盘操作详解

python

Python RDP 库使用:连接、认证及自动化操作

使用 Python 进行 RDP(远程桌面协议)自动化操作时,一个关键环节是如何通过代码实现连接远程服务器,并完成用户身份验证, 之后可以执行鼠标键盘操作,比如发送按键或点击事件。一些 RDP 库如 rdpy 提供了底层协议支持,但需要开发者自行实现认证流程和操作逻辑。本文探讨如何利用 rdpy 等库完成这些任务。

解决认证问题

提供的代码示例直接创建连接,并未包含用户身份验证步骤。RDP 的连接建立后,服务器通常会等待用户输入用户名、密码进行认证,这是一个安全访问的必要环节。我们需要将用户名密码传递给远程服务器。

一种常见的做法是在 RDP 会话建立后,通过发送键盘事件来模拟用户输入。以下是一种可行的策略,将 usernamepassword 和目标 ipport 设置为参数。

代码示例

from rdpy.protocol.rdp import rdp
from twisted.internet import reactor

def connect_rdp(ip, port, username, password):
    class MyRDPFactory(rdp.ClientFactory):
        def clientConnectionLost(self, connector, reason):
            reactor.stop()

        def clientConnectionFailed(self, connector, reason):
            reactor.stop()

        def buildObserver(self, controller, addr):
            class MyObserver(rdp.RDPClientObserver):
                _stage = 0 # 增加一个阶段标志,避免重复发送用户名和密码
                def onReady(self):
                    """
                    @summary: Call when stack is ready
                    """
                    if self._stage == 0:
                        # Send username
                        for char in username:
                           self._controller.sendKeyEventUnicode(ord(char), True)
                        self._controller.sendKeyEventUnicode(13, True) # enter key
                        self._stage=1

                def onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
                  """
                  @summary: Notify bitmap update
                  @param destLeft: xmin position
                  @param destTop: ymin position
                  @param destRight: xmax position because RDP can send bitmap with padding
                  @param destBottom: ymax position because RDP can send bitmap with padding
                  @param width: width of bitmap
                  @param height: height of bitmap
                  @param bitsPerPixel: number of bit per pixel
                  @param isCompress: use RLE compression
                  @param data: bitmap data
                  """
                    if self._stage == 1: # 进入第二阶段
                        # Send password
                        for char in password:
                           self._controller.sendKeyEventUnicode(ord(char), True)
                        self._controller.sendKeyEventUnicode(13, True)  # enter key
                        self._stage = 2 #完成密码发送


                def onSessionReady(self):
                    """
                    @summary: Windows session is ready
                    """
                  

                def onClose(self):
                  """
                  @summary: Call when stack is close
                  """


            return MyObserver(controller)


    reactor.connectTCP(ip, port, MyRDPFactory())
    reactor.run()

# 请替换为你的RDP服务器信息、用户名和密码
connect_rdp("目标服务器 IP", 3389, "用户名", "密码")

代码解析:

  1. 自定义MyObserver:MyObserver 类中,我们使用 _stage 变量来区分发送用户名和密码的阶段,避免重复发送用户名和密码。
  2. onReady 事件处理: 连接建立后,onReady 事件会被触发,这是发送用户名文本的好时机。使用 sendKeyEventUnicode 模拟键盘输入。回车符 (13) 被添加,用于模拟按“Enter”键。阶段变量 _stage 会更新到下一个阶段 1。
  3. onUpdate 事件处理 : 使用 onUpdate 事件来发送密码, 因为某些系统会先呈现界面然后请求用户名密码。这个步骤需要注意,只有当前 _stage 为 1 时才触发密码输入,避免 onReady 被多次调用,造成多次尝试登录。成功发送密码后,修改 _stage 到 2。
  4. 启动 Twisted 循环: 使用 reactor.connectTCP 创建 RDP 连接,并通过 reactor.run 启动 Twisted 事件循环。

重要提示:

  • 请将占位符 “目标服务器 IP”3389“用户名”,和 “密码” 替换为实际值。
  • 这种模拟键盘输入的方式可能存在不稳定性,特别是网络环境较差或 RDP 服务器有延迟的时候。一种改善的方式是为键盘事件发送加入一定的延迟,保证服务端可以顺利接收输入。

额外的安全建议

使用 RDP 时应特别注意安全,以下是一些建议:

  1. 避免硬编码凭据: 直接在代码中嵌入用户名和密码是非常不安全的,应考虑使用环境变量或者安全的密钥管理方案。
  2. 网络安全: 确保 RDP 连接使用强加密,并限制对 RDP 服务器的访问。
  3. 及时更新: 定期更新 RDP 服务器的补丁,降低漏洞风险。
  4. 最小权限原则: 只为用户赋予所需的最小权限。
  5. 双因素验证: 考虑使用双因素验证以增强账户安全。

总结

本文讨论了如何使用 Python rdpy 库连接到 RDP 服务器,并通过模拟键盘输入来处理用户身份验证,以及实现自动化鼠标键盘操作的方法,并提供了相应代码。使用 RDP 需要在安全性方面额外注意,应该遵循一些最佳安全实践来保护服务器免受恶意攻击。在实际项目中可以根据情况调整本文代码,以适应特定的需求。

通过对 RDP 协议和 RDP 库的深入了解,开发者可以在 Python 中实现高度灵活和可扩展的自动化 RDP 解决方案。