65.9K
CodeProject 正在变化。 阅读更多。
Home

XP 中的远程协助:以编程方式建立 RDP 会话

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (10投票s)

2008年10月6日

CPOL

3分钟阅读

viewsIcon

67362

downloadIcon

1234

在 C++ 中自动化帮助助手进程而无需肮脏的脚本代码的方法。

引言

我关于 RDP 的文章 介绍了如何管理远程桌面会话以提供帮助,但这仅适用于 Vista,而且许多用户(包括我自己!)仍然运行 XP。这是在不手动调用“帮助和支持”的情况下建立远程协助会话的方法。

我的实验项目“Turbo Remote”在使用此技术,如果它检测到低于 Windows Vista 的系统。

要求

  • Windows XP 或 2003。我没有在 Vista 中测试过,因为在 Vista 中,有一个干净的 API,如讨论的那样。
  • 管理员权限。
  • 这必须由原生应用程序完成。也就是说,如果您尝试在 x64 上运行 32 位版本的代码,它将失败。
  • 尚无加密。

目录

  • rdpxp.cpp/rdpxp.h - 一个提供服务器实现的简单类。

逐步实现服务器

需要创建“监听”会话的应用程序必须执行以下操作

  • 检查“终端服务”服务是否正在运行。如果此服务未运行,则必须启动它,否则其他任何操作都将无法正常工作。应用程序必须在服务器关闭后将服务恢复到其原始状态。这在我的代码中通过 EnableTSS(bool)IsTSSEnabled() 实现。(这些尚未实现!)
  • 使用 NetUserEnumNetUserSetInfo 函数启用帮助助手帐户。应用程序必须在帐户最初被禁用时禁用它。这通过 EnableHA(bool)IsHAEnabled() 实现。
  • 通过将 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server 中的“fAllowToGetHelp”设置为 1 来启用远程协助。通过 SetRARunning(bool)IsRARunning() 实现。
  • 启用组策略以接受远程协助。如果之前禁用了这些键,则进行恢复。这在 GetTicket() 中完成。相关内容是
    • Software\\Microsoft\\Windows\\CurrentVersion\\ Group Policy Objects\\<X>\\Software\\policies\\Microsoft\\Windows NT\\Terminal Services 中的“fAllowUnsolicited”、“fAllowUnsolicitedFullControl”、“fAllowToGetHelp”设置为 1(DWORD)。如果“Group Policy Objects”下存在键,则对其进行枚举,并选择包含“Machine”一词的键。如果不存在,则仅放置“LocalMachine”。如果该键根本不存在,则创建它。
    • 在其下创建另一个键“RAUnsolicit”,并添加一个与您的用户名(例如,Administrator)同名且值也等于您的用户名的值。
  • 导入 HelpServiceInterfaces.tlb 以获取帮助接口。
  • #import "HelpServiceInterfaces.tlb" rename_namespace("HSITLB") named_guids\
        rename("EOF", "XX_EOF")\
        rename("GetUserName", "GetUserName_Renamed")\
        rename("EncryptFile", "EncryptFile_Renamed")\
        rename("DecryptFile", "DecryptFile_Renamed")\
        rename("ULONG_PTR","ULONG_PTR1")

    如果上述代码生成 __missing__type 错误(如果您不使用 ATL),只需将 __missing__type 替换为 void*

  • 创建一个 IPCHService*
  • CoCreateInstance(HSITLB::CLSID_PCHService, NULL, CLSCTX_LOCAL_SERVER, 
                   __uuidof(HSITLB::IPCHService),(void**)&p);

    注意 CLSCTX_LOCAL_SERVER 的用法。

  • 调用 IPCHService::raw_RemoteConnectionParms(),提供用户名、计算机名称、终端服务会话 ID(WTSGetActiveConsoleSessionId())以及 blob 请求,该请求具有以下格式
  • "13;UNSOLICITED=1<X>;ID=<PCName>\\<Username>";

    <PCName><Username> 替换为所需值,将 <X> 替换为 <X> 之后所有内容的字符串长度。例如:“13;UNSOLICITED=122;ID=GATOR\\Administrator”。我的 PC 名称是 GATOR,我的用户名是 Administrator,字符串“ID=GATOR\Administrator”的总长度是 22。

  • 您已经获得了票证!

检查票证

您接下来需要做的是检查票证(它类似于:65538,1,192.168.1.21:3389;laptop:3389,*, KwRrNVpWH2g1vKfVlQUrJHKcpi8N1XA++9tQ+wnAXyE=,*,*,sdP7Lk3SFAXXcIrKpvLW6IJ8fg=),将端口 3389(它始终放在那里!)替换为终端服务服务器实际运行的端口。此端口位于 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TerminalServer\WinStations\RDP-Tcp 的“PortNumber”下。

创建 .MSRCINCIDENT 文件

这是一个 Unicode 文件(必须存在 BOM 标头 \xFE\xFF),格式如下

<?xml version="1.0" encoding="Unicode" ?>
<UPLOADINFO TYPE="Escalated">
  <UPLOADDATA USERNAME="Administrator" 
    RCTICKET="<ticket>" RCTICKETENCRYPTED="0" 
    DtStart="X" DtLength="Y" L="0"/>
</UPLOADINFO>

X 是创建票证的时间(标准 UNIX 格式,使用 time()),Y 是此时间 + 票证的长度。我尚未找到支持加密票证的方法。

拥有该文件后,您可以通过 TCP/IP 或其他方法将其发送到客户端。

实现客户端

客户端的实现只是接收 msrcincident 文件并通过 ShellExecute() 与“帮助和支持”一起运行它。

历史

  • 2008 年 10 月 6 日:首次发布。
© . All rights reserved.