在Windows服务中如何实现CreateProcessAsUser模拟?


0

CreateProcessAsUser是经常使用的情况下,用户是为了与中等完整性级别运行,以确保特权隔离指定的可执行文件启动的Windows服务。

CreateProcessAsUser stack trace

望着签名,hToken必须提供。从我的观察,Windows服务总是选择执行此操作的当前登录用户。

BOOL WINAPI CreateProcessAsUser(
    _In_opt_ HANDLE    hToken, 
    _In_opt_ LPCTSTR    lpApplicationName, 
    _Inout_opt_ LPTSTR    lpCommandLine, 
    _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 
    _In_  BOOL     bInheritHandles, 
    _In_  DWORD     dwCreationFlags, 
    _In_opt_ LPVOID    lpEnvironment, 
    _In_opt_ LPCTSTR    lpCurrentDirectory, 
    _In_  LPSTARTUPINFO   lpStartupInfo, 
    _Out_  LPPROCESS_INFORMATION lpProcessInformation 
); 

问:什么样的机制决定了 “当前用户”?

我双引号引起“当前用户”,因为它似乎很模糊承担实施的一个点。我目前假设每个调用CreateProcessAsUser的函数都有自己的实现来检索“当前用户”以传递它的标记。

我想明白这是什么逻辑看起来和上选择什么标准的hToken。由于用户模式进程创建是由许多Windows服务执行的,所以我不得不假设它有一个共同的逻辑,但是我没有在堆栈跟踪中看到它(见图)。

  0

好吧,一个非常受欢迎的方法的基础还有几个COM/RPC方法可以在'ImpersonateNamedPipeClient'中找到。但是,鉴于服务在TCB中运行,他们可以轻易地从某个进程“窃取”现有的令牌或伪造自己的令牌。最后但并非最不重要的几个内部因Windows版本而改变,因此_you_请求什么版本?哦,这实际上可能更适合StackOverflow。 19 12月. 172017-12-19 22:18:33

  0

我正在查看Windows 10 x64的当前版本。当然,一个'SYSTEM'进程可以接受任何令牌,因为它有足够的权限。但它选择当前用户的令牌 - 基于[...],这是我特别好奇的。 *在StackOverflow中,我认为这是不重要的,因为它不直接编程。* 19 12月. 172017-12-19 22:24:06

  0

嗯,名称中真正的*是*。任何*服务*为用户做一份工作都有一些与用户安全上下文进行交流的方式。这样 - 至少在我调查过的所有情况下,无论是COM,RPC还是其他 - 最后都被命名为管道。所以重新阅读我上面的评论。我现在根本没有时间去详细描述这个问题(希望别人会这么做)。也许关于你的其他评论。但是,这也不是直接关于RCE。 19 12月. 172017-12-19 22:29:03

  0

我发现的一个触发器是一个HWND广播'(0xffff,...)' - 查看该示例时,从用户到服务的管道在哪里?有趣的是,UIPI并没有阻止它。 19 12月. 172017-12-19 22:33:23

  0

这不是一个预定义的窗口消息,所以你必须弄清楚谁来查找并处理它(当它们在目标进程中运行时,窗口挂钩可能会派上用场,尽管如此。但是,你怎么知道这是一个*触发器*(相关!=因果关系)。 19 12月. 172017-12-19 22:38:38

  0

因为当我SendMessage一个特定的广播时,一个SYSTEM进程执行一个二进制AsUser。一旦我意识到这一点,我试图找到分析HWND消息的工具,特别是广播。 (有什么建议?)。或者我会写我自己的WndProc来查看哪些消息去了哪里。 19 12月. 172017-12-19 22:42:31

  0

让我们[在聊天中继续讨论](http://chat.stackexchange.com/rooms/70526/discussion-between-0xc0000022l-and-bytecode77)。 19 12月. 172017-12-19 22:49:16

4

目前,我认为每一个调用CreateProcessAsUser函数都有自己的执行检索“当前用户”以通其令牌。

我想明白这是什么逻辑看起来和上选择什么标准的hToken。

后来我写了一些Delphi代码来做到这一点,当作为系统运行一个程序。我从一个SYSTEM cmd提示符执行,而不是一个服务,我使用psexec:psexec -s -i -d cmd.exe)调用。逻辑如下流动:

  1. 呼叫WTSGetActiveConsoleSessionID检索连接到物理控制台(因此不是术语服务会话)的会话的会话ID。 code
  2. 可接下来请WTSQueryUserToken通过调用OpenProcesscode
  3. 使用该句柄来检索令牌该会话获取PID为一个系统进程,如winlogon.exe
  4. 获取句柄到这个过程中,调用OpenProcessToken获得句柄进程的访问令牌code
  5. 呼叫DuplicateTokenEx指定此手柄和用户的会话ID,以创建令牌的副本。 code
  6. 使用此重复标记调用CreateProcessAsUser。 code

这是similar example in C#

您可以使用Process Explorer来查看进程正在运行中的会议。 enter image description here

  0

啊,我明白了!由于SessionID = 1,用户就是我。在Session 0中运行的进程是什么 - CreateProcessAsUser会做什么?我知道这取决于具体的实施。但是,如果从Session 0中的进程调用CreateProcessAsUser,它会产生一个SYSTEM进程吗? 20 12月. 172017-12-20 00:05:30

  0

那么,你可以像任何用户一样创建一个进程,并选择显示的桌面。在我上面链接的Delphi代码中,我检索[我找到的第一个explorer.exe登录的用户令牌](https://github.com/MicksMix/RunAsLou/blob/master/uWtsUtils.pas#L417),然后通过[硬编码lpDesktop为Winsta0 \ default](https://github.com/MicksMix/RunAsLou/blob/master/uWtsUtils.pas#L429)在登录用户的桌面上创建一个新进程。所以这意味着我在用户的桌面上创建了一个新进程,但是通过合并SYSTEM标记和用户令牌来启动。 20 12月. 172017-12-20 00:53:32

  0

在**多用户**操作系统上不是一个好主意。 20 12月. 172017-12-20 09:04:09

  0

那么在会话0而不是1+中运行的系统进程呢?我将需要观察这些服务是否会创建更多用户进程。但是现在,你的回答帮助我了解了内部逻辑。谢谢:) 20 12月. 172017-12-20 10:43:05

+1

@ 0xC0000022L - 同意。在我编写程序的具体用例中,这满足了需求并始终如一地工作。但是,正确的方法是调用[WTSQueryUserToken,我在我的程序中注释](https://github.com/MicksMix/RunAsLou/blob/master/uWtsUtils.pas#L425)来检索用户令牌。 20 12月. 172017-12-20 16:28:37

  0

@bytecode77 - 默认情况下,SYSTEM进程在会话0中运行,自Windows Vista开始,[OS已采取步骤隔离会话](https://blogs.technet.microsoft.com/askperf/2007/04/27/application -compatibility-session-0-isolation /)。我使用进程管理器的屏幕快照更新了我的答案,显示了如何将'Session'列添加到显示器。 20 12月. 172017-12-20 17:56:14

+1

WTSQueryUserToken已经返回用户的主访问令牌,因此不需要复制它。 28 12月. 172017-12-28 13:05:44