stash/Get-Privileges.ps1
using namespace System.Text # Easiest way: whoami /priv /fo csv | ConvertFrom-Csv function Get-Privileges { [CmdletBinding()]param() begin { New-Delegate advapi32 { bool GetTokenInformation([ptr, uint, buf, uint, uint_]) bool LookupPrivilegeDisplayNameW([string, buf, buf, uint_, uint_]) bool LookupPrivilegeNameW([string, buf, buf, uint_]) bool OpenProcessToken([ptr, uint, ptr_]) } New-Delegate kernel32 { bool CloseHandle([ptr]) } $token, $sz = [IntPtr]::Zero, 0 } process {} end { try { if (!$advapi32.OpenProcessToken.Invoke([IntPtr]-1, 0x08, [ref]$token)) { throw [InvalidOperationException]::new('Cannot access token.') } # TokenPrivileges = 0x03 if (!$advapi32.GetTokenInformation.Invoke($token, 0x03, $null, 0, [ref]$sz) -and $sz -ne 0) { $buf = [Byte[]]::new($sz) if (!$advapi32.GetTokenInformation.Invoke($token, 0x03, $buf, $buf.Length, [ref]$sz)) { throw [InvalidOperationException]::new('Cannot get token information.') } } # getting PrivilegeCount (first field of TOKEN_PRIVILEGES) $PrivilegeCount = [BitConverter]::ToUInt32($buf[0..3], 0) # other bytes of $buf are Privileges (LUID_AND_ATTRIBUTES[$PrivilegeCount]) $Privileges = $buf[4..$buf.Length] # sizeof(LUID_AND_ATTRIBUTES) = 0x0C [Array]::Resize([ref]$buf, 255) for ($i = 0; $i -lt $Privileges.Length; $i++) { # sizeof(LUID) = 0x08, Attributes takes 4 bytes $LUID, $Attributes = $Privileges[0..7], [BitConverter]::ToUInt32($Privileges[8..11], 0) $buf.Clear() $sz = $buf.Length if ($advapi32.LookupPrivilegeNameW.Invoke($null, $LUID, $buf, [ref]$sz)) { $name = $buf[0..($sz * 2 - 1)] # keep in mind that is Unicode data $buf.Clear() $sz = $buf.Length if ($advapi32.LookupPrivilegeDisplayNameW.Invoke($null, $name, $buf, [ref]$sz, [ref]$null)) { [PSCustomObject]@{ Privilege = [Encoding]::Unicode.GetString($name) Description = [Encoding]::Unicode.GetString($buf[0..($sz * 2 - 1)]) Attributes = ( ('Disabled','Default Enabled')[$Attributes -band 1], 'Enabled' )[($Attributes -band 2) -eq 2] } } } $Privileges = $Privileges[12..$Privileges.Length] } } catch { Write-Verbose $_ } finally { if ($token -ne [IntPtr]::Zero) { if (!$kernel32.CloseHandle.Invoke($token)) { Write-Verbose 'Cannot release token.' } } } } } |