locked
Getting Process Integrity Level in Vista using Pinvoke. RRS feed

  • Question

  •  

    Hello All,

     

    I am trying to get the integrity levels of processes(low,medium,high,system) running using GetTokenInformation(...) function in advapi32.dll.

     

    The problem is I am getting some random 'Junk Values' for IntegrityLevel.I have tried every alternative but the result I get is the same.I am not able to troubleshoot where I went wrong.

     

    What is wrong with the code? or is there any other alternative available ?

     

    Below is the code I have used.

    class API
        {
            public const UInt32 TOKEN_QUERY = 0x0008;
            public const uint ERROR_SUCCESS = 0;
            public const uint ERROR_INSUFFICIENT_BUFFER = 122;
            public const uint TokenIntegrityLevel = 25;
           
            long SECURITY_MANDATORY_UNTRUSTED_RID = (0x00000000L);
            long SECURITY_MANDATORY_LOW_RID = (0x00001000L);
            long SECURITY_MANDATORY_MEDIUM_RID =(0x00002000L);
            long SECURITY_MANDATORY_HIGH_RID =(0x00003000L);
            long SECURITY_MANDATORY_SYSTEM_RID =(0x00004000L);
            long SECURITY_MANDATORY_PROTECTED_PROCESS_RID =(0x00005000L);
           
           
            public enum TOKEN_INFORMATION_CLASS
            {
                TokenUser = 1,
                TokenGroups,
                TokenPrivileges,
                TokenOwner,
                TokenPrimaryGroup,
                TokenDefaultDacl,
                TokenSource,
                TokenType,
                TokenImpersonationLevel,
                TokenStatistics,
                TokenRestrictedSids,
                TokenSessionId,
                TokenGroupsAndPrivileges,
                TokenSessionReference,
                TokenSandBoxInert,
                TokenAuditPolicy,
                TokenOrigin,
                TokenElevationType,
                TokenLinkedToken,
                TokenElevation,
                TokenHasRestrictions,
                TokenAccessInformation,
                TokenVirtualizationAllowed,
                TokenVirtualizationEnabled,
                TokenIntegrityLevel,
                TokenUIAccess,
                TokenMandatoryPolicy,
                TokenLogonSid,
                MaxTokenInfoClass
            }


            [StructLayout(LayoutKind.Sequential)]
            public struct TOKEN_MANDATORY_LABEL
            {

                public SID_AND_ATTRIBUTES Label;

            }

            [StructLayout(LayoutKind.Sequential)]
            public struct SID_AND_ATTRIBUTES
            {
                public IntPtr Sid;
                public int Attributes;
            }


            [DllImport("advapi32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool OpenProcessToken(IntPtr ProcessHandle,

            UInt32 DesiredAccess, out IntPtr TokenHandle);
            [DllImport("advapi32.dll", SetLastError = true)]
            public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength,
            out uint ReturnLength);

            [DllImport("kernel32.dll")]
            public static extern IntPtr LocalAlloc(uint uFlags, UIntPtr uBytes);

            [DllImport("advapi32.dll", SetLastError = true)]
            public static extern IntPtr GetSidSubAuthority(IntPtr pSid, int nSubAuthority);

            [DllImport("advapi32.dll", SetLastError = true)]
            public static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);

             public void GetIntegrityLevel()
             {
                
                 IntPtr TokenHandle;

                uint dwLengthNeeded;

                uint dwError = ERROR_SUCCESS;

                TOKEN_MANDATORY_LABEL pTIL;

                int IntegrityLevel = 0;
               Process[] proc = Process.GetProcesses();

                 for(int i=0;i<proc.Length;i++)
                 {
                if(procIdea.SessionId==1)
                if (OpenProcessToken(procIdea.Handle,TOKEN_QUERY, out TokenHandle))
                {

                    if (!GetTokenInformation(TokenHandle,(TOKEN_INFORMATION_CLASS)TokenIntegrityLevel,IntPtr.Zero, 0, out dwLengthNeeded))
                    {

                        dwError = (uint)Marshal.GetLastWin32Error();

                        if (dwError == ERROR_INSUFFICIENT_BUFFER)
                        {

                            pTIL = (TOKEN_MANDATORY_LABEL)Marshal.PtrToStructure(LocalAlloc(0, (UIntPtr)dwLengthNeeded), typeof(TOKEN_MANDATORY_LABEL));

                            IntPtr StructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pTIL));

                            Marshal.StructureToPtr(pTIL, StructPtr, false);

                            try
                            {

                                if (GetTokenInformation(TokenHandle, (TOKEN_INFORMATION_CLASS)TokenIntegrityLevel, StructPtr, dwLengthNeeded, out dwLengthNeeded))
                                {

                                    IntPtr SubAuthorityCount = GetSidSubAuthorityCount(pTIL.Label.Sid);

                                    IntPtr IntegrityLevelPtr = GetSidSubAuthority(pTIL.Label.Sid, SubAuthorityCount.ToInt32() - 1);

                                    IntegrityLevel = IntegrityLevelPtr.ToInt32();

                                    MessageBox.Show("Integritylevel: " + IntegrityLevelPtr.ToInt32().ToString());

                                }

                                if (IntegrityLevel < SECURITY_MANDATORY_MEDIUM_RID) //nb: Vista SDK definition
                                {
                                    MessageBox.Show("low");

                                }
                                else if (IntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID && IntegrityLevel < SECURITY_MANDATORY_HIGH_RID)
                                {
                                    MessageBox.Show("Meduim");

                                }
                                else if (IntegrityLevel >= SECURITY_MANDATORY_HIGH_RID)
                                {
                                    MessageBox.Show("High");

                                }

     

                            }

                            finally
                            {

                                Marshal.FreeHGlobal(StructPtr);

                            }


                        }}}}}}

    Wednesday, January 23, 2008 1:58 PM

