예제 #1
0
 internal static partial bool DuplicateTokenEx(
     SafeTokenHandle ExistingTokenHandle,
     TokenAccessLevels DesiredAccess,
     IntPtr TokenAttributes,
     SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
     System.Security.Principal.TokenType TokenType,
     ref SafeTokenHandle?DuplicateTokenHandle);
예제 #2
0
        internal static int SetThreadToken(SafeTokenHandle?hToken)
        {
            int hr = 0;

            if (!Interop.Advapi32.SetThreadToken(IntPtr.Zero, hToken))
            {
                hr = Marshal.GetHRForLastWin32Error();
            }
            return(hr);
        }
예제 #3
0
        private static unsafe void SetPrivilege(string privilegeName, int attrib)
        {
            // this is only a "pseudo handle" to the current process - no need to close it later
            SafeProcessHandle processHandle = Interop.Kernel32.GetCurrentProcess();

            SafeTokenHandle?hToken = null;

            try
            {
                // get the process token so we can adjust the privilege on it.  We DO need to
                // close the token when we're done with it.
                if (!Interop.Advapi32.OpenProcessToken(processHandle, Interop.Kernel32.HandleOptions.TOKEN_ADJUST_PRIVILEGES, out hToken))
                {
                    throw new Win32Exception();
                }

                if (!Interop.Advapi32.LookupPrivilegeValue(null, privilegeName, out Interop.Advapi32.LUID luid))
                {
                    throw new Win32Exception();
                }

                Interop.Advapi32.TOKEN_PRIVILEGE tp;
                tp.PrivilegeCount        = 1;
                tp.Privileges.Luid       = luid;
                tp.Privileges.Attributes = (uint)attrib;

                Interop.Advapi32.AdjustTokenPrivileges(hToken, false, &tp, 0, null, null);

                // AdjustTokenPrivileges can return true even if it failed to
                // set the privilege, so we need to use GetLastError
                if (Marshal.GetLastWin32Error() != Interop.Errors.ERROR_SUCCESS)
                {
                    throw new Win32Exception();
                }
            }
            finally
            {
                if (hToken != null)
                {
                    hToken.Dispose();
                }
            }
        }
        static unsafe ProcessManager()
        {
            // In order to query information (OpenProcess) on some protected processes
            // like csrss, we need SeDebugPrivilege privilege.
            // After removing the dependency on Performance Counter, we don't have a chance
            // to run the code in CLR performance counter to ask for this privilege.
            // So we will try to get the privilege here.
            // We could fail if the user account doesn't have right to do this, but that's fair.

            Interop.Advapi32.LUID luid;
            if (!Interop.Advapi32.LookupPrivilegeValue(null, Interop.Advapi32.SeDebugPrivilege, out luid))
            {
                return;
            }

            SafeTokenHandle?tokenHandle = null;

            try
            {
                if (!Interop.Advapi32.OpenProcessToken(
                        Interop.Kernel32.GetCurrentProcess(),
                        Interop.Kernel32.HandleOptions.TOKEN_ADJUST_PRIVILEGES,
                        out tokenHandle))
                {
                    return;
                }

                Interop.Advapi32.TOKEN_PRIVILEGE tp;
                tp.PrivilegeCount        = 1;
                tp.Privileges.Luid       = luid;
                tp.Privileges.Attributes = Interop.Advapi32.SEPrivileges.SE_PRIVILEGE_ENABLED;

                // AdjustTokenPrivileges can return true even if it didn't succeed (when ERROR_NOT_ALL_ASSIGNED is returned).
                Interop.Advapi32.AdjustTokenPrivileges(tokenHandle, false, &tp, 0, null, null);
            }
            finally
            {
                if (tokenHandle != null)
                {
                    tokenHandle.Dispose();
                }
            }
        }
        private static bool GetCurrentProcessIntegrity(out int integrityLevel)
        {
            integrityLevel = 0;
            SafeTokenHandle?safeTokenHandle = null;
            var             num             = IntPtr.Zero;

            try
            {
                if (!Process.GetCurrentProcess().SafeHandle.OpenAccessToken(8, out safeTokenHandle))
                {
                    return(false);
                }
                if (!safeTokenHandle.GetIntegrityLevelTokenSize(out var tokenSize))
                {
                    return(false);
                }
                num = Marshal.AllocHGlobal((int)tokenSize);
                if (num == IntPtr.Zero)
                {
                    return(false);
                }
                if (!safeTokenHandle.GetIntegrityLevelToken(tokenSize, num))
                {
                    return(false);
                }

                integrityLevel = num.GetIntegrityLevel();
                return(true);
            }
            finally
            {
                safeTokenHandle?.CloseTokenHandleIfOpened();
                if (num != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(num);
                }
            }
        }
