Process.Avviare con credenziali diverse con UAC triggersto

Sto cercando di avviare un altro processo con Process.Start in esecuzione con credenziali diverse con il controllo dell’account utente triggersto. Ottengo il seguente errore:

System.ComponentModel.Win32Exception: errore di accesso: restrizione dell’account utente. Possibili cause sono le password vuote non consentite, le restrizioni delle ore di accesso o una restrizione dei criteri è stata applicata a System.Diagnostics.Process.StartWithCreateProcess (ProcessStartInfo startInfo) su System.Diagnostics.Process.Start ()
a System.Diagnostics.Process.Start (ProcessStartInfo startInfo)

Se spengo il controllo dell’account utente, funziona correttamente. Se avvio il processo senza specificare nome utente e password, funziona correttamente. Di seguito una copia del codice:

ProcessStartInfo processInfo = new ProcessStartInfo(); processInfo.Verb = "runas"; processInfo.FileName = command; processInfo.Arguments = parameters; processInfo.UserName = txtUserName.Text; processInfo.Password = password; processInfo.Domain = "myDomain"; processInfo.UseShellExecute = false; processInfo.LoadUserProfile = true; Process.Start(processInfo); 

Credo che questo abbia qualcosa a che fare con la sessione desktop, ma non sono sicuro del perché funzioni quando il controllo dell’account utente è distriggersto.

Qualsiasi idea su come farlo funzionare senza distriggersre UAC, modificare il registro o modificare le politiche locali / di gruppo sarebbe molto apprezzato.

Grazie

MODIFICARE

