CreateProcessAsUser从适当的PEB和ACL的服务

我已经阅读了很多有关这个问题的SO问题,但我没有find一个真正的明确的指导方针来做这个正确的方法。

我的目标是列举[断开和活动]用户控制台会话,并在其中的每一个启动一个进程。 每个用户会话进程至less需要在DACL中拥有这些权限:

令牌访问权限:

  • TOKEN_QUERY (用于GetTokenInformation() )
  • TOKEN_QUERY_SOURCE (用于GetTokenInformation() )

进程访问权限:

  • PROCESS_QUERY_INFORMATION (用于OpenProcessToken() )
  • PROCESS_QUERY_INFORMATION | PROCESS_VM_READ PROCESS_QUERY_INFORMATION | PROCESS_VM_READ (用于GetModuleFileNameEx() )
  • PROCESS_VM_OPERATION (与GetTokenInformation()一起用于稍后使用LookupAccountSid()获取其他进程的用户名)

但是,正如你可以在这里读到的(在底部): "Windows Vista introduces protected processes to enhance support for Digital Rights Management. The system restricts access to protected processes and the threads of protected processes."
所以我想也许只有PROCESS_QUERY_LIMITED_INFORMATION我可以得到一些关于其他进程的信息。 我尝试QueryFullProcessImageName()的升级过程从Vista开始(见Giori的答案 ),但它不工作了,因为它似乎 。
解决scheme:使用Windows服务的重复标记CreateProcessAs_ LOCAL_SYSTEM
问题:生成的进程应该设置各自的login用户的环境variables,以便能够定位networking打印机和映射的驱动器等等。 但是如果我使用服务的令牌,我inheritance了它的PEB,我甚至不能将映射的驱动器转换到它们的UNCpath。

于是我开始寻找方法来“提升”进程并绕过UAC提示,我试着:

  • 使用AdjustTokenPrivileges()在标记中启用SE_DEBUG_PRIVILEGE特权(如果标记没有这些特权,则不起作用,可以先使用LookUpPrivilegeValue()进行validation)
  • 使用winlogon.exe.的令牌winlogon.exe. (不起作用)
  • 更改DACL( 源代码 )(没有工作)

我遵循的步骤是:

  1. 使用WTSEnumerateSessions()枚举会话
  2. 获取令牌(两种select):
    • SYSTEM令牌: OpenProcessToken ( GetCurrentProcess() ,TokenAccessLevels.MaximumAllowed,out hProcessToken)
    • 用户令牌: WTSQueryUserToken (sessionId,out hUserToken)
  3. 使用DuplicateTokenEx()复制令牌
  4. LookUpPrivilegeValue() / AdjustTokenPrivileges() (无用?)
  5. CreateEnvironmentBlock()
  6. CreateProccessAsUser() ,flags: NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT ,启动信息桌面: "WinSta0\Default"
  7. 更改过程DACL(请参阅上面的链接,没用?)
  8. Dispose / Clean:销毁创build的PEB,closures打开的句柄并释放内存。

我的问题:如何授予从LOCAL_SYSTEM下运行的Windows服务使用CreateProccessAsUser()创build的进程足够的特权/权限,以便在不损失用户环境variables的情况下获取有关其他进程(来自其他进程,其他用户和不同完整性级别) ?

你对一些事情感到困惑。

每个用户会话进程至少需要在DACL中拥有这些权限

进程DACL控制对该进程的访问,但不确定该进程具有什么访问权限。 进程的安全令牌决定访问权限。

Windows Vista引入了受保护的进程,以增强对数字权限管理的支持。

很明显,你还没有足够的时间来担心受保护的流程。 让它为普通的进程工作!

产生的进程应该有相应的登录用户的环境变量设置为能够定位网络打印机和映射驱动器等等。

网络打印机和映射驱动器与环境变量无关。 我想你要做的是将新进程放到用户的登录会话中,这就是控制网络驱动器映射等等。

如何授予使用CreateProccessAsUser()创建的进程足够的特权/权限来获取有关其他进程(来自其他进程,其他用户和不同完整性级别)的信息,而不会丢失用户的环境变量?

别。 这将违反安全模型的完整性。

