#c# #.net #winapi
#c# #.net #winapi
Вопрос:
Я пытаюсь получить список групп и привилегий в токене доступа к процессу и некоторую информацию о них (имя, флаги и описание).
Для этого я использую функцию 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, и он работает нормально.
Комментарии:
1. Второй параметр
LookupPrivilegeNameW
— это указатель на aLUID
. Вы должны объявить его как ссылочный типref Win32Structures.LUID LUID
.2. Спасибо @DrakeWu-MSFT, теперь это работает, я не могу поверить, что это было что-то настолько простое.
Ответ №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);
}
}
}