Il processo che ha il codice sopra è stato avviato come amministratore:

  static void Main(string[] args) { //make sure we are running with admin privileges if (VerifyIsAdmin()) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MyApp(args)); } } private static bool VerifyIsAdmin() { WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); bool isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator); if (!isAdmin) { ProcessStartInfo processInfo = new ProcessStartInfo(); processInfo.Verb = "runas"; processInfo.FileName = Application.ExecutablePath; Process.Start(processInfo); } return isAdmin; } 

MODIFICARE

Provato CreateProcessWithLogonW … Aveva lo stesso problema.

Dopo ulteriori ricerche, sembra che si tratti di un problema con i Criteri di gruppo che richiedono l’accesso con smart card (scforceoption). Detto questo, continuo a non capire perché funzioni quando il controllo dell’account utente è distriggersto. Dovrebbe comunque essere necessaria una smart card all’accesso.

Non sembra che sarò in grado di aggirare questo. Qualsiasi intuito / consiglio sarebbe apprezzato.

Devi fare quanto segue: 1. Ottieni chi è loggato e in questo utente ha un desktop attivo 2. Ottieni processo ‘handle avviato da questo utente 3. “Ruba” le credenziali da questo processo 4. Avvia il processo con quelle credenziali

Il seguente codice dovrebbe fare il trucco:

 using System; using System.Text; using System.Security; using System.Management; using System.Diagnostics; using System.Runtime.InteropServices; namespace Win32 { public class Win32API { #region WMI Constants private const String cstrScope = "root\\CIMV2"; private const String cstrLoggenInUser = "SELECT * FROM Win32_ComputerSystem"; #endregion #region Win32 API routines [StructLayout(LayoutKind.Sequential)] struct SECURITY_ATTRIBUTES { public Int32 Length; public IntPtr lpSecurityDescriptor; public Boolean bInheritHandle; } enum TOKEN_TYPE { TokenPrimary = 1, TokenImpersonation = 2 } enum TOKEN_INFORMATION_CLASS { TokenUser = 1, TokenGroups, TokenPrivileges, TokenOwner, TokenPrimaryGroup, TokenDefaultDacl, TokenSource, TokenType, TokenImpersonationLevel, TokenStatistics, TokenRestrictedSids, TokenSessionId, TokenGroupsAndPrivileges, TokenSessionReference, TokenSandBoxInert, TokenAuditPolicy, TokenOrigin, MaxTokenInfoClass // MaxTokenInfoClass should always be the last enum } [StructLayout(LayoutKind.Sequential)] struct STARTUPINFO { public Int32 cb; public String lpReserved; public String lpDesktop; public String lpTitle; public UInt32 dwX; public UInt32 dwY; public UInt32 dwXSize; public UInt32 dwYSize; public UInt32 dwXCountChars; public UInt32 dwYCountChars; public UInt32 dwFillAttribute; public UInt32 dwFlags; public short wShowWindow; public short cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; } [StructLayout(LayoutKind.Sequential)] struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public UInt32 dwProcessId; public UInt32 dwThreadId; } enum SECURITY_IMPERSONATION_LEVEL { SecurityAnonymous = 0, SecurityIdentification = 1, SecurityImpersonation = 2, SecurityDelegation = 3, } [StructLayout(LayoutKind.Sequential)] struct LUID { public Int32 LowPart; public Int32 HighPart; } [StructLayout(LayoutKind.Sequential)] struct LUID_AND_ATRIBUTES { LUID Luid; Int32 Attributes; } [StructLayout(LayoutKind.Sequential)] struct TOKEN_PRIVILEGES { public Int32 PrivilegeCount; //LUID_AND_ATRIBUTES [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public Int32[] Privileges; } const Int32 READ_CONTROL = 0x00020000; const Int32 STANDARD_RIGHTS_REQUIRED = 0x000F0000; const Int32 STANDARD_RIGHTS_READ = READ_CONTROL; const Int32 STANDARD_RIGHTS_WRITE = READ_CONTROL; const Int32 STANDARD_RIGHTS_EXECUTE = READ_CONTROL; const Int32 STANDARD_RIGHTS_ALL = 0x001F0000; const Int32 SPECIFIC_RIGHTS_ALL = 0x0000FFFF; const Int32 TOKEN_ASSIGN_PRIMARY = 0x0001; const Int32 TOKEN_DUPLICATE = 0x0002; const Int32 TOKEN_IMPERSONATE = 0x0004; const Int32 TOKEN_QUERY = 0x0008; const Int32 TOKEN_QUERY_SOURCE = 0x0010; const Int32 TOKEN_ADJUST_PRIVILEGES = 0x0020; const Int32 TOKEN_ADJUST_GROUPS = 0x0040; const Int32 TOKEN_ADJUST_DEFAULT = 0x0080; const Int32 TOKEN_ADJUST_SESSIONID = 0x0100; const Int32 TOKEN_ALL_ACCESS_P = ( STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT); const Int32 TOKEN_ALL_ACCESS = TOKEN_ALL_ACCESS_P | TOKEN_ADJUST_SESSIONID; const Int32 TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY; const Int32 TOKEN_WRITE = STANDARD_RIGHTS_WRITE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT; const Int32 TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE; const UInt32 MAXIMUM_ALLOWED = 0x2000000; const Int32 CREATE_NEW_PROCESS_GROUP = 0x00000200; const Int32 CREATE_UNICODE_ENVIRONMENT = 0x00000400; const Int32 IDLE_PRIORITY_CLASS = 0x40; const Int32 NORMAL_PRIORITY_CLASS = 0x20; const Int32 HIGH_PRIORITY_CLASS = 0x80; const Int32 REALTIME_PRIORITY_CLASS = 0x100; const Int32 CREATE_NEW_CONSOLE = 0x00000010; const string SE_DEBUG_NAME = "SeDebugPrivilege"; const string SE_RESTORE_NAME = "SeRestorePrivilege"; const string SE_BACKUP_NAME = "SeBackupPrivilege"; const Int32 SE_PRIVILEGE_ENABLED = 0x0002; const Int32 ERROR_NOT_ALL_ASSIGNED = 1300; [StructLayout(LayoutKind.Sequential)] struct PROCESSENTRY32 { UInt32 dwSize; UInt32 cntUsage; UInt32 th32ProcessID; IntPtr th32DefaultHeapID; UInt32 th32ModuleID; UInt32 cntThreads; UInt32 th32ParentProcessID; Int32 pcPriClassBase; UInt32 dwFlags; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] string szExeFile; } const UInt32 TH32CS_SNAPPROCESS = 0x00000002; const Int32 INVALID_HANDLE_VALUE = -1; [DllImport("kernel32.dll", SetLastError = true)] static extern Boolean CloseHandle(IntPtr hSnapshot); [DllImport("kernel32.dll")] public static extern UInt32 WTSGetActiveConsoleSessionId(); [DllImport("Wtsapi32.dll")] static extern UInt32 WTSQueryUserToken(UInt32 SessionId, ref IntPtr phToken); [DllImport("advapi32.dll", SetLastError = true)] static extern Boolean LookupPrivilegeValue(IntPtr lpSystemName, string lpname, [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid); [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] extern static Boolean CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, Boolean bInheritHandle, Int32 dwCreationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); [DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")] extern static Boolean DuplicateTokenEx(IntPtr ExistingTokenHandle, UInt32 dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, Int32 TokenType, Int32 ImpersonationLevel, ref IntPtr DuplicateTokenHandle); [DllImport("kernel32.dll")] static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Boolean bInheritHandle, UInt32 dwProcessId); [DllImport("advapi32", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute] static extern Boolean OpenProcessToken(IntPtr ProcessHandle, // handle to process Int32 DesiredAccess, // desired access to process ref IntPtr TokenHandle); // handle to open access token [DllImport("advapi32.dll", SetLastError = true)] static extern Boolean AdjustTokenPrivileges(IntPtr TokenHandle, Boolean DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, Int32 BufferLength, IntPtr PreviousState, IntPtr ReturnLength); [DllImport("advapi32.dll", SetLastError = true)] static extern Boolean SetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, ref UInt32 TokenInformation, UInt32 TokenInformationLength); [DllImport("userenv.dll", SetLastError = true)] static extern Boolean CreateEnvironmentBlock(ref IntPtr lpEnvironment, IntPtr hToken, Boolean bInherit); #endregion #region Methods ///  /// Method returns name of the user that logged in on workstation ///  public static String GetLoggedInUserName() { String userName = String.Empty; try { ManagementObjectSearcher searcher = new ManagementObjectSearcher(cstrScope, cstrLoggenInUser); foreach (ManagementObject queryObj in searcher.Get()) { userName = queryObj["UserName"].ToString(); break; } } catch { userName = String.Empty; } return userName; } ///  /// Creates the process in the interactive desktop with credentials of the logged in user. ///  public static Boolean CreateProcessAsUser(String commandLine, String workingDirectory, String userAppName, out StringBuilder output) { Boolean processStarted = false; output = new StringBuilder(); try { UInt32 dwSessionId = WTSGetActiveConsoleSessionId(); output.AppendLine(String.Format("Active console session Id: {0}", dwSessionId)); IntPtr hUserToken = IntPtr.Zero; WTSQueryUserToken(dwSessionId, ref hUserToken); if (hUserToken != IntPtr.Zero) { output.AppendLine(String.Format("WTSQueryUserToken() OK (hUserToken:{0})", hUserToken)); Process[] processes = Process.GetProcessesByName(userAppName); if (processes.Length == 0) { output.AppendLine(String.Format("Application '{0}' can not be found in the running processes", userAppName)); return false; } Int32 userAppProcessId = -1; for (Int32 k = 0; k < processes.Length; k++) { output.AppendLine(String.Format("Process: '{0}', PID: {1}, Handle: {2}, Session: {3}", processes[k].ProcessName, processes[k].Id, processes[k].Handle, processes[k].SessionId)); if ((UInt32)processes[k].SessionId == dwSessionId) { userAppProcessId = processes[k].Id; } } if (userAppProcessId == -1) { output.AppendLine(String.Format("Application '{0}' is not found in the processes of the current session", userAppName)); return false; } IntPtr hProcess = OpenProcess((Int32)MAXIMUM_ALLOWED, false, (UInt32)userAppProcessId); IntPtr hPToken = IntPtr.Zero; OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE, ref hPToken); if (hPToken != IntPtr.Zero) { output.AppendLine(String.Format("OpenProcessToken() OK (Token: {0})", hPToken)); LUID luid = new LUID(); if (LookupPrivilegeValue(IntPtr.Zero, SE_DEBUG_NAME, ref luid)) { output.AppendLine(String.Format("LookupPrivilegeValue() OK (High: {0}, Low: {1})", luid.HighPart, luid.LowPart)); SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); sa.Length = Marshal.SizeOf(sa); IntPtr hUserTokenDup = IntPtr.Zero; DuplicateTokenEx(hPToken, (Int32)MAXIMUM_ALLOWED, ref sa, (Int32)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (Int32)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup); if (hUserTokenDup != IntPtr.Zero) { output.AppendLine(String.Format("DuplicateTokenEx() OK (hToken: {0})", hUserTokenDup)); TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES { PrivilegeCount = 1, Privileges = new Int32[3] }; tp.Privileges[1] = luid.HighPart; tp.Privileges[0] = luid.LowPart; tp.Privileges[2] = SE_PRIVILEGE_ENABLED; //Adjust Token privilege if (SetTokenInformation(hUserTokenDup, TOKEN_INFORMATION_CLASS.TokenSessionId, ref dwSessionId, (UInt32)IntPtr.Size)) { output.AppendLine(String.Format("SetTokenInformation() OK")); if (AdjustTokenPrivileges(hUserTokenDup, false, ref tp, Marshal.SizeOf(tp), IntPtr.Zero, IntPtr.Zero)) { output.AppendLine("AdjustTokenPrivileges() OK"); Int32 dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE; IntPtr pEnv = IntPtr.Zero; if (CreateEnvironmentBlock(ref pEnv, hUserTokenDup, true)) { dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; } else { output.AppendLine(String.Format("CreateEnvironmentBlock() FAILED (Last Error: {0})", Marshal.GetLastWin32Error())); pEnv = IntPtr.Zero; } // Launch the process in the client's logon session. PROCESS_INFORMATION pi; STARTUPINFO si = new STARTUPINFO(); si.cb = Marshal.SizeOf(si); si.lpDesktop = "winsta0\\default"; output.AppendLine(String.Format("CreateProcess (Path:{0}, CurrDir:{1})", commandLine, workingDirectory)); if (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 dwCreationFlags, // creation flags pEnv, // pointer to new environment block workingDirectory, // name of current directory ref si, // pointer to STARTUPINFO structure out pi // receives information about new process )) { processStarted = true; output.AppendLine(String.Format("CreateProcessAsUser() OK (PID: {0})", pi.dwProcessId)); } else { output.AppendLine(String.Format("CreateProcessAsUser() failed (Last Error: {0})", Marshal.GetLastWin32Error())); } } else { output.AppendLine(String.Format("AdjustTokenPrivileges() failed (Last Error: {0})", Marshal.GetLastWin32Error())); } } else { output.AppendLine(String.Format("SetTokenInformation() failed (Last Error: {0})", Marshal.GetLastWin32Error())); } CloseHandle(hUserTokenDup); } else { output.AppendLine(String.Format("DuplicateTokenEx() failed (Last Error: {0})", Marshal.GetLastWin32Error())); } } else { output.AppendLine(String.Format("LookupPrivilegeValue() failed (Last Error: {0})", Marshal.GetLastWin32Error())); } CloseHandle(hPToken); } else { output.AppendLine(String.Format("OpenProcessToken() failed (Last Error: {0})", Marshal.GetLastWin32Error())); } CloseHandle(hUserToken); } else { output.AppendLine(String.Format("WTSQueryUserToken failed: {0}", Marshal.GetLastWin32Error())); } } catch (Exception ex) { output.AppendLine("Exception occurred: " + ex.Message); } return processStarted; } #endregion } } 

Uso:

 try { StringBuilder output = new StringBuilder(); if (!Win32API.CreateProcessAsUser("C:\\WINDOWS\\notepad.exe", "C:\\WINDOWS\\", "winlogon", out output)) throw new Win32Exception(output.ToString()); else throw new Win32Exception("Process RUN!!!"); } catch (Win32Exception ex) { File.WriteAllText("c:\\hello!.txt", ex.Message + " " + ex.ErrorCode.ToString()); } 

I crediti per il codice vanno a Forcas da rsdn.ru

Ho trovato un vecchio progetto in cui ho usato il codice qui sotto e ha funzionato in quel momento (sembra simile al tuo), forse non sarà di aiuto ma comunque vale la pena provare:

 ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.UseShellExecute = true; startInfo.WorkingDirectory = Environment.CurrentDirectory; startInfo.FileName = Application.ExecutablePath; startInfo.Verb = "runas"; try { Process p = Process.Start(startInfo); } catch(System.ComponentModel.Win32Exception ex) { return; } 

Sembra che tu non sia il solo a risolvere questo problema e potrebbe non essere ansible mentre stai provando a fare:

http://www.icodefactory.com/lab/post/UAC-Revealed-7e-elevation-of-rights-from-NET-as-commonly-misunderstood.aspx

È solo un’ipotesi, ma forse è ansible richiedere i privilegi di amministratore e quindi impersonare l’utente e quindi finalmente avviare il processo mentre si impersona?

Modifica: puoi anche provare PInvoke che in base a un commento su questa pagina sta lavorando per avviare un processo con un altro utente: http://blogs.msdn.com/thottams/archive/2006/08/11/696013.aspx

Prova ad aggiungere file manifest per quell’altro processo che vuoi avviare. Windows analizzerà il file manifest e ti presenterà con la finestra di dialogo UAC prima dell’avvio del processo.

Ecco le informazioni su come incorporare file manifest link1 e link2

HTH