public static extern bool CreateProcessAsUser( SafeTokenHandle hToken, string applicationName, string commandLine, IntPtr pProcessAttributes, IntPtr pThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr pEnvironment, string currentDirectory, ref STARTUPINFO startupInfo, out PROCESS_INFORMATION processInformation);
/// <summary> /// The function launches an application at low integrity level. /// </summary> /// <param name="commandLine"> /// The command line to be executed. The maximum length of this string is 32K /// characters. /// </param> /// <remarks> /// To start a low-integrity process, /// 1) Duplicate the handle of the current process, which is at medium /// integrity level. /// 2) Use SetTokenInformation to set the integrity level in the access token /// to Low. /// 3) Use CreateProcessAsUser to create a new process using the handle to /// the low integrity access token. /// </remarks> public static void CreateLowIntegrityProcess(string commandLine) { SafeTokenHandle hToken = null; SafeTokenHandle hNewToken = null; IntPtr pIntegritySid = IntPtr.Zero; IntPtr pTokenInfo = IntPtr.Zero; STARTUPINFO si = new STARTUPINFO(); PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); try { // Open the primary access token of the process. if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, NativeMethods.TOKEN_DUPLICATE | NativeMethods.TOKEN_ADJUST_DEFAULT | NativeMethods.TOKEN_QUERY | NativeMethods.TOKEN_ASSIGN_PRIMARY, out hToken)) { throw new Win32Exception(); } // Duplicate the primary token of the current process. if (!NativeMethods.DuplicateTokenEx(hToken, 0, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out hNewToken)) { throw new Win32Exception(); } // Create the low integrity SID. if (!NativeMethods.AllocateAndInitializeSid( ref NativeMethods.SECURITY_MANDATORY_LABEL_AUTHORITY, 1, NativeMethods.SECURITY_MANDATORY_LOW_RID, 0, 0, 0, 0, 0, 0, 0, out pIntegritySid)) { throw new Win32Exception(); } TOKEN_MANDATORY_LABEL tml; tml.Label.Attributes = NativeMethods.SE_GROUP_INTEGRITY; tml.Label.Sid = pIntegritySid; // Marshal the TOKEN_MANDATORY_LABEL struct to the native memory. int cbTokenInfo = Marshal.SizeOf(tml); pTokenInfo = Marshal.AllocHGlobal(cbTokenInfo); Marshal.StructureToPtr(tml, pTokenInfo, false); // Set the integrity level in the access token to low. if (!NativeMethods.SetTokenInformation(hNewToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenInfo, cbTokenInfo + NativeMethods.GetLengthSid(pIntegritySid))) { throw new Win32Exception(); } // Create the new process at the Low integrity level. si.cb = Marshal.SizeOf(si); if (!NativeMethods.CreateProcessAsUser(hNewToken, null, commandLine, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref si, out pi)) { throw new Win32Exception(); } } finally { // Centralized cleanup for all allocated resources. if (hToken != null) { hToken.Close(); } if (hNewToken != null) { hNewToken.Close(); } if (pIntegritySid != IntPtr.Zero) { NativeMethods.FreeSid(pIntegritySid); } if (pTokenInfo != IntPtr.Zero) { Marshal.FreeHGlobal(pTokenInfo); } if (pi.hProcess != IntPtr.Zero) { NativeMethods.CloseHandle(pi.hProcess); pi.hProcess = IntPtr.Zero; } if (pi.hThread != IntPtr.Zero) { NativeMethods.CloseHandle(pi.hThread); pi.hThread = IntPtr.Zero; } } }