【问题标题】:Alternatives to LogonUser for network impersonation (C++)用于网络模拟的 LogonUser 的替代方案 (C++)
【发布时间】:2010-11-12 10:28:48
【问题描述】:

是否有任何替代 LogonUser 和模拟给定帐户以访问网络资源的方法?我正在寻找一种模拟方法,它可以让我连接到外国域中的机器(或同样的工作组机器)。

对于初始数据,我有:机器名、用户名(或域\用户名)、明文密码。

我知道有一种方法可以使用 WNetAddConnection 与 \\machinename\ipc$ 建立连接,然后大多数网络功能将在该帐户的上下文中运行,但是 win2008 增加了另一个转折点,一些功能仍然使用该帐户,该线程正在运行。

我也知道,有一些方法可以使用 SSPI 获取模拟令牌。有没有人尝试过这些令牌,它们是否适合访问共享、SCM、远程注册表和其他东西?是什么 WNetAddConnection 正在使用?

编辑:澄清一下,我不能使用 LogonUser 的原因是因为我需要在不受信任的域或工作组中模拟用户

EDIT2: 另一个澄清:我试图实现的项目类似于 psexec,例如:

  • 程序不应修改主机或活动目录配置(例如:创建临时本地用户等)。此外,不能假设它是否在 DC 上运行
  • 不能假设远程主机上预装了哪些软件,唯一的条件是目标上启用了 Windows 文件共享
  • 已知帐户/密码在目标上工作,但目标计算机可能在本地域、外部域中,根本不在域中。

EDIT3:我真的很想了解更多关于 SSPI InitializeSecurityContext / AcquireCredentialsHandle 选项的信息。有没有人一直在广泛使用这个 API?是否可以使用模拟返回的令牌,以便线程可以访问网络共享和复制文件等?有人可以发布一个工作代码sn-p吗?

EDIT4:感谢 Marsh Ray,问题得到解决。如果有人想查看概念验证代码,it is here

【问题讨论】:

    标签: c++ security winapi impersonation sspi


    【解决方案1】:

    理论上,您将凭据作为SEC_WINNT_AUTH_IDENTITY 结构传递给AcquireCredentialsHandle 函数,该函数创建InitializeSecurityContext 中使用的句柄。我从来没有在外国域名上试过这个,我不知道它是否有效。

    【讨论】:

      【解决方案2】:

      通过 Windows API 直接可靠地执行此操作似乎几乎是不可能的,而且 Windows 在幕后做了很多工作以使网络访问“正常工作”。此外,模拟方面仅适用于调用 API 的单线程。

      但是...您可以在不同的用户下运行整个程序...例如在您运行服务时。

      因此,您可以在主程序中编辑注册表以在不同的安全令牌下运行各种服务,并使用 IPC/Sockets 从您的主应用程序中与这些进程进行通信。 IE。一大堆(或重新启动并重新配置同一进程)在您的主应用滥用的不同用户下运行的辅助进程。

      我意识到这是一个 hack,但它似乎可行 ;)

      【讨论】:

      • 不。不可行。需要能够为不受信任的森林中的机器获取模拟令牌。您不能以不受信任林的用户身份运行程序
      • 你可以在本地创建用户,因为你有明文密码,完成后删除用户。另一种选择是直接谈论 DCERPC/MSRPC (en.wikipedia.org/wiki/MSRPC),但随后您实际上会走上与 samba 类似的轨道,但至少您可以使用 Wireshark 将您的实现与通过普通 Window API 发生的情况进行比较。你能在远程机器上安装帮助程序并在该端进行模拟(并使用你喜欢的任何协议连接到远程帮助程序吗?)?
      • 我想我没有仔细阅读您对服务的评论。我的帖子特别受到以下事实的启发:当我尝试将服务安装到远程 Windows 2008 机器时,并且我已经映射了一个共享,远程 SCM 仍然不会使用用于映射共享的帐户
      • 较新版本的 Windows 停止允许服务使用映射驱动器,这仅留下 UNC 路径来访问远程驱动器。这是有道理的,因为映射驱动器比其他任何东西都更依赖于桌面。
      • 正确。我应该谨慎使用措辞。 “映射驱动器”是指“建立 WMNet 连接”。然而,我发现,即使我建立了连接并可以复制文件,在 windows 2008 下尝试打开 SCM 仍将使用当前登录的帐户,而不是我用来建立连接和复制文件的帐户。这就是我正在寻找替代品的原因
      【解决方案3】:

      您可以打开命令行,使用明文用户名和密码映射驱动器。然后断开驱动器:

      net use m: \\machinename\share password /user:username
      ... do stuff ...
      net use m: /delete
      

      http://technet.microsoft.com/en-us/library/cc756153(WS.10).aspx

      【讨论】:

      • 我提到这个解决方案不起作用:“我知道有一种方法可以使用 WNetAddConnection 建立与 \\machinename\ipc$ 的连接,...” - 你基本上是在暗示同样的事情
      • 抱歉,我认为 WNetAddConnection 有所不同。
      【解决方案4】:

      如果您想要在您的林之外“访问网络资源”,请使用您提到的 WNetAddConnection2/3 执行此操作,或者使用带有 RPC_C__ AUTHN__ GSS__ NEGOTIATE 和显式凭据结构的标准 RPC API。

      通常,“模拟”是在服务器端发生的事情。服务器端将能够将连接模拟为您正在连接的帐户。

      但关键是:模拟仅对模拟服务器可以在其本地 SAM/domain/forest 目录中访问的帐户有意义。如果客户端和服务器在不同的森林中,他们显然不能就模拟令牌的帐户的 SID 达成一致(除了像管理员这样的知名 SID 主要用于混淆这类事情的情况),并且这似乎有必要检查 DACL 等。

      也许您想要的是使用 LOGON32__ LOGON__ NEW__ CREDENTIALS 标志调用 LogonUserEx。这应该会成功(即使在不同的森林中 - 它实际上不会验证您提供的凭据)为您提供一个带有您指定的用户名/密码的令牌。您可能必须使用 DuplicateToken 将其转换为模拟令牌。然后您可以使用 SetThreadToken 替换线程上的令牌。

      恕我直言,这并不是真正的“模拟”,您只是直接使用凭据,但它允许您以您提供的任意用户名/密码透明地访问网络资源。

      编辑:哦,是的,请注意,在这种类型的连接上没有针对中间人的保护。客户端尤其不能对服务器进行强身份验证(缺乏像 IPSEC 这样的英雄事迹),所以理论上你不能相信服务器告诉你的任何事情。

      【讨论】:

      • 哇,听起来不错!我从来没想过用这个。让我快速测试一下它是否有效
      • 老兄,做到了!非常感谢,这正是我一直在寻找的
      • 不要忘记恢复线程的旧令牌并清理所有新令牌。您不想泄漏令牌,我怀疑它们会消耗内核和/或 lsass.exe 中的稀缺资源。
      • 出于好奇,您最终需要调用 DuplicateToken 吗?
      • 不。所有作品都没有故障,不需要 DuplicateToken。这是代码:docs.google.com/View?id=djcgsjz_1gvhc7wfg
      猜你喜欢
      • 2020-09-07
      • 2014-04-20
      • 1970-01-01
      • 2019-10-19
      • 2011-02-12
      • 2018-03-23
      • 2015-01-04
      • 2023-04-09
      • 1970-01-01
      相关资源
      最近更新 更多