【问题标题】:Can't read privileges from process access token无法从进程访问令牌中读取权限
【发布时间】:2020-12-06 12:22:16
【问题描述】:

我正在尝试获取进程访问令牌中的组和权限列表以及有关它们的一些信息(名称、标志和描述)。

为此,我使用了GetTokenInfomation 函数和TOKEN_GROUPS_AND_PRIVILEGES 结构。

这些是结构定义:

TOKEN_GROUPS_AND_PRIVILEGES

        [StructLayout(LayoutKind.Sequential)]
        public struct TOKEN_GROUPS_AND_PRIVILEGES
        {
            public uint SidCount;

            public uint SidLength;

            public IntPtr Sids;

            public uint RestrictedSidCount;

            public uint RestrictedSidLength;

            public IntPtr RestrictedSids;

            public uint PrivilegeCount;

            public uint PrivilegeLength;

            public IntPtr Privileges;

            public LUID AuthenticationID;
        }

LUID_AND_ATTRIBUTES

        [StructLayout(LayoutKind.Sequential)]
        public struct LUID_AND_ATTRIBUTES
        {
            public LUID Luid;

            public uint Attributes;
        }

LUID

        [StructLayout(LayoutKind.Sequential)]
        public struct LUID
        {
            public uint LowPart;

            public int HighPart;
        }

我可以很好地读取组 SID 并获取有关它们的信息,但是当我尝试读取权限时,我总是会遇到访问冲突。

这是我用来读取权限的代码:

            for (int i = 0; i < GroupsAndPrivilegesInfo.PrivilegeCount; i++)
            {
                Privilege = (Win32Structures.LUID_AND_ATTRIBUTES)Marshal.PtrToStructure(GroupsAndPrivilegesInfo.Privileges, typeof(Win32Structures.LUID_AND_ATTRIBUTES));
                PrivilegeName = GetPrivilegeName(Privilege.Luid) ?? "Non disponibile";
                PrivilegeStatus = GetPrivilegeFlags((Win32Enumerations.PrivilegeLUIDAttribute)Privilege.Attributes) ?? "Non disponibile";
                PrivilegeDescription = GetPrivilegeDescription(PrivilegeName) ?? "Non disponibile";
                Privileges.Add(new TokenPrivilegeInfo(PrivilegeName, PrivilegeStatus, PrivilegeDescription));
                GroupsAndPrivilegesInfo.Privileges += Marshal.SizeOf(typeof(Win32Structures.LUID_AND_ATTRIBUTES));
            }

