Esempio n. 1
0
        /// <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>
        /// <param name="selectedIntegrityLevel">
        /// Numeric representation of integrity level with which process has to be started
        /// </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 CreateSpecificIntegrityProcess(string commandLine, int selectedIntegrityLevel)
        {
            SafeTokenHandle     hToken        = null;
            SafeTokenHandle     hNewToken     = null;
            IntPtr              pIntegritySid = IntPtr.Zero;
            int                 cbTokenInfo   = 0;
            IntPtr              pTokenInfo    = IntPtr.Zero;
            STARTUPINFO         si            = new STARTUPINFO();
            PROCESS_INFORMATION pi            = new PROCESS_INFORMATION();

            try
            {
                // Open the primary access token of the process.
                if (!NativeMethod.OpenProcessToken(Process.GetCurrentProcess().Handle,
                                                   NativeMethod.TOKEN_DUPLICATE | NativeMethod.TOKEN_ADJUST_DEFAULT |
                                                   NativeMethod.TOKEN_QUERY | NativeMethod.TOKEN_ASSIGN_PRIMARY,
                                                   out hToken))
                {
                    throw new Win32Exception();
                }

                // Duplicate the primary token of the current process.
                if (!NativeMethod.DuplicateTokenEx(hToken, 0, IntPtr.Zero,
                                                   SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
                                                   TOKEN_TYPE.TokenPrimary, out hNewToken))
                {
                    throw new Win32Exception();
                }

                // Create the low integrity SID.
                if (!NativeMethod.AllocateAndInitializeSid(
                        ref NativeMethod.SECURITY_MANDATORY_LABEL_AUTHORITY, 1,
                        selectedIntegrityLevel,
                        0, 0, 0, 0, 0, 0, 0, out pIntegritySid))
                {
                    throw new Win32Exception();
                }

                TOKEN_MANDATORY_LABEL tml;
                tml.Label.Attributes = NativeMethod.SE_GROUP_INTEGRITY;
                tml.Label.Sid        = pIntegritySid;

                // Marshal the TOKEN_MANDATORY_LABEL struct to the native memory.
                cbTokenInfo = Marshal.SizeOf(tml);
                pTokenInfo  = Marshal.AllocHGlobal(cbTokenInfo);
                Marshal.StructureToPtr(tml, pTokenInfo, false);

                // Set the integrity level in the access token to low.
                if (!NativeMethod.SetTokenInformation(hNewToken,
                                                      TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenInfo,
                                                      cbTokenInfo + NativeMethod.GetLengthSid(pIntegritySid)))
                {
                    throw new Win32Exception();
                }

                // Create the new process at the Low integrity level.
                si.cb = Marshal.SizeOf(si);
                if (!NativeMethod.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();
                    hToken = null;
                }
                if (hNewToken != null)
                {
                    hNewToken.Close();
                    hNewToken = null;
                }
                if (pIntegritySid != IntPtr.Zero)
                {
                    NativeMethod.FreeSid(pIntegritySid);
                    pIntegritySid = IntPtr.Zero;
                }
                if (pTokenInfo != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pTokenInfo);
                    pTokenInfo  = IntPtr.Zero;
                    cbTokenInfo = 0;
                }
                if (pi.hProcess != IntPtr.Zero)
                {
                    NativeMethod.CloseHandle(pi.hProcess);
                    pi.hProcess = IntPtr.Zero;
                }
                if (pi.hThread != IntPtr.Zero)
                {
                    NativeMethod.CloseHandle(pi.hThread);
                    pi.hThread = IntPtr.Zero;
                }
            }
        }