相反,从系统服务枚举和查询进程,并使用共享内存(在MSDN中查找“文件映射对象”)或其他合适的IPC机制,只传递用户会话进程所需的任何信息。

我知道这是前一阵子问的。 由于我碰巧一直在做,下面是工作的伪代码。

首先,如何在一个服务的用户会话中运行一个进程:

 //IMPORTANT: All error checks are omitted for brevity! // Each of the lines of code below MUST be // checked for possible errors!!! //INFO: The following pseudo-code is intended to run // from the Windows local service. DWORD dwSessionID; //Session ID to run your user process in //Get token for the session ID HANDLE hToken; WTSQueryUserToken(dwSessionID, &hToken); //Duplicate this token HANDLE hToken2; DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hToken2); PSID gpSidMIL_High = NULL; if(you_want_to_change_integrity_level_for_user_process) { if(!Windows_XP) { //For example, create "high" mandaroty integrity level SID ::ConvertStringSidToSid(L"S-1-16-12288", &gpSidMIL_High); TOKEN_MANDATORY_LABEL tml = {0}; tml.Label.Attributes = SE_GROUP_INTEGRITY; tml.Label.Sid = gpSidMIL_High; SetTokenInformation(hToken2, TokenIntegrityLevel, &tml, sizeof(TOKEN_MANDATORY_LABEL) + ::GetSidLengthRequired(1)); } } //Copy environment strings LPVOID pEnvBlock = NULL; CreateEnvironmentBlock(&pEnvBlock, hToken2, FALSE); //Initialize the STARTUPINFO structure. // Specify that the process runs in the interactive desktop. STARTUPINFO si; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.lpDesktop = _T("winsta0\\default"); PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); //Create non-const buffer TCHAR pBuffCmdLine[MAX_PATH]; pBuffCmdLine[0] = 0; //Copy process path & parameters to the non-constant buffer StringCchCopy(pBuffCmdLine, MAX_PATH, L"\"C:\\Program Files (x86)\\Company\\Brand\\process.exe\" -parameter"); //Impersonate the user ImpersonateLoggedOnUser(hToken2); //Launch the process in the user session. bResult = CreateProcessAsUser( hToken2, // client's access token L"C:\\Program Files (x86)\\Company\\Brand\\process.exe", // file to execute pBuffCmdLine[0] != 0 ? pBuffCmdLine : NULL, // command line NULL, // pointer to process SECURITY_ATTRIBUTES NULL, // pointer to thread SECURITY_ATTRIBUTES FALSE, // handles are not inheritable NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, // creation flags pEnvBlock, // pointer to new environment block NULL, // name of current directory &si, // pointer to STARTUPINFO structure &pi // receives information about new process ); //Get last error nOSError = GetLastError(); //Revert to self RevertToSelf(); //At this point you may want to wait for the user process to start, etc. //using its handle in `pi.hProcess` ... //Otherwise, close handles if(pi.hProcess) CloseHandle(pi.hProcess); if(pi.hThread) CloseHandle(pi.hThread); //Clean-up if(pEnvBlock) DestroyEnvironmentBlock(pEnvBlock); CloseHandle(hToken2); CloseHandle(hToken); if(gpSidMIL_High) ::LocalFree(gpSidMIL_High); 

如果您需要使用已登录的交互式用户在所有会话中运行流程,则可以运行上面给出的可用于以下枚举的会话的方法:

 //Enumerate all sessions WTS_SESSION_INFO* pWSI = NULL; DWORD nCntWSI = 0; if(WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWSI, &nCntWSI)) { //Go through all sessions for(DWORD i = 0; i < nCntWSI; i++) { //To select logged in interactive user session, //try to get its name. If you get something, then //this session has a user logged in to... LPTSTR pUserName = NULL; DWORD dwcbSzUserName = 0; if(WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, pWSI[i].SessionId, WTSUserName, &pUserName, &dwcbSzUserName) && pUserName && dwcbSzUserName >= sizeof(TCHAR) && pUserName[0] != 0) { //Use my method above to run your user process // in this session. DWORD dwSessionID = pWSI[i].SessionId; } //Free mem if(pUserName) WTSFreeMemory(pUserName); } //Free mem WTSFreeMemory(pWSI); }