Архив за ‘C#’ категория

Получение любых привилегий для процесса на C#

Май 15th, 2010

Иногда для выполнения каких-либо операций приложению требуется получить различные привилегии. Например для того, чтобы посмотреть используемые модули системного процесса, наше приложение должно обладать привилегией отладчика.

Чтобы изменить привилегии процесса, нужно воспользоваться тремя WinAPI-функциями:

  1. Прежде всего, необходимо открыть токен доступа процесса функцией OpenProcessToken() из библиотеки advapi32.dll .
  2. С помощью функции LookupPrivilegeValue(), подготовить структуру TOKEN_PRIVILEGES, в которой разместить информацию о требуемом уровне привилегий.
  3. Обратиться к функции AdjustTokenPrivileges() непосредственно для изменения привилегии процесса.

Кстати, чтобы успешно получить привилегии отладчика, нужно иметь администраторские права.

Ниже приведен код на C#, обеспечивающий получение заданных привилегий(метод SetPrivilege()). В нем также определены строковые константы привилегий:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
public class PrivilegeManager
{
    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool OpenProcessToken(IntPtr ProcessHandle,
        UInt32 DesiredAccess, out IntPtr TokenHandle);

    private static uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
    private static uint STANDARD_RIGHTS_READ = 0x00020000;
    private static uint TOKEN_ASSIGN_PRIMARY = 0x0001;
    private static uint TOKEN_DUPLICATE = 0x0002;
    private static uint TOKEN_IMPERSONATE = 0x0004;
    private static uint TOKEN_QUERY = 0x0008;
    private static uint TOKEN_QUERY_SOURCE = 0x0010;
    private static uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
    private static uint TOKEN_ADJUST_GROUPS = 0x0040;
    private static uint TOKEN_ADJUST_DEFAULT = 0x0080;
    private static uint TOKEN_ADJUST_SESSIONID = 0x0100;
    private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
    private static uint TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
        TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
        TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
        TOKEN_ADJUST_SESSIONID);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr GetCurrentProcess();

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool LookupPrivilegeValue(string lpSystemName, string lpName,
        out LUID lpLuid);

    #region Privelege constants
         
        public const string SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege";
        public const string SE_AUDIT_NAME = "SeAuditPrivilege";
        public const string SE_BACKUP_NAME = "SeBackupPrivilege";
        public const string SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege";
        public const string SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege";
        public const string SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege";
        public const string SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege";
        public const string SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege";
        public const string SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege";
        public const string SE_DEBUG_NAME = "SeDebugPrivilege";
        public const string SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege";
        public const string SE_IMPERSONATE_NAME = "SeImpersonatePrivilege";
        public const string SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege";
        public const string SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege";
        public const string SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege";
        public const string SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege";
        public const string SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege";
        public const string SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege";
        public const string SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege";
        public const string SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege";
        public const string SE_RELABEL_NAME = "SeRelabelPrivilege";
        public const string SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege";
        public const string SE_RESTORE_NAME = "SeRestorePrivilege";
        public const string SE_SECURITY_NAME = "SeSecurityPrivilege";
        public const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
        public const string SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege";
        public const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege";
        public const string SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege";
        public const string SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege";
        public const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege";
        public const string SE_TCB_NAME = "SeTcbPrivilege";
        public const string SE_TIME_ZONE_NAME = "SeTimeZonePrivilege";
        public const string SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege";
        public const string SE_UNDOCK_NAME = "SeUndockPrivilege";
        public const string SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege";
    #endregion

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID
    {
        public UInt32 LowPart;
        public Int32 HighPart;
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CloseHandle(IntPtr hHandle);

    public const UInt32 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
    public const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
    public const UInt32 SE_PRIVILEGE_REMOVED = 0x00000004;
    public const UInt32 SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000;

    [StructLayout(LayoutKind.Sequential)]
    public struct TOKEN_PRIVILEGES
    {
        public UInt32 PrivilegeCount;
        public LUID Luid;
        public UInt32 Attributes;
    }

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

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
       [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
       ref TOKEN_PRIVILEGES NewState,
       UInt32 Zero,
       IntPtr Null1,
       IntPtr Null2);

    /// <summary>
    /// Меняет привилегию
    /// </summary>
    /// <param name="PID">ID процесса</param>
    /// <param name="privelege">Привилегия</param>
    public static void SetPrivilege(IntPtr PID, string privilege)
    {
        IntPtr hToken;
        LUID luidSEDebugNameValue;
        TOKEN_PRIVILEGES tkpPrivileges;

        if (!OpenProcessToken(PID, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken))
        {
            throw new Exception("Произошла ошибка при выполнении OpenProcessToken(). Код ошибки "
                + Marshal.GetLastWin32Error());
        }

        if (!LookupPrivilegeValue(null, privilege, out luidSEDebugNameValue))
        {
            CloseHandle(hToken);
            throw new Exception("Произошла ошибка при выполнении LookupPrivilegeValue(). Код ошибки "
                + Marshal.GetLastWin32Error());
        }

        tkpPrivileges.PrivilegeCount = 1;
        tkpPrivileges.Luid = luidSEDebugNameValue;
        tkpPrivileges.Attributes = SE_PRIVILEGE_ENABLED;

        if (!AdjustTokenPrivileges(hToken, false, ref tkpPrivileges, 0, IntPtr.Zero, IntPtr.Zero))
        {
            throw new Exception("Произошла ошибка при выполнении LookupPrivilegeValue(). Код ошибки :"
                + Marshal.GetLastWin32Error());
        }
        CloseHandle(hToken);
    }
}

Статический метод SetPrivilege() принимает два параметра: первый – PID(Process ID), идентификатор процесса, а второй – строковое название привилегии. Во второй параметр удобно передавать одну из констант, которые также есть в классе PrivilegeManager.

Возможно Вам понадобится узнать PID Вашего процесса. Нет ничего проще! Воспользуйтесь функцией GetCurrentProcess().

См. также Константы привилегий в Windows.

Копирование материалов сайта допускается только с разрешения администрации сайта.