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

逆向工程 视窗 过程
2021-06-19 09:47:16

CreateProcessAsUser Windows 服务通常在启动用户指定的可执行文件时使用它,以便以中等完整性级别运行它以确保特权隔离。

CreateProcessAsUser 堆栈跟踪

查看签名,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
);

Q:什么机制决定了“当前用户”?

我用双引号引用了“当前用户”,因为假设一个实现点似乎很模糊。我目前假设每个调用的函数CreateProcessAsUser都有自己的检索“当前用户”以传递其令牌的实现。

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

1个回答

我目前假设调用 CreateProcessAsUser 的每个函数都有自己的检索“当前用户”以传递其令牌的实现。

我想了解这个逻辑是什么样的,以及 hToken 的选择标准是什么。

不久前,当以 SYSTEM 身份运行程序时,我编写了一些 Delphi 代码来执行此操作。我不是服务,而是从 SYSTEM cmd 提示符执行,我使用 psexec: 调用了该提示符psexec -s -i -d cmd.exe逻辑是这样流动的:

  1. 调用WTSGetActiveConsoleSessionID来检索连接到物理控制台的会话的会话 ID(因此不是术语服务会话)。代码
  2. 接下来可以调用WTSQueryUserToken来检索该会话的令牌获取 SYSTEM 进程的 PID,例如winlogon.exe
  3. 通过调用代码获取该进程的句柄OpenProcess
  4. 使用此句柄,调用OpenProcessToken以获取进程访问令牌代码的句柄
  5. 调用DuplicateTokenEx指定此句柄和用户的会话 ID 以创建令牌的副本。代码
  6. 使用此重复令牌调用 CreateProcessAsUser。代码

这是C# 中的一个类似示例

您可以使用Process Explorer查看进程正在其中运行的会话。 在此处输入图片说明