예제 #6
0
            private void Dispose(bool disposing)
            {
                if (this.disposed)
                {
                    return;
                }

                if (disposing)
                {
                    if (this.threadHandle != null)
                    {
                        this.threadHandle.Dispose();
                        this.threadHandle = null !;
                    }
                }

                if (this.isImpersonating)
                {
                    Interop.Advapi32.RevertToSelf();
                }

                this.disposed = true;
            }
예제 #7
0
            public TlsContents()
            {
                int  error        = 0;
                int  cachingError = 0;
                bool success      = true;

                if (processHandle.IsInvalid)
                {
                    lock (syncRoot)
                    {
                        if (processHandle.IsInvalid)
                        {
                            SafeTokenHandle localProcessHandle;
                            if (false == Interop.Advapi32.OpenProcessToken(
                                    Interop.Kernel32.GetCurrentProcess(),
                                    TokenAccessLevels.Duplicate,
                                    out localProcessHandle))
                            {
                                cachingError = Marshal.GetLastWin32Error();
                                success      = false;
                            }
                            processHandle = localProcessHandle;
                        }
                    }
                }

                try
                {
                    //
                    // Open the thread token; if there is no thread token, get one from
                    // the process token by impersonating self.
                    //

                    SafeTokenHandle?threadHandleBefore = this.threadHandle;
                    error = OpenThreadToken(
                        TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges,
                        WinSecurityContext.Process,
                        out this.threadHandle);
                    unchecked { error &= ~(int)0x80070000; }

                    if (error != 0)
                    {
                        if (success == true)
                        {
                            this.threadHandle = threadHandleBefore;

                            if (error != Interop.Errors.ERROR_NO_TOKEN)
                            {
                                success = false;
                            }

                            System.Diagnostics.Debug.Assert(this.isImpersonating == false, "Incorrect isImpersonating state");

                            if (success == true)
                            {
                                error = 0;
                                if (false == Interop.Advapi32.DuplicateTokenEx(
                                        processHandle,
                                        TokenAccessLevels.Impersonate | TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges,
                                        IntPtr.Zero,
                                        Interop.Advapi32.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
                                        System.Security.Principal.TokenType.TokenImpersonation,
                                        ref this.threadHandle))
                                {
                                    error   = Marshal.GetLastWin32Error();
                                    success = false;
                                }
                            }

                            if (success == true)
                            {
                                error = SetThreadToken(this.threadHandle);
                                unchecked { error &= ~(int)0x80070000; }

                                if (error != 0)
                                {
                                    success = false;
                                }
                            }

                            if (success == true)
                            {
                                this.isImpersonating = true;
                            }
                        }
                        else
                        {
                            error = cachingError;
                        }
                    }
                    else
                    {
                        success = true;
                    }
                }
                finally
                {
                    if (!success)
                    {
                        Dispose();
                    }
                }

                if (error == Interop.Errors.ERROR_NOT_ENOUGH_MEMORY)
                {
                    throw new OutOfMemoryException();
                }
                else if (error == Interop.Errors.ERROR_ACCESS_DENIED ||
                         error == Interop.Errors.ERROR_CANT_OPEN_ANONYMOUS)
                {
                    throw new UnauthorizedAccessException();
                }
                else if (error != 0)
                {
                    System.Diagnostics.Debug.Fail($"WindowsIdentity.GetCurrentThreadToken() failed with unrecognized error code {error}");
                    throw new InvalidOperationException();
                }
            }
        /// <summary>
        /// The function gets the integrity level of the current process. Integrity level is only
        /// available on Windows Vista and newer operating systems, thus GetProcessIntegrityLevel
        /// throws a C++ exception if it is called on systems prior to Windows Vista.
        /// </summary>
        /// <returns>
        /// Returns the integrity level of the current process. It is usually one of these values:
        ///
        /// SECURITY_MANDATORY_UNTRUSTED_RID - means untrusted level. It is used by processes
        /// started by the Anonymous group. Blocks most write access. (SID: S-1-16-0x0)
        ///
        /// SECURITY_MANDATORY_LOW_RID - means low integrity level. It is used by Protected Mode
        /// Internet Explorer. Blocks write acess to most objects (such as files and registry keys)
        /// on the system. (SID: S-1-16-0x1000)
        ///
        /// SECURITY_MANDATORY_MEDIUM_RID - means medium integrity level. It is used by normal
        /// applications being launched while UAC is enabled. (SID: S-1-16-0x2000)
        ///
        /// SECURITY_MANDATORY_HIGH_RID - means high integrity level. It is used by administrative
        /// applications launched through elevation when UAC is enabled, or normal applications if
        /// UAC is disabled and the user is an administrator. (SID: S-1-16-0x3000)
        ///
        /// SECURITY_MANDATORY_SYSTEM_RID - means system integrity level. It is used by services and
        /// other system-level applications (such as Wininit, Winlogon, Smss, etc.) (SID: S-1-16-0x4000)
        /// </returns>
        /// <exception cref="System.ComponentModel.Win32Exception">
        /// When any native Windows API call fails, the function throws a Win32Exception with the
        /// last error code.
        /// </exception>
        public static int GetProcessIntegrityLevel()
        {
            int             IL        = -1;
            SafeTokenHandle?hToken    = null;
            int             cbTokenIL = 0;
            IntPtr          pTokenIL  = IntPtr.Zero;

            try
            {
                // Open the access token of the current process with TOKEN_QUERY.
                if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
                                                    NativeMethods.TOKEN_QUERY, out hToken))
                {
                    throw new Win32Exception();
                }

                // Then we must query the size of the integrity level information associated with
                // the token. Note that we expect GetTokenInformation to return false with the
                // ERROR_INSUFFICIENT_BUFFER error code because we've given it a null buffer. On
                // exit cbTokenIL will tell the size of the group information.
                if (!NativeMethods.GetTokenInformation(hToken,
                                                       TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, IntPtr.Zero, 0,
                                                       out cbTokenIL))
                {
                    int error = Marshal.GetLastWin32Error();
                    if (error != NativeMethods.ERROR_INSUFFICIENT_BUFFER)
                    {
                        // When the process is run on operating systems prior to Windows Vista,
                        // GetTokenInformation returns false with the ERROR_INVALID_PARAMETER error
                        // code because TokenIntegrityLevel is not supported on those OS's.
                        throw new Win32Exception(error);
                    }
                }

                // Now we allocate a buffer for the integrity level information.
                pTokenIL = Marshal.AllocHGlobal(cbTokenIL);
                if (pTokenIL == IntPtr.Zero)
                {
                    throw new Win32Exception();
                }

                // Now we ask for the integrity level information again. This may fail if an
                // administrator has added this account to an additional group between our first
                // call to GetTokenInformation and this one.
                if (!NativeMethods.GetTokenInformation(hToken,
                                                       TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenIL, cbTokenIL,
                                                       out cbTokenIL))
                {
                    throw new Win32Exception();
                }

                // Marshal the TOKEN_MANDATORY_LABEL struct from native to .NET object.
                var tokenMandatoryLabel = Marshal.PtrToStructure(pTokenIL, typeof(TOKEN_MANDATORY_LABEL));

                if (tokenMandatoryLabel is TOKEN_MANDATORY_LABEL tokenIL)
                {
                    // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. S-1-16-0x1000
                    // stands for low integrity level SID). There is one and only one subauthority.
                    IntPtr pIL = NativeMethods.GetSidSubAuthority(tokenIL.Label.Sid, 0);
                    IL = Marshal.ReadInt32(pIL);
                }
                else
                {
#pragma warning disable CA1303 // Do not pass literals as localized parameters
                    throw new NullReferenceException(nameof(tokenMandatoryLabel));
#pragma warning restore CA1303 // Do not pass literals as localized parameters
                }
            }
            finally
            {
                // Centralized cleanup for all allocated resources.
                if (hToken != null)
                {
                    hToken.Close();
                }
                if (pTokenIL != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pTokenIL);
                }
            }

            return(IL);
        }
        /// <summary>
        /// The function checks whether the primary access token of the process belongs to user
        /// account that is a member of the local Administrators group, even if it currently is not elevated.
        /// </summary>
        /// <returns>
        /// Returns true if the primary access token of the process belongs to user account that is
        /// a member of the local Administrators group. Returns false if the token does not.
        /// </returns>
        /// <exception cref="System.ComponentModel.Win32Exception">
        /// When any native Windows API call fails, the function throws a Win32Exception with the
        /// last error code.
        /// </exception>
        internal static bool IsUserInAdminGroup()
        {
            bool            fInAdminGroup  = false;
            SafeTokenHandle?hToken         = null;
            SafeTokenHandle?hTokenToCheck  = null;
            IntPtr          pElevationType = IntPtr.Zero;
            IntPtr          pLinkedToken   = IntPtr.Zero;
            int             cbSize         = 0;

            try
            {
                // Open the access token of the current process for query and duplicate.
                if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
                                                    NativeMethods.TOKEN_QUERY | NativeMethods.TOKEN_DUPLICATE, out hToken))
                {
                    throw new Win32Exception();
                }

                // Determine whether system is running Windows Vista or later operating systems
                // (major version >= 6) because they support linked tokens, but previous versions
                // (major version < 6) do not.
                if (Environment.OSVersion.Version.Major >= 6)
                {
                    // Running Windows Vista or later (major version >= 6). Determine token type:
                    // limited, elevated, or default.

                    // Allocate a buffer for the elevation type information.
                    cbSize         = sizeof(TOKEN_ELEVATION_TYPE);
                    pElevationType = Marshal.AllocHGlobal(cbSize);
                    if (pElevationType == IntPtr.Zero)
                    {
                        throw new Win32Exception();
                    }

                    // Retrieve token elevation type information.
                    if (!NativeMethods.GetTokenInformation(hToken,
                                                           TOKEN_INFORMATION_CLASS.TokenElevationType, pElevationType,
                                                           cbSize, out cbSize))
                    {
                        throw new Win32Exception();
                    }

                    // Marshal the TOKEN_ELEVATION_TYPE enum from native to .NET.
                    TOKEN_ELEVATION_TYPE elevType = (TOKEN_ELEVATION_TYPE)
                                                    Marshal.ReadInt32(pElevationType);

                    // If limited, get the linked elevated token for further check.
                    if (elevType == TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited)
                    {
                        // Allocate a buffer for the linked token.
                        cbSize       = IntPtr.Size;
                        pLinkedToken = Marshal.AllocHGlobal(cbSize);
                        if (pLinkedToken == IntPtr.Zero)
                        {
                            throw new Win32Exception();
                        }

                        // Get the linked token.
                        if (!NativeMethods.GetTokenInformation(hToken,
                                                               TOKEN_INFORMATION_CLASS.TokenLinkedToken, pLinkedToken,
                                                               cbSize, out cbSize))
                        {
                            throw new Win32Exception();
                        }

                        // Marshal the linked token value from native to .NET.
                        IntPtr hLinkedToken = Marshal.ReadIntPtr(pLinkedToken);
                        hTokenToCheck = new SafeTokenHandle(hLinkedToken);
                    }
                }

                // CheckTokenMembership requires an impersonation token. If we just got a linked
                // token, it already is an impersonation token. If we did not get a linked token,
                // duplicate the original into an impersonation token for CheckTokenMembership.
                if (hTokenToCheck == null)
                {
                    if (!NativeMethods.DuplicateToken(hToken,
                                                      SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
                                                      out hTokenToCheck))
                    {
                        throw new Win32Exception();
                    }
                }

                // Check if the token to be checked contains admin SID.
                using WindowsIdentity id = new WindowsIdentity(hTokenToCheck.DangerousGetHandle());
                WindowsPrincipal principal = new WindowsPrincipal(id);
                fInAdminGroup = principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
            finally
            {
                // Centralized cleanup for all allocated resources.
                if (hToken != null)
                {
                    hToken.Close();
                }
                if (hTokenToCheck != null)
                {
                    hTokenToCheck.Close();
                }
                if (pElevationType != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pElevationType);
                }
                if (pLinkedToken != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pLinkedToken);
                }
            }

            return(fInAdminGroup);
        }
        /// <summary>
        /// The function gets the elevation information of the current process. It dictates whether
        /// the process is elevated or not. Token elevation is only available on Windows Vista and
        /// newer operating systems, thus IsProcessElevated throws a C++ exception if it is called
        /// on systems prior to Windows Vista. It is not appropriate to use this function to
        /// determine whether a process is run as administartor.
        /// </summary>
        /// <returns>Returns true if the process is elevated. Returns false if it is not.</returns>
        /// <exception cref="System.ComponentModel.Win32Exception">
        /// When any native Windows API call fails, the function throws a Win32Exception with the
        /// last error code.
        /// </exception>
        /// <remarks>
        /// TOKEN_INFORMATION_CLASS provides TokenElevationType to check the elevation type
        /// (TokenElevationTypeDefault / TokenElevationTypeLimited /
        /// TokenElevationTypeFull) of the process. It is different from TokenElevation in that,
        /// when UAC is turned off, elevation type always returns TokenElevationTypeDefault even
        /// though the process is elevated (Integrity Level == High). In other words, it is not safe
        /// to say if the process is elevated based on elevation type. Instead, we should use TokenElevation.
        /// </remarks>
        internal static bool IsProcessElevated()
        {
            bool            fIsElevated      = false;
            SafeTokenHandle?hToken           = null;
            int             cbTokenElevation = 0;
            IntPtr          pTokenElevation  = IntPtr.Zero;

            try
            {
                // Open the access token of the current process with TOKEN_QUERY.
                if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
                                                    NativeMethods.TOKEN_QUERY, out hToken))
                {
                    throw new Win32Exception();
                }

                // Allocate a buffer for the elevation information.
                cbTokenElevation = Marshal.SizeOf(typeof(TOKEN_ELEVATION));
                pTokenElevation  = Marshal.AllocHGlobal(cbTokenElevation);
                if (pTokenElevation == IntPtr.Zero)
                {
                    throw new Win32Exception();
                }

                // Retrieve token elevation information.
                if (!NativeMethods.GetTokenInformation(hToken,
                                                       TOKEN_INFORMATION_CLASS.TokenElevation, pTokenElevation,
                                                       cbTokenElevation, out cbTokenElevation))
                {
                    // When the process is run on operating systems prior to Windows Vista,
                    // GetTokenInformation returns false with the error code ERROR_INVALID_PARAMETER
                    // because TokenElevation is not supported on those operating systems.
                    throw new Win32Exception();
                }

                // Marshal the TOKEN_ELEVATION struct from native to .NET object.
                //TOKEN_ELEVATION elevation = (TOKEN_ELEVATION)

                // Marshal the TOKEN_MANDATORY_LABEL struct from native to .NET object.
                var elevation = Marshal.PtrToStructure(pTokenElevation, typeof(TOKEN_ELEVATION));

                if (elevation is TOKEN_ELEVATION elevationToken)
                {
                    // TOKEN_ELEVATION.TokenIsElevated is a non-zero value if the token has elevated
                    // privileges; otherwise, a zero value.
                    fIsElevated = (elevationToken.TokenIsElevated != 0);
                }
                else
                {
#pragma warning disable CA1303 // Do not pass literals as localized parameters
                    throw new NullReferenceException(nameof(elevation));
#pragma warning restore CA1303 // Do not pass literals as localized parameters
                }
            }
            finally
            {
                // Centralized cleanup for all allocated resources.
                if (hToken != null)
                {
                    hToken.Close();
                }
                if (pTokenElevation != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pTokenElevation);
                }
            }

            return(fIsElevated);
        }
