使用Ntrights.exe授予用户权限后无法启用权限的技术咨询
使用Ntrights.exe授予用户权限后无法启用权限的技术咨询
你好!首先得明确一点:Ntrights.exe的作用仅仅是把权限添加到用户的权限集合中(也就是授予权限),它本身并不会自动启用这些权限——这是Windows权限机制的正常设计,不是工具的问题。
在Windows系统里,用户被授予的权限默认在登录会话中都是Disabled状态,这是出于安全考虑:权限只有在需要使用它的程序主动通过系统API(比如AdjustTokenPrivileges)申请启用时,才会变成Enabled状态。你用whoami /priv看到的Disabled,只是说明当前会话里这个权限没被激活,但你的用户已经拥有了该权限,当你运行需要它的程序(比如shutdown.exe)时,程序会自动启用这个权限完成操作。
至于你问的有没有Sysinternals工具能直接启用权限:遗憾的是Sysinternals套件里没有专门做这件事的工具,但我们可以用PowerShell脚本调用Windows API来实现临时启用当前会话中的权限,比如针对SeShutdownPrivilege的示例脚本:
$privilegeName = "SeShutdownPrivilege" $token = [System.Security.Principal.WindowsIdentity]::GetCurrent().Token $privilege = New-Object System.Security.Principal.WindowsPrincipal($token) if (-not $privilege.HasPrivilege($privilegeName)) { Write-Host "该用户未被授予$privilegeName权限" exit } $tokenHandle = [IntPtr]::Zero if ([Advapi32]::OpenProcessToken([System.Diagnostics.Process]::GetCurrentProcess().Handle, [TokenAccessLevels]::AdjustPrivileges -bor [TokenAccessLevels]::Query, [ref]$tokenHandle)) { $luid = New-Object Interop.LUID if ([Advapi32]::LookupPrivilegeValue($null, $privilegeName, [ref]$luid)) { $privilegeSet = New-Object Interop.TOKEN_PRIVILEGES $privilegeSet.PrivilegeCount = 1 $privilegeSet.Privileges = New-Object Interop.LUID_AND_ATTRIBUTES[] 1 $privilegeSet.Privileges[0].Luid = $luid $privilegeSet.Privileges[0].Attributes = [PrivilegeAttributes]::Enabled $previousPrivilegeSet = New-Object Interop.TOKEN_PRIVILEGES $returnLength = [UInt32]::Zero if ([Advapi32]::AdjustTokenPrivileges($tokenHandle, $false, [ref]$privilegeSet, [System.Runtime.InteropServices.Marshal]::SizeOf($previousPrivilegeSet), [ref]$previousPrivilegeSet, [ref]$returnLength)) { Write-Host "$privilegeName权限已在当前会话中启用" } else { Write-Host "启用权限失败,错误码: $([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())" } } [Kernel32]::CloseHandle($tokenHandle) } # 提前定义所需的API调用结构体和函数 Add-Type @" using System; using System.Runtime.InteropServices; public class Interop { [StructLayout(LayoutKind.Sequential)] public struct LUID { public uint LowPart; public int HighPart; } [StructLayout(LayoutKind.Sequential)] public struct LUID_AND_ATTRIBUTES { public LUID Luid; public uint Attributes; } [StructLayout(LayoutKind.Sequential)] public struct TOKEN_PRIVILEGES { public uint PrivilegeCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] public LUID_AND_ATTRIBUTES[] Privileges; } } public enum TokenAccessLevels : uint { AdjustPrivileges = 0x0020, Query = 0x0008 } public enum PrivilegeAttributes : uint { Enabled = 0x00000002 } public class Advapi32 { [DllImport("advapi32.dll", SetLastError = true)] public static extern bool OpenProcessToken(IntPtr ProcessHandle, TokenAccessLevels DesiredAccess, ref IntPtr TokenHandle); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref Interop.LUID lpLuid); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref Interop.TOKEN_PRIVILEGES NewState, uint BufferLength, ref Interop.TOKEN_PRIVILEGES PreviousState, ref uint ReturnLength); } public class Kernel32 { [DllImport("kernel32.dll", SetLastError = true)] public static extern bool CloseHandle(IntPtr hObject); } "@
如果想要让权限在用户登录后自动启用,其实不太推荐(会增加安全风险),但如果确实有需求,可以通过组策略配置登录脚本,在用户登录时运行类似上述的代码来激活权限。
备注:内容来源于stack exchange,提问作者k1dfr0std
相关产品推荐
相关产品推荐

