我想使用C#来确定为我的进程/线程令牌分配了哪些权限,并根据需要进行调整.例如,为了让我的程序重新启动计算机,它必须首先启用SeShutdownPrivilege权限.
如何从托管代码安全地完成?
解决方法
事实证明这并不重要,因为它没有内置机制.不仅需要P / Invoke,而且您必须仔细编码以确保您不会通过启用它们来“泄漏”权限,然后不会很快禁用它们(如果您重新启动计算机则不会出现问题).
有关描述的完整代码示例,请阅读Mark Novak 2005年3月“Manipulate Privileges in Managed Code Reliably,Securely,and Efficiently”中的MSDN杂志文章.
这是P / Invoke声明:
using System; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; namespace PrivilegeClass { [Flags] internal enum TokenAccessLevels { AssignPrimary = 0x00000001,Duplicate = 0x00000002,Impersonate = 0x00000004,Query = 0x00000008,QuerySource = 0x00000010,AdjustPrivileges = 0x00000020,AdjustGroups = 0x00000040,AdjustDefault = 0x00000080,AdjustSessionId = 0x00000100,Read = 0x00020000 | Query,Write = 0x00020000 | AdjustPrivileges | AdjustGroups | AdjustDefault,AllAccess = 0x000F0000 | AssignPrimary | Duplicate | Impersonate | Query | QuerySource | AdjustPrivileges | AdjustGroups | AdjustDefault | AdjustSessionId,MaximumAllowed = 0x02000000 } internal enum SecurityImpersonationLevel { Anonymous = 0,Identification = 1,Impersonation = 2,Delegation = 3,} internal enum TokenType { Primary = 1,} internal sealed class NativeMethods { internal const uint SE_PRIVILEGE_DISABLED = 0x00000000; internal const uint SE_PRIVILEGE_ENABLED = 0x00000002; [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)] internal struct LUID { internal uint LowPart; internal uint HighPart; } [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)] internal struct LUID_AND_ATTRIBUTES { internal LUID Luid; internal uint Attributes; } [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)] internal struct TOKEN_PRIVILEGE { internal uint PrivilegeCount; internal LUID_AND_ATTRIBUTES Privilege; } internal const string ADVAPI32 = "advapi32.dll"; internal const string KERNEL32 = "kernel32.dll"; internal const int ERROR_SUCCESS = 0x0; internal const int ERROR_ACCESS_DENIED = 0x5; internal const int ERROR_NOT_ENOUGH_MEMORY = 0x8; internal const int ERROR_NO_TOKEN = 0x3f0; internal const int ERROR_NOT_ALL_ASSIGNED = 0x514; internal const int ERROR_NO_SUCH_PRIVILEGE = 0x521; internal const int ERROR_CANT_OPEN_ANONYMOUS = 0x543; [DllImport( KERNEL32,SetLastError=true)] [ReliabilityContract(Consistency.WillNotCorruptState,Cer.MayFail)] internal static extern bool CloseHandle(IntPtr handle); [DllImport( ADVAPI32,CharSet=CharSet.Unicode,Cer.MayFail)] internal static extern bool AdjustTokenPrivileges ( [In] SafeTokenHandle TokenHandle,[In] bool DisableAllPrivileges,[In] ref TOKEN_PRIVILEGE NewState,[In] uint BufferLength,[In,Out] ref TOKEN_PRIVILEGE PrevIoUsState,Out] ref uint ReturnLength); [DllImport( ADVAPI32,CharSet=CharSet.Auto,Cer.MayFail)] internal static extern bool RevertToSelf(); [DllImport( ADVAPI32,EntryPoint="LookupPrivilegeValueW",Cer.MayFail)] internal static extern bool LookupPrivilegeValue ( [In] string lpSystemName,[In] string lpName,Out] ref LUID Luid); [DllImport( KERNEL32,Cer.MayFail)] internal static extern IntPtr GetCurrentProcess(); [DllImport( KERNEL32,Cer.MayFail)] internal static extern IntPtr GetCurrentThread (); [DllImport( ADVAPI32,Cer.MayFail)] internal static extern bool OpenProcessToken ( [In] IntPtr ProcessToken,[In] TokenAccessLevels DesiredAccess,Out] ref SafeTokenHandle TokenHandle); [DllImport (ADVAPI32,Cer.MayFail)] internal static extern bool OpenThreadToken( [In] IntPtr ThreadToken,[In] bool OpenAsSelf,Out] ref SafeTokenHandle TokenHandle); [DllImport (ADVAPI32,Cer.MayFail)] internal static extern bool DuplicateTokenEx( [In] SafeTokenHandle ExistingToken,[In] TokenAccessLevels DesiredAccess,[In] IntPtr TokenAttributes,[In] SecurityImpersonationLevel ImpersonationLevel,[In] TokenType TokenType,Out] ref SafeTokenHandle NewToken); [DllImport (ADVAPI32,Cer.MayFail)] internal static extern bool SetThreadToken( [In] IntPtr Thread,[In] SafeTokenHandle Token); static NativeMethods() { } } }