internal static bool EnablePrivilege(string privilegeName, bool bEnablePrivilege) { Console.WriteLine($"Trying to enable {privilegeName}"); int returnLength = 0; var token = IntPtr.Zero; var tokenPrivileges = new TOKEN_PRIVILEGES { Privileges = new int[3] }; var oldTokenPrivileges = new TOKEN_PRIVILEGES { Privileges = new int[3] }; var tLUID = new LUID(); tokenPrivileges.PrivilegeCount = 1; if (bEnablePrivilege) { tokenPrivileges.Privileges[2] = SE_PRIVILEGE_ENABLED; } else { tokenPrivileges.Privileges[2] = 0; } var unmanagedTokenPrivileges = IntPtr.Zero; try { if (!NativeMethod.LookupPrivilegeValue(null, privilegeName, ref tLUID)) { Console.WriteLine($"Failed to Lookup {privilegeName}"); return(false); } var process = Process.GetCurrentProcess(); if (process.Handle == IntPtr.Zero) { Console.WriteLine($"Failed to get process handle"); return(false); } if (NativeMethod.OpenProcessToken(process.Handle, TOKEN_ALL_ACCESS, ref token) == 0) { Console.WriteLine($"Failed to open process token ({Marshal.GetLastWin32Error()})"); return(false); } tokenPrivileges.PrivilegeCount = 1; tokenPrivileges.Privileges[2] = SE_PRIVILEGE_ENABLED; tokenPrivileges.Privileges[1] = tLUID.HighPart; tokenPrivileges.Privileges[0] = tLUID.LowPart; const int bufLength = 256; unmanagedTokenPrivileges = Marshal.AllocHGlobal(bufLength); Marshal.StructureToPtr(tokenPrivileges, unmanagedTokenPrivileges, true); if (NativeMethod.AdjustTokenPrivileges(token, 0, unmanagedTokenPrivileges, bufLength, IntPtr.Zero, ref returnLength) == 0) { Console.WriteLine($"Failed to adjust privileges ({Marshal.GetLastWin32Error()})"); Console.WriteLine(new Win32Exception(Marshal.GetLastWin32Error())); return(false); } if (Marshal.GetLastWin32Error() != 0) { Console.WriteLine($"Failed to adjust privileges ({Marshal.GetLastWin32Error()})"); return(false); } Console.WriteLine($"Successfully enabled privilege {privilegeName}"); return(true); } catch (Exception ex) { Console.WriteLine($"Error while trying to enable {privilegeName}"); Console.WriteLine(ex); return(false); } finally { if (token != IntPtr.Zero) { NativeMethod.CloseHandle(token); } if (unmanagedTokenPrivileges != IntPtr.Zero) { Marshal.FreeHGlobal(unmanagedTokenPrivileges); } } }
private static bool StartProcessInSession(IntPtr sessionToken, string path, string arguments, string workingDirectory, string desktop) { if (sessionToken == null) { throw new ArgumentNullException(nameof(sessionToken)); } // Adjust token Console.WriteLine("Adjusting token ..."); if (!TokenAdjuster.EnablePrivilege("SeAssignPrimaryTokenPrivilege", true)) { Console.WriteLine("Failed to enable required privilege (SeAssignPrimaryTokenPrivilege)"); return(false); } Console.WriteLine($"Trying to start '{path}' with arguments '{arguments}' in working directory '{workingDirectory}' ..."); var duplicatedToken = IntPtr.Zero; var environment = IntPtr.Zero; var processInformation = new PROCESS_INFORMATION(); try { var securityAttributes = new SECURITY_ATTRIBUTES(); securityAttributes.Length = Marshal.SizeOf(securityAttributes); if (!NativeMethod.DuplicateTokenEx( sessionToken, GENERIC_ALL_ACCESS, ref securityAttributes, (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, (int)TOKEN_TYPE.TokenPrimary, ref duplicatedToken ) ) { Console.WriteLine($"Failed to duplicate token ({Marshal.GetLastWin32Error()})"); return(false); } if (!NativeMethod.CreateEnvironmentBlock(out environment, duplicatedToken, false)) { Console.WriteLine($"Failed to get environment ({Marshal.GetLastWin32Error()})"); return(false); } var startupInfo = new STARTUPINFO(); startupInfo.cb = Marshal.SizeOf(startupInfo); startupInfo.lpDesktop = desktop; startupInfo.wShowWindow = 5; // SW_SHOW if (!NativeMethod.CreateProcessAsUser( duplicatedToken, path, arguments, ref securityAttributes, ref securityAttributes, false, ProcessCreationFlags.NORMAL_PRIORITY_CLASS | ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT | ProcessCreationFlags.CREATE_NEW_CONSOLE | ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB, environment, workingDirectory, ref startupInfo, ref processInformation ) ) { Console.WriteLine($"Failed to start process ({Marshal.GetLastWin32Error()})"); return(false); } Console.WriteLine($"Process started as {processInformation.dwProcessID} ({Marshal.GetLastWin32Error()})"); return(true); } catch (Exception ex) { Console.WriteLine("Error while trying to start process as user"); Console.WriteLine(ex); return(false); } finally { if (processInformation.hProcess != IntPtr.Zero) { NativeMethod.CloseHandle(processInformation.hProcess); } if (processInformation.hThread != IntPtr.Zero) { NativeMethod.CloseHandle(processInformation.hThread); } if (duplicatedToken != IntPtr.Zero) { NativeMethod.CloseHandle(duplicatedToken); } if (environment != IntPtr.Zero) { NativeMethod.DestroyEnvironmentBlock(environment); } if (sessionToken != IntPtr.Zero) { NativeMethod.CloseHandle(sessionToken); } } }