BAMCIS.TokenManipulation.psm1
Function Get-TokenGroups { <# .SYNOPSIS Enumerates the SIDs that are maintained in a user's access token issued at logon and translates the SIDs to group names. .DESCRIPTION The function gets the access token for the user that was issued at their logon. It reads the TOKEN_GROUPS from the access token and retrieves their SIDs from unmanaged memory. It then attempts to translate these SIDs to group names. The function includes all group memberships inherited from nested grouping. .INPUTS None .OUTPUTS System.String[] .EXAMPLE Get-TokenGroups Returns an array of group names and/or SIDs in the access token for the current user. .NOTES AUTHOR: Michael Haken LAST UPDATED: 10/24/2017 #> [CmdletBinding()] [OutputType([System.String[]])] Param( ) Begin { } Process { if (!([System.Management.Automation.PSTypeName]"BAMCIS.PowerShell.TokenManipulation.Token").Type) { Add-Type -TypeDefinition $script:TokenSignature } [UInt32]$TokenInformationLength = 0 # This first call will get the token information length $ResultValue = [BAMCIS.PowerShell.TokenManipulation.Token]::GetTokenInformation( [System.Security.Principal.WindowsIdentity]::GetCurrent().Token, [BAMCIS.PowerShell.TokenManipulation.Token+TOKEN_INFORMATION_CLASS]::TokenGroups, [System.IntPtr]::Zero, $TokenInformationLength, [ref]$TokenInformationLength ) if ($TokenInformationLength -gt 0) { # Create a pointer to hold the information in the token now that we have the length needed [IntPtr]$TokenInformation = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenInformationLength) $ResultValue = [BAMCIS.PowerShell.TokenManipulation.Token]::GetTokenInformation( [System.Security.Principal.WindowsIdentity]::GetCurrent().Token, [BAMCIS.PowerShell.TokenManipulation.Token+TOKEN_INFORMATION_CLASS]::TokenGroups, $TokenInformation, $TokenInformationLength, [ref]$TokenInformationLength ) if ($ResultValue -eq $true) { [BAMCIS.PowerShell.TokenManipulation.Token+TOKEN_GROUPS]$Groups = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenInformation, [System.Type][BAMCIS.PowerShell.TokenManipulation.Token+TOKEN_GROUPS]) [System.Int32]$Size = [System.Runtime.InteropServices.Marshal]::SizeOf([System.Type][BAMCIS.PowerShell.TokenManipulation.Token+SID_AND_ATTRIBUTES]) try { # Start at the TokenInformation pointer, # The compiler aligns each of the fieds in the TOKEN_GROUP struct on the nearest n byte boundary where n is 4 on 32 bit and 8 on 64 bit # The size of an IntPtr is 8 on 64 bit and 4 on 32 bit [System.Int64]$Base = $TokenInformation.ToInt64() + [System.IntPtr]::Size [System.String[]]$GroupResults = @() for ($i = 0; $i -lt $Groups.GroupCount; $i++) { [System.Int64]$Offset = $Base + ($i * $Size) [BAMCIS.PowerShell.TokenManipulation.Token+SID_AND_ATTRIBUTES]$SidAndAttrsGroup = [System.Runtime.InteropServices.Marshal]::PtrToStructure([IntPtr]($Offset), [System.Type][BAMCIS.PowerShell.TokenManipulation.Token+SID_AND_ATTRIBUTES]) [System.String]$Sid = [System.String]::Empty $ResultValue = [BAMCIS.PowerShell.TokenManipulation.Token]::ConvertSidToStringSid($SidAndAttrsGroup.Sid, [ref]$Sid) if ($ResultValue -eq $true) { try { $Group = (New-Object System.Security.Principal.SecurityIdentifier($Sid)).Translate([System.Security.Principal.NTAccount]) | Select-Object -ExpandProperty Value $GroupResults += $Group } catch [Exception] { $GroupResults += $Sid Write-Log -ErrorRecord $_ -Level WARNING } } else { Write-Log -Message "Failed to get SID for group $i : $((New-Object System.ComponentModel.Win32Exception([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())).Message)." -Level WARNING } } Write-Output -InputObject $GroupResults } catch [Exception] { Write-Log -ErrorRecord $_ -Level FATAL } finally { [BAMCIS.PowerShell.TokenManipulation.Token]::CloseHandle($TokenInformation) | Out-Null } } else { [BAMCIS.PowerShell.TokenManipulation.Token]::CloseHandle($TokenInformation) | Out-Null Write-Log -Message (New-Object System.ComponentModel.Win32Exception([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())).Message -Level WARNING } } } End { } } Function Update-TokenGroupMembership { <# .SYNOPSIS The command refreshes the user's token and clears their current Kerberos tickets in order to pick up Active Directory group membership changes since their last logon. .DESCRIPTION The current group membership of the user is recorded. Then, the user's Kerberos tickets are purged. After that, the explorer.exe process is stopped and restarted, which refreshes the logon token for the user. The user will be required to enter a set of credentials and then required to enter their password to restart the explorer.exe process. .PARAMETER Credential The credentials of the current user. These are used to launch a new powershell process to get the updated token group membership. Without using credentials, the new process won't be started with the new token and won't reflect the updates in group membership. .PARAMETER UseSmartcard If the user only has a Smartcard and does not know their windows password, utilize this switch to enable prompting for Smartcard credentials when explorer.exe restarts. However, they will need to specify a credential object to start a new process to check the token changes. .INPUTS None .OUTPUTS None .EXAMPLE Update-TokenGroupMembership -Credential (Get-Credential) Updates the group membership for the current user. .EXAMPLE Update-TokenGroupMembership -UseSmartcard Updates the groups membership for the current user, but prompts for Smartcard credentials to restart explorer.exe. Because the Credential parameter was not specified, the changes in the group membership in the token are not displayed. .NOTES AUTHOR: Michael Haken LAST UPDATED: 11/14/2016 #> [CmdletBinding()] [OutputType()] Param( [Parameter(Mandatory = $true)] [ValidateNotNull()] [System.Management.Automation.Credential()] [System.Management.Automation.PSCredential]$Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter()] [Switch]$UseSmartcard ) Begin { } Process { $CurrentGroups = @() [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups.Translate([System.Security.Principal.NTAccount]) | Select-Object -ExpandProperty Value | ForEach-Object { if ($_ -ne $null -and $_ -ne "") { $CurrentGroups += $_ } } #The ampersand signifies to execute the following scriptblock and treat each value as a parameter & "$env:SYSTEMROOT\system32\klist.exe" purge | Out-Null & "$env:SYSTEMROOT\system32\klist.exe" tgt | Out-Null & "$env:SYSTEMROOT\system32\taskkill.exe" "/F" "/IM" "explorer.exe" | Out-Null if (!$UseSmartcard) { & "$env:SYSTEMROOT\system32\runas.exe" "/user:$env:USERDOMAIN\$env:USERNAME" "explorer.exe" } else { & "$env:SYSTEMROOT\system32\runas.exe" "/user:$env:USERDOMAIN\$env:USERNAME" "/smartcard" "explorer.exe" } if ($Credential -ne [System.Management.Automation.PSCredential]::Empty) { $Command = @" `$Groups = whoami /groups /FO CSV | ConvertFrom-Csv | Select-Object -ExpandProperty "Group Name" `$Groups2 = [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups.Translate([System.Security.Principal.NTAccount]) | Select-Object -ExpandProperty Value `$Groups += `$Groups2 `$Groups | Select-Object -Unique "@ #Encode the command because it does not like the Open and Close parentheses $Bytes = [System.Text.Encoding]::Unicode.GetBytes($Command) $EncodedCommand = [Convert]::ToBase64String($Bytes) #Because Start-Process does not capture the standard out as part of the object, it can only be redirected to a file #Use the .NET object in order to capture the standard out without writing to file $ProcessInfo = New-Object -TypeName System.Diagnostics.ProcessStartInfo $ProcessInfo.FileName = "$env:SYSTEMROOT\System32\windowspowershell\v1.0\powershell.exe" $ProcessInfo.CreateNoWindow = $true $ProcessInfo.Verb = "runas" $ProcessInfo.RedirectStandardError = $true $ProcessInfo.RedirectStandardOutput = $true $ProcessInfo.UseShellExecute = $false $ProcessInfo.LoadUserProfile = $false $ProcessInfo.Domain = $Credential.UserName.Substring(0, $Credential.UserName.IndexOf("\")) $ProcessInfo.UserName = $Credential.UserName.Substring($Credential.UserName.IndexOf("\") + 1) $ProcessInfo.Password = $Credential.Password $ProcessInfo.Arguments = "-EncodedCommand $EncodedCommand" $Process = New-Object -TypeName System.Diagnostics.Process $Process.StartInfo = $ProcessInfo $Process.Start() | Out-Null $Process.WaitForExit() if ($Process.ExitCode -eq 0) { $NewGroups = @() $Process.StandardOutput.ReadToEnd().Split("`r`n") | ForEach-Object { if ($_ -ne $null -and $_ -ne [System.String]::Empty) { $NewGroups += $_ } } Write-Host "" foreach ($OldGroup in $CurrentGroups) { if (!$NewGroups.Contains($OldGroup) -and $OldGroup -ne "CONSOLE LOGON") { Write-Host "REMOVED : $OldGroup" -ForegroundColor Red } } Write-Host "" foreach ($NewGroup in $NewGroups) { if (!($CurrentGroups.Contains($NewGroup)) -and !$NewGroup.StartsWith("Mandatory Label\")) { Write-Host "ADDED : $NewGroup" -ForegroundColor Green } } } else { throw $Process.StandardError.ReadToEnd() } } } End {} } Function Get-ProcessToken { <# .SYNOPSIS Gets the token handle for a specified process. .DESCRIPTION The Get-ProcessToken cmdlet gets a token handle pointer for a specified process. The CmdLet must be run with elevated permissions. .PARAMETER ProcessName The name of the process to get a token handle for. .PARAMETER ProcessId The Id of the process to get a token handle for. .PARAMETER CloseHandle Specifies if the handle to the token should be closed. Do not close the handle if you want to duplicate the token in another process. .EXAMPLE Get-ProcessToken -ProcessName lsass Gets the token handle for the lsass process. .INPUTS System.String, System.Int32 .OUTPUTS System.IntPtr .NOTES AUTHOR: Michael Haken LAST UPDATE: 3/25/2016 #> [CmdletBinding()] [OutputType([System.IntPtr])] Param( [Parameter()] [Switch]$CloseHandle ) DynamicParam { # Create the dictionary $RuntimeParameterDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary $Set = Get-Process | Select-Object -Property Name, Id New-DynamicParameter -Name "ProcessName" -Alias "Name" -Mandatory -ParameterSets "Name" -Type ([System.String]) -Position 0 -ValueFromPipeline -ValidateSet ($Set | Select-Object -ExpandProperty Name) -RuntimeParameterDictionary $RuntimeParameterDictionary | Out-Null New-DynamicParameter -Name "ProcessId" -Alias "Id" -Mandatory -ParameterSets "Id" -Type ([System.Int32]) -Position 0 -ValueFromPipeline -ValidateSet ($Set | Select-Object -ExpandProperty Id) -RuntimeParameterDictionary $RuntimeParameterDictionary | Out-Null return $RuntimeParameterDictionary } Begin { if (-not (Test-IsLocalAdmin)) { throw "Run the cmdlet with elevated credentials." } if (!([System.Management.Automation.PSTypeName]"BAMCIS.PowerShell.TokenManipulation.Token").Type) { Add-Type -TypeDefinition $script:TokenSignature } } Process { [IntPtr]$DulicateTokenHandle = [IntPtr]::Zero [IntPtr]$ProcessTokenHandle = [IntPtr]::Zero try { switch ($PSCmdlet.ParameterSetName) { "Name" { $Process = Get-Process -Name $PSBoundParameters["ProcessName"] break } "Id" { $Process = Get-Process -Id $PSBoundParameters["ProcessId"] break } default { throw "Cannot determine parameter set." } } $ReturnValue = [BAMCIS.PowerShell.TokenManipulation.Token]::OpenProcessToken($Process.Handle, ([BAMCIS.PowerShell.TokenManipulation.Token]::TOKEN_IMPERSONATE -BOR [BAMCIS.PowerShell.TokenManipulation.Token]::TOKEN_DUPLICATE), [ref]$ProcessTokenHandle) $ReturnValue = [BAMCIS.PowerShell.TokenManipulation.Token]::DuplicateToken($ProcessTokenHandle, [BAMCIS.PowerShell.TokenManipulation.Token+SECURITY_IMPERSONATION_LEVEL]::SecurityImpersonation, [ref]$DulicateTokenHandle) if($ReturnValue -eq $null -or $ReturnValue -eq $false) { throw (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.marshal]::GetLastWin32Error())) } } finally { [BAMCIS.PowerShell.TokenManipulation.Token]::CloseHandle($ProcessTokenHandle) | Out-Null if ($CloseHandle) { [BAMCIS.PowerShell.TokenManipulation.Token]::CloseHandle($DulicateTokenHandle) | Out-Null } } Write-Output -InputObject $DulicateTokenHandle } End { } } Function Set-ProcessToken { <# .SYNOPSIS Replaces the process token for the current process thread with a token from another process. .DESCRIPTION The Set-ProcessToken cmdlet takes a token handle from another process and then sets the process thread to use that token. Then it closes the token handle. The passed token handle must not be closed before it is passed. The CmdLet must be run with elevated permissions. .PARAMETER TokenHandle The Token Handle pointer that will replace the current process thread token. .PARAMETER ElevatePrivileges Adds the SeDebugPrivilege to the current process thread, which may be needed to replace the current process thread token. .EXAMPLE Get-ProcessToken -ProcessName lsass | Set-ProcessToken Gets the token handle for the lsass process and replaces the current process thread token. .INPUTS System.IntPtr .OUTPUTS None .NOTES AUTHOR: Michael Haken LAST UPDATE: 10/23/2017 #> [CmdletBinding()] [OutputType()] Param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [System.IntPtr]$TokenHandle, [Parameter()] [Switch]$ElevatePrivileges ) Begin { if (-not (Test-IsLocalAdmin)) { throw "Run the cmdlet with elevated credentials." } } Process { if (!([System.Management.Automation.PSTypeName]"BAMCIS.PowerShell.TokenManipulation.Token").Type) { Add-Type -TypeDefinition $script:TokenSignature } if ($ElevatePrivileges) { Set-TokenPrivilege -Privileges SeDebugPrivilege -Enable } try { $ReturnValue = [BAMCIS.PowerShell.TokenManipulation.Token]::SetThreadToken([IntPtr]::Zero, $TokenHandle) if($ReturnValue -eq $null -or $ReturnValue -eq $false) { throw (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.Marshal]::GetLastWin32Error())) } } finally { [BAMCIS.PowerShell.TokenManipulation.Token]::CloseHandle($TokenHandle) | Out-Null } Write-Log -Message "Successfully duplicated token to current process thread." -Level VERBOSE } End { } } Function Reset-ProcessToken { <# .SYNOPSIS Reverts to the process thread token to the current user. .DESCRIPTION The Reset-ProcessToken cmdlet needs to be called to end any process impersonation called through DdeImpersonateClient, ImpersonateDdeClientWindow, ImpersonateLoggedOnUser, ImpersonateNamedPipeClient, ImpersonateSelf, ImpersonateAnonymousToken or SetThreadToken. Underlying the cmdlet is a P/Invoke call to RevertToSelf() in AdvApi32.dll. The CmdLet must be run with elevated permissions. .EXAMPLE Reset-ProcessToken Reverts the process thread to use the token of the current user. .INPUTS None .OUTPUTS None .NOTES AUTHOR: Michael Haken LAST UPDATE: 3/25/2016 #> [CmdletBinding()] [OutputType()] Param() Begin { if (-not (Test-IsLocalAdmin)) { throw "Run the cmdlet with elevated credentials." } } Process { if (!([System.Management.Automation.PSTypeName]"BAMCIS.PowerShell.TokenManipulation.Token").Type) { Add-Type -TypeDefinition $script:TokenSignature } #RevertToSelf is equivalent to SetThreadToken([System.IntPtr]::Zero, [System.IntPtr]::Zero) $ReturnValue = [BAMCIS.PowerShell.TokenManipulation.Token]::RevertToSelf() if($ReturnValue -eq $null -or $ReturnValue -eq $false) { throw (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.Marshal]::GetLastWin32Error())) } Write-Log -Message "Successfully executed RevertToSelf() and reset the process thread token." -Level VERBOSE } End { } } Function Set-TokenPrivilege { <# .SYNOPSIS Enables or disables security privileges for the current user's process. .DESCRIPTION This cmdlet enables or disables available security privileges for the current user. .PARAMETER Privileges The privileges to enable or disable. .PARAMETER Enable Enables the privileges. .PARAMETER Disable Disables the privileges. .INPUTS None .OUTPUTS None .EXAMPLE Set-TokenPrivilege -Privileges SeSecurityPrivilege -Enable Enables the SeSecurityPrivilege for the user running the cmdlet. .NOTES AUTHOR: Michael Haken LAST UPDATE: 10/23/2017 #> [CmdletBinding()] [OutputType()] Param( ## The privilege to adjust. This set is taken from ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)] [ValidateSet( "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege", "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege", "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege", "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege", "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege", "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege", "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege", "SeUndockPrivilege", "SeUnsolicitedInputPrivilege" )] [System.String[]]$Privileges, [Parameter(ParameterSetName = "Enable", Mandatory = $true)] [Switch]$Enable, [Parameter(ParameterSetName = "Disable", Mandatory = $true)] [Switch]$Disable ) Begin { if (-not (Test-IsLocalAdmin)) { throw "Run the cmdlet with elevated credentials." } if (-not ([System.Management.Automation.PSTypeName]"BAMCIS.PowerShell.TokenManipulation.Token").Type) { Add-Type -TypeDefinition $script:TokenSignature } } Process { foreach ($Privilege in $Privileges) { [BAMCIS.PowerShell.TokenManipulation.Token+TokPriv1Luid]$TokenPrivilege1Luid = New-Object BAMCIS.PowerShell.TokenManipulation.Token+TokPriv1Luid $TokenPrivilege1Luid.Count = 1 $TokenPrivilege1Luid.Luid = 0 if ($Enable) { $TokenPrivilege1Luid.Attr = [BAMCIS.PowerShell.TokenManipulation.Token]::SE_PRIVILEGE_ENABLED } else { $TokenPrivilege1Luid.Attr = [BAMCIS.PowerShell.TokenManipulation.Token]::SE_PRIVILEGE_DISABLED } [System.IntPtr]$TokenHandle = [System.IntPtr]::Zero $Temp = $null $ReturnValue = [BAMCIS.PowerShell.TokenManipulation.Token]::LookupPrivilegeValue($null, $Privilege, [ref]$Temp) if ($ReturnValue -eq $true) { $TokenPrivilege1Luid.Luid = $Temp $ReturnValue = [BAMCIS.PowerShell.TokenManipulation.Token]::OpenProcessToken([BAMCIS.PowerShell.TokenManipulation.Token]::GetCurrentProcess(), [BAMCIS.PowerShell.TokenManipulation.Token]::TOKEN_ADJUST_PRIVILEGES -BOR [BAMCIS.PowerShell.TokenManipulation.Token]::TOKEN_QUERY, [ref]$TokenHandle) $DisableAllPrivileges = $false $ReturnValue = [BAMCIS.PowerShell.TokenManipulation.Token]::AdjustTokenPrivileges($TokenHandle, $DisableAllPrivileges, [ref]$TokenPrivilege1Luid, [System.Runtime.InteropServices.Marshal]::SizeOf($TokenPrivilege1Luid), [IntPtr]::Zero, [IntPtr]::Zero) if($ReturnValue -eq $null -or $ReturnValue -eq $false) { throw (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.Marrshal]::GetLastWin32Error())) } } else { throw (New-Object -TypeName System.Exception([System.ComponentModel.Win32Exception][System.Runtime.InteropServices.Marrshal]::GetLastWin32Error())) } } } End { } } $script:TokenSignature = @" using System; using System.Runtime.InteropServices; namespace BAMCIS.PowerShell.TokenManipulation { public class Token { public const int ANYSIZE_ARRAY = 1; public enum SECURITY_IMPERSONATION_LEVEL { SecurityAnonymous = 0, SecurityIdentification = 1, SecurityImpersonation = 2, SecurityDelegation = 3 } public enum TOKEN_INFORMATION_CLASS { /// <summary> /// The buffer receives a TOKEN_USER structure that contains the user account of the token. /// </summary> TokenUser = 1, /// <summary> /// The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token. /// </summary> TokenGroups, /// <summary> /// The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token. /// </summary> TokenPrivileges, /// <summary> /// The buffer receives a TOKEN_OWNER structure that contains the default owner security identifier (SID) for newly created objects. /// </summary> TokenOwner, /// <summary> /// The buffer receives a TOKEN_PRIMARY_GROUP structure that contains the default primary group SID for newly created objects. /// </summary> TokenPrimaryGroup, /// <summary> /// The buffer receives a TOKEN_DEFAULT_DACL structure that contains the default DACL for newly created objects. /// </summary> TokenDefaultDacl, /// <summary> /// The buffer receives a TOKEN_SOURCE structure that contains the source of the token. TOKEN_QUERY_SOURCE access is needed to retrieve this information. /// </summary> TokenSource, /// <summary> /// The buffer receives a TOKEN_TYPE value that indicates whether the token is a primary or impersonation token. /// </summary> TokenType, /// <summary> /// The buffer receives a SECURITY_IMPERSONATION_LEVEL value that indicates the impersonation level of the token. If the access token is not an impersonation token, the function fails. /// </summary> TokenImpersonationLevel, /// <summary> /// The buffer receives a TOKEN_STATISTICS structure that contains various token statistics. /// </summary> TokenStatistics, /// <summary> /// The buffer receives a TOKEN_GROUPS structure that contains the list of restricting SIDs in a restricted token. /// </summary> TokenRestrictedSids, /// <summary> /// The buffer receives a DWORD value that indicates the Terminal Services session identifier that is associated with the token. /// </summary> TokenSessionId, /// <summary> /// The buffer receives a TOKEN_GROUPS_AND_PRIVILEGES structure that contains the user SID, the group accounts, the restricted SIDs, and the authentication ID associated with the token. /// </summary> TokenGroupsAndPrivileges, /// <summary> /// Reserved. /// </summary> TokenSessionReference, /// <summary> /// The buffer receives a DWORD value that is nonzero if the token includes the SANDBOX_INERT flag. /// </summary> TokenSandBoxInert, /// <summary> /// Reserved. /// </summary> TokenAuditPolicy, /// <summary> /// The buffer receives a TOKEN_ORIGIN value. /// </summary> TokenOrigin, /// <summary> /// The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token. /// </summary> TokenElevationType, /// <summary> /// The buffer receives a TOKEN_LINKED_TOKEN structure that contains a handle to another token that is linked to this token. /// </summary> TokenLinkedToken, /// <summary> /// The buffer receives a TOKEN_ELEVATION structure that specifies whether the token is elevated. /// </summary> TokenElevation, /// <summary> /// The buffer receives a DWORD value that is nonzero if the token has ever been filtered. /// </summary> TokenHasRestrictions, /// <summary> /// The buffer receives a TOKEN_ACCESS_INFORMATION structure that specifies security information contained in the token. /// </summary> TokenAccessInformation, /// <summary> /// The buffer receives a DWORD value that is nonzero if virtualization is allowed for the token. /// </summary> TokenVirtualizationAllowed, /// <summary> /// The buffer receives a DWORD value that is nonzero if virtualization is enabled for the token. /// </summary> TokenVirtualizationEnabled, /// <summary> /// The buffer receives a TOKEN_MANDATORY_LABEL structure that specifies the token's integrity level. /// </summary> TokenIntegrityLevel, /// <summary> /// The buffer receives a DWORD value that is nonzero if the token has the UIAccess flag set. /// </summary> TokenUIAccess, /// <summary> /// The buffer receives a TOKEN_MANDATORY_POLICY structure that specifies the token's mandatory integrity policy. /// </summary> TokenMandatoryPolicy, /// <summary> /// The buffer receives the token's logon security identifier (SID). /// </summary> TokenLogonSid, /// <summary> /// The maximum value for this enumeration /// </summary> MaxTokenInfoClass } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TokPriv1Luid { public int Count; public long Luid; public int Attr; } [StructLayout(LayoutKind.Sequential)] public struct TOKEN_USER { public SID_AND_ATTRIBUTES User; } [StructLayout(LayoutKind.Sequential)] public struct TOKEN_GROUPS { public UInt32 GroupCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst = ANYSIZE_ARRAY)] public SID_AND_ATTRIBUTES[] Groups; }; [StructLayout(LayoutKind.Sequential)] public struct SID_AND_ATTRIBUTES { public IntPtr Sid; public UInt32 Attributes; } [StructLayout(LayoutKind.Sequential)] public struct LUID { public UInt32 LowPart; public UInt32 HighPart; } [StructLayout(LayoutKind.Sequential)] public struct LUID_AND_ATTRIBUTES { public LUID Luid; public UInt32 Attributes; } [StructLayout(LayoutKind.Sequential)] public struct TOKEN_PRIVILEGES { public UInt32 PrivilegeCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst=ANYSIZE_ARRAY)] public LUID_AND_ATTRIBUTES[] Privileges; } public const int SE_PRIVILEGE_DISABLED = 0x00000000; public const int SE_PRIVILEGE_ENABLED = 0x00000002; public const UInt32 SE_GROUP_LOGON_ID = 0xC0000000; public const int TOKEN_QUERY = 0x00000008; public const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000; public const UInt32 STANDARD_RIGHTS_READ = 0x00020000; public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001; public const UInt32 TOKEN_DUPLICATE = 0x0002; public const UInt32 TOKEN_IMPERSONATE = 0x0004; public const UInt32 TOKEN_QUERY_SOURCE = 0x0010; public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040; public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080; public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100; public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); public const UInt32 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); public const string SE_TIME_ZONE_NAMETEXT = "SeTimeZonePrivilege"; [DllImport("advapi32.dll", SetLastError=true)] public static extern bool GetTokenInformation( IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, UInt32 TokenInformationLength, out UInt32 ReturnLength ); [DllImport("advapi32", SetLastError=true, CharSet=CharSet.Auto)] public static extern bool ConvertSidToStringSid( IntPtr pSID, [In,Out,MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid ); [DllImport("advapi32.dll", SetLastError=true)] public extern static bool DuplicateToken( IntPtr ExistingTokenHandle, Int32 SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle ); [DllImport("advapi32.dll", SetLastError=true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetThreadToken( IntPtr PHThread, IntPtr Token ); [DllImport("advapi32.dll", SetLastError=true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool OpenProcessToken( IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle ); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool LookupPrivilegeValue( string host, string name, ref long pluid ); [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)] public static extern IntPtr GetCurrentProcess(); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] public static extern bool AdjustTokenPrivileges( IntPtr htok, bool disall, ref TokPriv1Luid newst, Int32 len, IntPtr prev, IntPtr relen ); [DllImport( "kernel32.dll", CharSet = CharSet.Auto, SetLastError = true )] public static extern bool CloseHandle(IntPtr handle); [DllImport("advapi32.dll", SetLastError = true)] public static extern bool RevertToSelf(); [DllImport("kernel32.dll")] static extern IntPtr LocalFree(IntPtr hMem); public static bool AddPrivilege(string privilege) { try { bool ReturnValue; TokPriv1Luid TokenPrivilege; IntPtr ProcessHandle = GetCurrentProcess(); IntPtr TokenHandle = IntPtr.Zero; ReturnValue = OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out TokenHandle); TokenPrivilege.Count = 1; TokenPrivilege.Luid = 0; TokenPrivilege.Attr = SE_PRIVILEGE_ENABLED; ReturnValue = LookupPrivilegeValue(null, privilege, ref TokenPrivilege.Luid); ReturnValue = AdjustTokenPrivileges(TokenHandle, false, ref TokenPrivilege, 0, IntPtr.Zero, IntPtr.Zero); return ReturnValue; } catch (Exception ex) { throw ex; } } public static bool RemovePrivilege(string privilege) { try { bool ReturnValue; TokPriv1Luid TokenPrivilege; IntPtr ProcessHandle = GetCurrentProcess(); IntPtr TokenHandle = IntPtr.Zero; ReturnValue = OpenProcessToken(ProcessHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out TokenHandle); TokenPrivilege.Count = 1; TokenPrivilege.Luid = 0; TokenPrivilege.Attr = SE_PRIVILEGE_DISABLED; ReturnValue = LookupPrivilegeValue(null, privilege, ref TokenPrivilege.Luid); ReturnValue = AdjustTokenPrivileges(TokenHandle, false, ref TokenPrivilege, 0, IntPtr.Zero, IntPtr.Zero); return ReturnValue; } catch (Exception ex) { throw ex; } } } } "@ |