예제 #1
0
 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;
                }
            }
        }