从会话0(服务)启动提升的用户流程

大家早,

这个问题似乎已被问过几次,但我无法确定它是否真的有可能。 我已经在这里发布

没有回复 – 让我们试试这里的人。

我的目标是从当前用户上下文中的服务启动一个提升的进程(作为管理员)(仅当它们在本地管理员组中时)。

我可以毫无问题地获得当前用户令牌,但我无法获得该帐户的辅助/管理员令牌!

我已经阅读了很多论坛,但却无法让它工作(开始认为它不可行)。

我目前的方法:

  • WTSGetActiveConsoleSessionId – 获取活动会话ID
  • WTSQueryUserToken – 获取会话ID的用户令牌
  • 检查令牌是否为admin – 不是。
  • OpenProcess – 登录用户的explorer.exe的进程句柄
  • OpenProcessToken – 获取访问令牌的句柄
  • LookupPrivilegeValue – SE_DEBUG确认我们可以调整令牌权限
  • DuplicateTokenEx – 用户令牌
  • SetTokenInformation
  • AdjustTokenPrivileges
  • CreateEnvironmentBlock – 在中运行新进程
  • CreateProcessAsUser – 希望在提升的用户上下文中生成进程(未发生 – 标准用户上下文)

请参阅下面的代码 – 道歉它的混乱,需要整理,所有句柄都关闭。 这只是目前的经验代码。

 public static bool CreateProcessInConsoleSession(String CommandLine, bool bElevate) { PROCESS_INFORMATION pi; bool isadmin = IsUserAnAdmin(); bool bResult = false; uint dwSessionId, winlogonPid = 0; IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero, hPToken = IntPtr.Zero, hProcess = IntPtr.Zero; Debug.Print("CreateProcessInConsoleSession"); // Log the client on to the local computer. dwSessionId = WTSGetActiveConsoleSessionId(); // Find the winlogon process var procEntry = new PROCESSENTRY32(); uint hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnap == INVALID_HANDLE_VALUE) { return false; } procEntry.dwSize = (uint)Marshal.SizeOf(procEntry); //sizeof(PROCESSENTRY32); if (Process32First(hSnap, ref procEntry) == 0) { return false; } String strCmp = "explorer.exe"; do { if (strCmp.IndexOf(procEntry.szExeFile) == 0) { // We found a winlogon process...make sure it's running in the console session uint winlogonSessId = 0; if (ProcessIdToSessionId(procEntry.th32ProcessID, ref winlogonSessId) && winlogonSessId == dwSessionId) { winlogonPid = procEntry.th32ProcessID; break; } } } while (Process32Next(hSnap, ref procEntry) != 0); //Get the user token used by DuplicateTokenEx WTSQueryUserToken(dwSessionId, ref hUserToken); //Check if the user token is admin isadmin = CheckIfAdminToken(hUserToken); var si = new STARTUPINFO(); si.cb = Marshal.SizeOf(si); si.lpDesktop = "winsta0\\default"; var tp = new TOKEN_PRIVILEGES(); var luid = new LUID(); hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid); TOKEN_INFORMATION_CLASS tokenInfo = new TOKEN_INFORMATION_CLASS(); uint TokenInfLength = 0 ; if ( !OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE, ref hPToken)) { Debug.Print(String.Format("CreateProcessInConsoleSession OpenProcessToken error: {0}", Marshal.GetLastWin32Error())); } if (!LookupPrivilegeValue(IntPtr.Zero, SE_DEBUG_NAME, ref luid)) { Debug.Print(String.Format("CreateProcessInConsoleSession LookupPrivilegeValue error: {0}", Marshal.GetLastWin32Error())); } bool Result; #region TestToElevate //http://www.microsoft-questions.com/microsoft/Platform-SDK-Security/35984508/how-to-run-a-process-with-elevated-privileges-run-as-administrat.aspx // first call gets lenght of TokenInformation Result = GetTokenInformation(hPToken, TOKEN_INFORMATION_CLASS.TokenUser, IntPtr.Zero , TokenInfLength , out TokenInfLength ); IntPtr TokenInformation = Marshal.AllocHGlobal((int)TokenInfLength); Result = GetTokenInformation(hPToken, TOKEN_INFORMATION_CLASS.TokenElevation, TokenInformation, TokenInfLength, out TokenInfLength); if (Result == false) Result = GetTokenInformation(hPToken, TOKEN_INFORMATION_CLASS.TokenLinkedToken, TokenInformation, TokenInfLength, out TokenInfLength); isadmin = CheckIfAdminToken(hPToken); #endregion var sa = new SECURITY_ATTRIBUTES(); sa.Length = Marshal.SizeOf(sa); if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup)) { Debug.Print( String.Format( "CreateProcessInConsoleSession DuplicateTokenEx error: {0} Token does not have the privilege.", Marshal.GetLastWin32Error())); CloseHandle(hProcess); CloseHandle(hUserToken); CloseHandle(hPToken); return false; } if (bElevate) { tp.PrivilegeCount = 1; tp.Privileges = new int[3]; tp.Privileges[2] = SE_PRIVILEGE_ENABLED; tp.Privileges[1] = luid.HighPart; tp.Privileges[0] = luid.LowPart; //Adjust Token privilege if (!SetTokenInformation(hUserTokenDup, TOKEN_INFORMATION_CLASS.TokenSessionId, ref dwSessionId, (uint)IntPtr.Size)) { Debug.Print( String.Format( "CreateProcessInConsoleSession SetTokenInformation error: {0} Token does not have the privilege.", Marshal.GetLastWin32Error())); CloseHandle(hProcess); CloseHandle(hUserToken); CloseHandle(hPToken); CloseHandle(hUserTokenDup); return false; } if (!AdjustTokenPrivileges(hUserTokenDup, false, ref tp, Marshal.SizeOf(tp), /*(PTOKEN_PRIVILEGES)*/ IntPtr.Zero, IntPtr.Zero)) { int nErr = Marshal.GetLastWin32Error(); if (nErr == ERROR_NOT_ALL_ASSIGNED) { Debug.Print(String.Format( "CreateProcessInConsoleSession AdjustTokenPrivileges error: {0} Token does not have the privilege.", nErr)); } else { Debug.Print(String.Format("CreateProcessInConsoleSession AdjustTokenPrivileges error: {0}", nErr)); } } } isadmin = CheckIfAdminToken(hUserTokenDup); //Create Environment uint dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE; IntPtr pEnv = IntPtr.Zero; if (CreateEnvironmentBlock(ref pEnv, hUserTokenDup, true)) { dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; } else { pEnv = IntPtr.Zero; } // Launch the process in the client's logon session. bResult = CreateProcessAsUser( hUserTokenDup, // client's access token null, // file to execute CommandLine, // command line ref sa, // pointer to process SECURITY_ATTRIBUTES ref sa, // pointer to thread SECURITY_ATTRIBUTES false, // handles are not inheritable (int)dwCreationFlags, // creation flags pEnv, // pointer to new environment block null, // name of current directory ref si, // pointer to STARTUPINFO structure out pi // receives information about new process ); // End impersonation of client. //GetLastError should be 0 int iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error(); //Close handles task CloseHandle(hProcess); CloseHandle(hUserToken); CloseHandle(hUserTokenDup); CloseHandle(hPToken); return (iResultOfCreateProcessAsUser == 0) ? true : false; } 

你不能。 服务被隔离并在不同的会话(会话0)上运行,该会话与用户的会话(会话1,2,3等)隔离。