【发布时间】: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);
我尝试了不同的方法来读取数据,例如:
- 手动计算从结构开始到权限数组元素的偏移量
- 将权限字段声明为数组并将 SizeConst 设置为明显过大的值
即使是这些方法也会引发访问冲突异常。
鉴于我使用相同的代码读取 SID 并且它正常工作,我不明白这是什么问题。
【问题讨论】:
-
LookupPrivilegeNameW的第二个参数是指向LUID的指针。您应该将其声明为引用类型ref Win32Structures.LUID LUID。 -
谢谢@DrakeWu-MSFT,现在它可以工作了,我不敢相信它是如此简单。