Answers

  • Both GetSubAuthority and GetSubAuthorityCount return pointers, and you need to dereference those pointers to get the actual values you want. Calling ToInt32 will not help with that, you need to call Marshal.ReadInt32 and Marshal.ReadByte respectively.

     

     

    Thursday, January 24, 2008 9:11 AM
  • Hello

    I have finished a working sample code to demonstrate how to check Integrity Level of the current process in C#. You can download the sample from Microsoft All-In-One Code Framework http://cfx.codeplex.com/SourceControl/list/changesets  (changeset >=39038), and find CSUACSelfElevation in the download package. You can also find its C++ and VB.NET versions: CppUACSelfElevation and VBUACSelfElevation.

    Here is the code snippet that retrieves the IL of the current process.


            /// <summary>
            /// The function gets the integrity level of the current process.
            /// </summary>
            /// <returns>
            /// Returns the integrity level of the current process. It is usually one of
            /// these values:
            ///
            ///    SECURITY_MANDATORY_UNTRUSTED_RID - means untrusted level
            ///    SECURITY_MANDATORY_LOW_RID - means low integrity level.
            ///    SECURITY_MANDATORY_MEDIUM_RID - means medium integrity level.
            ///    SECURITY_MANDATORY_HIGH_RID - means high integrity level.
            ///    SECURITY_MANDATORY_SYSTEM_RID - means system integrity level.
            ///
            /// </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;
                SafeWaitHandle 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(Marshal.GetLastWin32Error());
                    }

                    // 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(Marshal.GetLastWin32Error());
                    }

                    // 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.GetLastWin32Error());
                    }

                    // 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));

                    IntPtr pIL = NativeMethod.GetSidSubAuthority(tokenIL.Label.Sid, 0);
                    IL = Marshal.ReadInt32(pIL);
                }
                finally
                {
                    // Centralized cleanup for all allocated resources. Clean up only
                    // those which were allocated, and clean them up in the right order.

                    if (hToken != null)
                    {
                        hToken.Close();
                        hToken = null;
                    }

                    if (pTokenIL != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(pTokenIL);
                        pTokenIL = IntPtr.Zero;
                        cbTokenIL = 0;
                    }
                }

                return IL;
            }


    Regards,
    Jialiang Ge
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Sunday, January 24, 2010 7:51 AM
    Moderator