调用GetPrivilegeName方法时发生异常,该方法使用函数LookupPrivilegeNameW定义如下:

        [DllImport("Advapi32.dll", EntryPoint = "LookupPrivilegeNameW", CharSet = CharSet.Unicode, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool LookupPrivilegeName(string SystemName, Win32Structures.LUID LUID, StringBuilder PrivilegeName, ref uint NameLength);

我尝试了不同的方法来读取数据,例如:

  1. 手动计算从结构开始到权限数组元素的偏移量
  2. 将权限字段声明为数组并将 SizeConst 设置为明显过大的值

即使是这些方法也会引发访问冲突异常。

鉴于我使用相同的代码读取 SID 并且它正常工作,我不明白这是什么问题。

【问题讨论】:

  • LookupPrivilegeNameW 的第二个参数是指向LUID指针。您应该将其声明为引用类型ref Win32Structures.LUID LUID
  • 谢谢@DrakeWu-MSFT,现在它可以工作了,我不敢相信它是如此简单。

标签: c# .net winapi


【解决方案1】:

首先,LookupPrivilegeNameW 的第二个参数是一个指向 LUID 的指针。您需要将其声明为 ref Win32Structures.LUID LUID 之类的引用类型。

然后TOKEN_GROUPS_AND_PRIVILEGES.Privileges 是一个权限数组。 您的代码不会检索所有权限,而是每次都重复读取第一个权限。 这是工作示例:

namespace ConsoleApp2
{
    class Program
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct TOKEN_GROUPS_AND_PRIVILEGES
        {
            public uint SidCount;
            public uint SidLength;
            public IntPtr Sids;
            public uint RestrictedSidCount;
            public uint RestrictedSidLength;
            public IntPtr RestrictedSids;
            public uint PrivilegeCount;
            public uint PrivilegeLength;
            public IntPtr Privileges;
            public LUID AuthenticationID;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct LUID_AND_ATTRIBUTES
        {
            public LUID Luid;
            public uint Attributes;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct LUID
        {
            public uint LowPart;
            public int HighPart;
        }
        public enum TOKEN_INFORMATION_CLASS
        {
            TokenUser = 1,
            TokenGroups,
            TokenPrivileges,
            TokenOwner,
            TokenPrimaryGroup,
            TokenDefaultDacl,
            TokenSource,
            TokenType,
            TokenImpersonationLevel,
            TokenStatistics,
            TokenRestrictedSids,
            TokenSessionId,
            TokenGroupsAndPrivileges,
            TokenSessionReference,
            TokenSandBoxInert,
            TokenAuditPolicy,
            TokenOrigin
        }
        [DllImport("Advapi32.dll", EntryPoint = "LookupPrivilegeNameW", CharSet = CharSet.Unicode, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool LookupPrivilegeName(string SystemName, ref LUID LUID, StringBuilder PrivilegeName, ref uint NameLength);
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool OpenProcessToken(IntPtr ProcessHandle,
    UInt32 DesiredAccess, out IntPtr TokenHandle);
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetCurrentProcess();
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool GetTokenInformation(IntPtr TokenHandle, 
            TOKEN_INFORMATION_CLASS TokenInformationClass, 
            IntPtr TokenInformation,
            Int32 TokenInformationLength,
            out Int32 ReturnLength);

        public static UInt32 TOKEN_QUERY = 0x0008;
        static void Main(string[] args)
        {
            bool ret = false;
            IntPtr token;
            ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, out token);
            Int32 ReturnLength;
            ret = GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TokenGroupsAndPrivileges, IntPtr.Zero, 0, out ReturnLength);
            IntPtr pGroupsAndPrivilegesInfo = Marshal.AllocHGlobal(ReturnLength);
            ret = GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TokenGroupsAndPrivileges, pGroupsAndPrivilegesInfo, ReturnLength, out ReturnLength);
            TOKEN_GROUPS_AND_PRIVILEGES GroupsAndPrivilegesInfo = (TOKEN_GROUPS_AND_PRIVILEGES)Marshal.PtrToStructure(pGroupsAndPrivilegesInfo, typeof(TOKEN_GROUPS_AND_PRIVILEGES));
            

            for (int i = 0; i < GroupsAndPrivilegesInfo.PrivilegeCount; i++)
            {
                //IntPtr ptr = GroupsAndPrivilegesInfo.Privileges + i * Marshal.SizeOf(typeof(LUID_AND_ATTRIBUTES));
                LUID_AND_ATTRIBUTES Privilege = (LUID_AND_ATTRIBUTES)Marshal.PtrToStructure(GroupsAndPrivilegesInfo.Privileges + i * Marshal.SizeOf(typeof(LUID_AND_ATTRIBUTES)), typeof(LUID_AND_ATTRIBUTES));
                StringBuilder name = new StringBuilder(50);
                uint cchName = 50; 
                ret = LookupPrivilegeName(null, ref Privilege.Luid, name, ref cchName);
                Console.WriteLine(name);
            }
            Marshal.FreeHGlobal(pGroupsAndPrivilegesInfo);

        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 2019-09-25
    • 2017-09-28
    • 2012-03-24
    • 2023-03-31
    • 1970-01-01
    • 2018-10-10
    相关资源
    最近更新 更多