예제 #11
0
 internal static partial bool SetThreadToken(
     IntPtr ThreadHandle,
     SafeTokenHandle?hToken);
예제 #12
0
 internal static extern bool SetThreadToken(IntPtr ThreadHandle, SafeTokenHandle?hToken);
예제 #13
0
        /// <summary>
        /// Logs on the user with the given credentials as an interactive user.
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <param name="domain">The domain.</param>
        /// <param name="password">The password.</param>
        /// <param name="userToken">The user token.</param>
        /// <returns>
        /// 0 if the function succeeds, a HRESULT of the last error if the function fails.
        /// </returns>
        public static int LogOnInteractiveUser([CanBeNull] string?userName, [CanBeNull] string?domain, [CanBeNull] string?password, [CanBeNull] out SafeTokenHandle?userToken)
        {
            ParseUserDomain(ref userName, ref domain);

            if (NativeMethods.LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out var pUserToken))
            {
                userToken = new SafeTokenHandle(pUserToken);
                return(0);
            }

            userToken = null;
            var error = Marshal.GetHRForLastWin32Error();

            return(error == 0 ? E_FAIL : error);
        }
예제 #14
0
 /// <summary>
 /// Logs on the user with the given credentials as an interactive user.
 /// </summary>
 /// <param name="credential">The credential.</param>
 /// <param name="userToken">The user token.</param>
 /// <returns>
 /// 0 if the function succeeds, a HRESULT of the last error if the function fails.
 /// </returns>
 public static int LogOnInteractiveUser([NotNull] this NetworkCredential credential, [CanBeNull] out SafeTokenHandle?userToken)
 {
     return(LogOnInteractiveUser(credential.UserName, credential.Domain, credential.Password, out userToken));
 }
예제 #15
0
        internal static int OpenThreadToken(TokenAccessLevels dwDesiredAccess, WinSecurityContext dwOpenAs, out SafeTokenHandle?phThreadToken)
        {
            int  hr         = 0;
            bool openAsSelf = true;

            if (dwOpenAs == WinSecurityContext.Thread)
            {
                openAsSelf = false;
            }

            if (!Interop.Advapi32.OpenThreadToken((IntPtr)(-2), dwDesiredAccess, openAsSelf, out phThreadToken))
            {
                if (dwOpenAs == WinSecurityContext.Both)
                {
                    openAsSelf = false;
                    hr         = 0;
                    if (!Interop.Advapi32.OpenThreadToken((IntPtr)(-2), dwDesiredAccess, openAsSelf, out phThreadToken))
                    {
                        hr = Marshal.GetHRForLastWin32Error();
                    }
                }
                else
                {
                    hr = Marshal.GetHRForLastWin32Error();
                }
            }
            if (hr != 0)
            {
                phThreadToken = null;
            }
            return(hr);
        }