Exemple #1
0
        /// <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>
        internal 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 (!NativeMethod.OpenProcessToken(Process.GetCurrentProcess().Handle,
                                                   NativeMethod.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 (!NativeMethod.GetTokenInformation(hToken,
                                                      TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, IntPtr.Zero, 0,
                                                      out cbTokenIL))
                {
                    int error = Marshal.GetLastWin32Error();
                    if (error != NativeMethod.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 (!NativeMethod.GetTokenInformation(hToken,
                                                      TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenIL, cbTokenIL,
                                                      out cbTokenIL))
                {
                    throw new Win32Exception();
                }

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

                // 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 = NativeMethod.GetSidSubAuthority(tokenIL.Label.Sid, 0);
                IL = Marshal.ReadInt32(pIL);
            }
            finally
            {
                // Centralized cleanup for all allocated resources.
                if (hToken != null)
                {
                    hToken.Close();
                    hToken = null;
                }
                if (pTokenIL != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pTokenIL);
                    pTokenIL  = IntPtr.Zero;
                    cbTokenIL = 0;
                }
            }

            return(IL);
        }
Exemple #2
0
        /// <summary>
        /// 此函数获取当前线程的完整性级别。完整性级别只有在Windows Vista及后
        /// 续版本的Windows中有效。所以在Windows Vista之前的版本中执行GetProcessIntegrityLevel,
        /// 它会抛出一个C++异常。
        /// </summary>
        /// <returns>
        /// 返回当前进程的完整性级别。它可能是以下某一个值。
        ///
        ///     SECURITY_MANDATORY_UNTRUSTED_RID (SID: S-1-16-0x0)
        ///     表示不被信任的级别。它被用于一个匿名组成员起动的进程。这时大多数
        ///     写入操作被禁止。
        ///
        ///     SECURITY_MANDATORY_LOW_RID (SID: S-1-16-0x1000)
        ///     表示低完整性级别。它被用于保护模式下的IE浏览器。这时大多数系统中对
        ///     象(包括文件及注册表键值)的写入操作被禁止。
        ///
        ///     SECURITY_MANDATORY_MEDIUM_RID (SID: S-1-16-0x2000)
        ///     表示中完整性级别。它被用于在UAC开启时启动普通应用程序。
        ///
        ///
        ///     SECURITY_MANDATORY_HIGH_RID (SID: S-1-16-0x3000)
        ///     表示高完整性级别。它被用于用户通过UAC提升权限启动一个管理员应用程序。
        ///     或则当UAC关闭时,管理员用户启动一个普通程序。
        ///
        ///
        ///     SECURITY_MANDATORY_SYSTEM_RID (SID: S-1-16-0x4000)
        ///     表示系统完整性级别。它被用于服务或则其他系统级别的应用程序(比如
        ///     Wininit, Winlogon, Smss,等等)
        /// </returns>
        /// <exception cref="System.ComponentModel.Win32Exception">
        /// 如果任何原生的Windows API函数出错,此函数会抛出一个包含最后错误代码的Win32Exception。
        /// </exception>
        internal int GetProcessIntegrityLevel()
        {
            int             IL        = -1;
            SafeTokenHandle hToken    = null;
            int             cbTokenIL = 0;
            IntPtr          pTokenIL  = IntPtr.Zero;

            try
            {
                // 使用TOKEN_QUERY打开线程的主访问令牌。
                if (!NativeMethod.OpenProcessToken(Process.GetCurrentProcess().Handle,
                                                   NativeMethod.TOKEN_QUERY, out hToken))
                {
                    throw new Win32Exception();
                }

                // 然后我们必须查询令牌完整性级别信息的大小。注意:我们预期得到一个FALSE结果及错误
                // ERROR_INSUFFICIENT_BUFFER, 这是由于我们在GetTokenInformation输入一个
                // 空缓冲。同时,在cbTokenIL中我们会得知完整性级别信息的大小。

                if (!NativeMethod.GetTokenInformation(hToken,
                                                      TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, IntPtr.Zero, 0,
                                                      out cbTokenIL))
                {
                    int error = Marshal.GetLastWin32Error();
                    if (error != NativeMethod.ERROR_INSUFFICIENT_BUFFER)
                    {
                        // 当进程运行于Windows Vista之前的系统中,GetTokenInformation返回
                        // FALSE和错误码ERROR_INVALID_PARAMETER。这是由于这些操作系统不支
                        // 持TokenElevation。
                        throw new Win32Exception(error);
                    }
                }

                // 现在我们为完整性级别信息分配一个缓存。
                pTokenIL = Marshal.AllocHGlobal(cbTokenIL);
                if (pTokenIL == IntPtr.Zero)
                {
                    throw new Win32Exception();
                }
                // 现在我们需要再次查询完整性级别信息。如果在第一次调用GetTokenInformation
                // 和本次之间一个管理员把当前账户加到另外一个组中,此次调用会失败。

                if (!NativeMethod.GetTokenInformation(hToken,
                                                      TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenIL, cbTokenIL,
                                                      out cbTokenIL))
                {
                    throw new Win32Exception();
                }

                // 转换TOKEN_MANDATORY_LABEL结构(从Native 到.Net)
                TOKEN_MANDATORY_LABEL tokenIL = (TOKEN_MANDATORY_LABEL)
                                                Marshal.PtrToStructure(pTokenIL, typeof(TOKEN_MANDATORY_LABEL));

                // 完整性级别SID为S-1-16-0xXXXX形式。(例如:S-1-16-0x1000表示为低完整性
                // 级别的SID)。而且有且仅有一个次级授权信息。
                IntPtr pIL = NativeMethod.GetSidSubAuthority(tokenIL.Label.Sid, 0);
                IL = Marshal.ReadInt32(pIL);
            }
            finally
            {
                // 集中清理所有已分配的内存资源
                if (hToken != null)
                {
                    hToken.Close();
                    hToken = null;
                }
                if (pTokenIL != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pTokenIL);
                    pTokenIL  = IntPtr.Zero;
                    cbTokenIL = 0;
                }
            }

            return(IL);
        }