All replies

  •  Ananda Ganesh wrote:

                            pTIL = (TOKEN_MANDATORY_LABEL)Marshal.PtrToStructure(LocalAlloc(0, (UIntPtr)dwLengthNeeded), typeof(TOKEN_MANDATORY_LABEL));

                            IntPtr StructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(pTIL));

                            Marshal.StructureToPtr(pTIL, StructPtr, false);

                            try
                            {

                                if (GetTokenInformation(TokenHandle, (TOKEN_INFORMATION_CLASS)TokenIntegrityLevel, StructPtr, dwLengthNeeded, out dwLengthNeeded))
                                {

                                    IntPtr SubAuthorityCount = GetSidSubAuthorityCount(pTIL.Label.Sid);

     

     

    I'm not sure exactly what you're trying to do with these lines of code, but it doesn't look right. There's no connection between StructPtr and pTIL so you can't expect pTIL to contain any useful data after the call to GetTokenInformation where you pass in StructPtr. The code should probably look more like this

     

     

    IntPtr StructPtr = Marshal.AllocHGlobal((int)dwLengthNeeded);
    try
    {
        if (GetTokenInformation(TokenHandle, (TOKEN_INFORMATION_CLASS)TokenIntegrityLevel, StructPtr, dwLengthNeeded, out dwLengthNeeded))
        {
            pTIL = (TOKEN_MANDATORY_LABEL)Marshal.PtrToStructure(StructPtr, typeof(TOKEN_MANDATORY_LABEL));
            IntPtr SubAuthorityCount = GetSidSubAuthorityCount(pTIL.Label.Sid);

    ...

    Marshal.FreeHGlobal(StructPtr);

    Wednesday, January 23, 2008 2:31 PM
  • Hello Mattias..

     

    Thanks for the reply,

     I included your part of the code ...still the value of process IntegrityLevel are random!

     

     

     

    Thursday, January 24, 2008 4:17 AM
  • Both GetSubAuthority and GetSubAuthorityCount return pointers, and you need to dereference those pointers to get the actual values you want. Calling ToInt32 will not help with that, you need to call Marshal.ReadInt32 and Marshal.ReadByte respectively.

     

     

    Thursday, January 24, 2008 9:11 AM
  • Thanks Mattias!. Finally got the code working.

     

     

     

     

     

    Friday, January 25, 2008 3:15 AM
  • Hi Ganesh,

    Can you please share the code which was working for you?

    Thanks,
    Suresh
    Wednesday, November 11, 2009 12:56 PM
  • Hello

    I have finished a working sample code to demonstrate how to check Integrity Level of the current process in C#. You can download the sample from Microsoft All-In-One Code Framework http://cfx.codeplex.com/SourceControl/list/changesets  (changeset >=39038), and find CSUACSelfElevation in the download package. You can also find its C++ and VB.NET versions: CppUACSelfElevation and VBUACSelfElevation.

    Here is the code snippet that retrieves the IL of the current process.


            /// <summary>
            /// The function gets the integrity level of the current process.
            /// </summary>
            /// <returns>
            /// Returns the integrity level of the current process. It is usually one of
            /// these values:
            ///
            ///    SECURITY_MANDATORY_UNTRUSTED_RID - means untrusted level
            ///    SECURITY_MANDATORY_LOW_RID - means low integrity level.
            ///    SECURITY_MANDATORY_MEDIUM_RID - means medium integrity level.
            ///    SECURITY_MANDATORY_HIGH_RID - means high integrity level.
            ///    SECURITY_MANDATORY_SYSTEM_RID - means system integrity level.
            ///
            /// </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;
                SafeWaitHandle 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(Marshal.GetLastWin32Error());
                    }

                    // 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(Marshal.GetLastWin32Error());
                    }

                    // 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.GetLastWin32Error());
                    }

                    // 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));

                    IntPtr pIL = NativeMethod.GetSidSubAuthority(tokenIL.Label.Sid, 0);
                    IL = Marshal.ReadInt32(pIL);
                }
                finally
                {
                    // Centralized cleanup for all allocated resources. Clean up only
                    // those which were allocated, and clean them up in the right order.

                    if (hToken != null)
                    {
                        hToken.Close();
                        hToken = null;
                    }

                    if (pTokenIL != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(pTokenIL);
                        pTokenIL = IntPtr.Zero;
                        cbTokenIL = 0;
                    }
                }

                return IL;
            }


    Regards,
    Jialiang Ge
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Sunday, January 24, 2010 7:51 AM
    Moderator