DCOMPermissions.psm1
<#
VERSION DATE AUTHOR 1.0.09 2017-09-15 Tony Pombo - Initial Release 1.1.03 2017-09-22 Tony Pombo - Replaced localized English names with SIDs - Minor code cleanup #> # Revision History #Requires -Version 4.0 Set-StrictMode -Version 2.0 $ACL_REVISION = 2 $COM_RIGHTS_EXECUTE = 1 $COM_RIGHTS_EXECUTE_LOCAL = 2 $COM_RIGHTS_EXECUTE_REMOTE = 4 $COM_RIGHTS_ACTIVATE_LOCAL = 8 $COM_RIGHTS_ACTIVATE_REMOTE = 16 $Admins_SID = [System.Security.Principal.SecurityIdentifier]"S-1-5-32-544" $System_SID = [System.Security.Principal.SecurityIdentifier]"S-1-5-18" # The code for: Add-Type, Grant-TokenPrivilege, Revoke-TokenPrivilege # is a subset of the "Grant, Revoke, Query user rights (privileges) using PowerShell" v1.3.1 # script available at https://gallery.technet.microsoft.com/Grant-Revoke-Query-user-26e259b0 Add-Type @' using System; namespace PS_LSA { using System.ComponentModel; using System.Runtime.InteropServices; using System.Security; public enum Rights { SeTrustedCredManAccessPrivilege, // Access Credential Manager as a trusted caller SeNetworkLogonRight, // Access this computer from the network SeTcbPrivilege, // Act as part of the operating system SeMachineAccountPrivilege, // Add workstations to domain SeIncreaseQuotaPrivilege, // Adjust memory quotas for a process SeInteractiveLogonRight, // Allow log on locally SeRemoteInteractiveLogonRight, // Allow log on through Remote Desktop Services SeBackupPrivilege, // Back up files and directories SeChangeNotifyPrivilege, // Bypass traverse checking SeSystemtimePrivilege, // Change the system time SeTimeZonePrivilege, // Change the time zone SeCreatePagefilePrivilege, // Create a pagefile SeCreateTokenPrivilege, // Create a token object SeCreateGlobalPrivilege, // Create global objects SeCreatePermanentPrivilege, // Create permanent shared objects SeCreateSymbolicLinkPrivilege, // Create symbolic links SeDebugPrivilege, // Debug programs SeDenyNetworkLogonRight, // Deny access this computer from the network SeDenyBatchLogonRight, // Deny log on as a batch job SeDenyServiceLogonRight, // Deny log on as a service SeDenyInteractiveLogonRight, // Deny log on locally SeDenyRemoteInteractiveLogonRight, // Deny log on through Remote Desktop Services SeEnableDelegationPrivilege, // Enable computer and user accounts to be trusted for delegation SeRemoteShutdownPrivilege, // Force shutdown from a remote system SeAuditPrivilege, // Generate security audits SeImpersonatePrivilege, // Impersonate a client after authentication SeIncreaseWorkingSetPrivilege, // Increase a process working set SeIncreaseBasePriorityPrivilege, // Increase scheduling priority SeLoadDriverPrivilege, // Load and unload device drivers SeLockMemoryPrivilege, // Lock pages in memory SeBatchLogonRight, // Log on as a batch job SeServiceLogonRight, // Log on as a service SeSecurityPrivilege, // Manage auditing and security log SeRelabelPrivilege, // Modify an object label SeSystemEnvironmentPrivilege, // Modify firmware environment values SeManageVolumePrivilege, // Perform volume maintenance tasks SeProfileSingleProcessPrivilege, // Profile single process SeSystemProfilePrivilege, // Profile system performance SeUnsolicitedInputPrivilege, // "Read unsolicited input from a terminal device" SeUndockPrivilege, // Remove computer from docking station SeAssignPrimaryTokenPrivilege, // Replace a process level token SeRestorePrivilege, // Restore files and directories SeShutdownPrivilege, // Shut down the system SeSyncAgentPrivilege, // Synchronize directory service data SeTakeOwnershipPrivilege // Take ownership of files or other objects } public sealed class TokenManipulator { [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct TokPriv1Luid { public int Count; public long Luid; public int Attr; } internal const int SE_PRIVILEGE_DISABLED = 0x00000000; internal const int SE_PRIVILEGE_ENABLED = 0x00000002; internal const int TOKEN_QUERY = 0x00000008; internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020; internal sealed class Win32Token { [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool AdjustTokenPrivileges( IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen ); [DllImport("kernel32.dll", ExactSpelling = true)] internal static extern IntPtr GetCurrentProcess(); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool OpenProcessToken( IntPtr h, int acc, ref IntPtr phtok ); [DllImport("advapi32.dll", SetLastError = true)] internal static extern bool LookupPrivilegeValue( string host, string name, ref long pluid ); [DllImport("kernel32.dll", ExactSpelling = true)] internal static extern bool CloseHandle( IntPtr phtok ); } public static void AddPrivilege(Rights privilege) { bool retVal; int lasterror; TokPriv1Luid tp; IntPtr hproc = Win32Token.GetCurrentProcess(); IntPtr htok = IntPtr.Zero; retVal = Win32Token.OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); tp.Count = 1; tp.Luid = 0; tp.Attr = SE_PRIVILEGE_ENABLED; retVal = Win32Token.LookupPrivilegeValue(null, privilege.ToString(), ref tp.Luid); retVal = Win32Token.AdjustTokenPrivileges(htok, false, ref tp, Marshal.SizeOf(tp), IntPtr.Zero, IntPtr.Zero); Win32Token.CloseHandle(htok); lasterror = Marshal.GetLastWin32Error(); if (lasterror != 0) throw new Win32Exception(); } public static void RemovePrivilege(Rights privilege) { bool retVal; int lasterror; TokPriv1Luid tp; IntPtr hproc = Win32Token.GetCurrentProcess(); IntPtr htok = IntPtr.Zero; retVal = Win32Token.OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok); tp.Count = 1; tp.Luid = 0; tp.Attr = SE_PRIVILEGE_DISABLED; retVal = Win32Token.LookupPrivilegeValue(null, privilege.ToString(), ref tp.Luid); retVal = Win32Token.AdjustTokenPrivileges(htok, false, ref tp, Marshal.SizeOf(tp), IntPtr.Zero, IntPtr.Zero); Win32Token.CloseHandle(htok); lasterror = Marshal.GetLastWin32Error(); if (lasterror != 0) throw new Win32Exception(); } } } '@ # This type is used by Grant-TokenPriviledge, Revoke-TokenPrivilege function Grant-TokenPrivilege { <# .SYNOPSIS Enables privileges in the current process token. .DESCRIPTION Enables one or more privileges for the current process token. If a privilege cannot be enabled, an exception is thrown. .PARAMETER Privilege Name of the privilege to enable. More than one privilege may be listed. Possible values: SeTrustedCredManAccessPrivilege Access Credential Manager as a trusted caller SeNetworkLogonRight Access this computer from the network SeTcbPrivilege Act as part of the operating system SeMachineAccountPrivilege Add workstations to domain SeIncreaseQuotaPrivilege Adjust memory quotas for a process SeInteractiveLogonRight Allow log on locally SeRemoteInteractiveLogonRight Allow log on through Remote Desktop Services SeBackupPrivilege Back up files and directories SeChangeNotifyPrivilege Bypass traverse checking SeSystemtimePrivilege Change the system time SeTimeZonePrivilege Change the time zone SeCreatePagefilePrivilege Create a pagefile SeCreateTokenPrivilege Create a token object SeCreateGlobalPrivilege Create global objects SeCreatePermanentPrivilege Create permanent shared objects SeCreateSymbolicLinkPrivilege Create symbolic links SeDebugPrivilege Debug programs SeDenyNetworkLogonRight Deny access this computer from the network SeDenyBatchLogonRight Deny log on as a batch job SeDenyServiceLogonRight Deny log on as a service SeDenyInteractiveLogonRight Deny log on locally SeDenyRemoteInteractiveLogonRight Deny log on through Remote Desktop Services SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation SeRemoteShutdownPrivilege Force shutdown from a remote system SeAuditPrivilege Generate security audits SeImpersonatePrivilege Impersonate a client after authentication SeIncreaseWorkingSetPrivilege Increase a process working set SeIncreaseBasePriorityPrivilege Increase scheduling priority SeLoadDriverPrivilege Load and unload device drivers SeLockMemoryPrivilege Lock pages in memory SeBatchLogonRight Log on as a batch job SeServiceLogonRight Log on as a service SeSecurityPrivilege Manage auditing and security log SeRelabelPrivilege Modify an object label SeSystemEnvironmentPrivilege Modify firmware environment values SeManageVolumePrivilege Perform volume maintenance tasks SeProfileSingleProcessPrivilege Profile single process SeSystemProfilePrivilege Profile system performance SeUnsolicitedInputPrivilege "Read unsolicited input from a terminal device" SeUndockPrivilege Remove computer from docking station SeAssignPrimaryTokenPrivilege Replace a process level token SeRestorePrivilege Restore files and directories SeShutdownPrivilege Shut down the system SeSyncAgentPrivilege Synchronize directory service data SeTakeOwnershipPrivilege Take ownership of files or other objects .EXAMPLE Grant-TokenPrivilege SeIncreaseWorkingSetPrivilege Enables the "Increase a process working set" privilege for the current process. .INPUTS PS_LSA.Rights Right .OUTPUTS None .LINK http://msdn.microsoft.com/en-us/library/aa375202.aspx http://msdn.microsoft.com/en-us/library/bb530716.aspx #> [CmdletBinding()] param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)] [Alias('Right')] [PS_LSA.Rights[]] $Privilege ) process { foreach ($Priv in $Privilege) { try { [PS_LSA.TokenManipulator]::AddPrivilege($Priv) } catch [System.ComponentModel.Win32Exception] { throw New-Object System.ComponentModel.Win32Exception("$($_.Exception.Message) ($Priv)", $_.Exception) } } } } # Enables privileges in the current process token function Revoke-TokenPrivilege { <# .SYNOPSIS Disables privileges in the current process token. .DESCRIPTION Disables one or more privileges for the current process token. If a privilege cannot be disabled, an exception is thrown. .PARAMETER Privilege Name of the privilege to disable. More than one privilege may be listed. Possible values: SeTrustedCredManAccessPrivilege Access Credential Manager as a trusted caller SeNetworkLogonRight Access this computer from the network SeTcbPrivilege Act as part of the operating system SeMachineAccountPrivilege Add workstations to domain SeIncreaseQuotaPrivilege Adjust memory quotas for a process SeInteractiveLogonRight Allow log on locally SeRemoteInteractiveLogonRight Allow log on through Remote Desktop Services SeBackupPrivilege Back up files and directories SeChangeNotifyPrivilege Bypass traverse checking SeSystemtimePrivilege Change the system time SeTimeZonePrivilege Change the time zone SeCreatePagefilePrivilege Create a pagefile SeCreateTokenPrivilege Create a token object SeCreateGlobalPrivilege Create global objects SeCreatePermanentPrivilege Create permanent shared objects SeCreateSymbolicLinkPrivilege Create symbolic links SeDebugPrivilege Debug programs SeDenyNetworkLogonRight Deny access this computer from the network SeDenyBatchLogonRight Deny log on as a batch job SeDenyServiceLogonRight Deny log on as a service SeDenyInteractiveLogonRight Deny log on locally SeDenyRemoteInteractiveLogonRight Deny log on through Remote Desktop Services SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation SeRemoteShutdownPrivilege Force shutdown from a remote system SeAuditPrivilege Generate security audits SeImpersonatePrivilege Impersonate a client after authentication SeIncreaseWorkingSetPrivilege Increase a process working set SeIncreaseBasePriorityPrivilege Increase scheduling priority SeLoadDriverPrivilege Load and unload device drivers SeLockMemoryPrivilege Lock pages in memory SeBatchLogonRight Log on as a batch job SeServiceLogonRight Log on as a service SeSecurityPrivilege Manage auditing and security log SeRelabelPrivilege Modify an object label SeSystemEnvironmentPrivilege Modify firmware environment values SeManageVolumePrivilege Perform volume maintenance tasks SeProfileSingleProcessPrivilege Profile single process SeSystemProfilePrivilege Profile system performance SeUnsolicitedInputPrivilege "Read unsolicited input from a terminal device" SeUndockPrivilege Remove computer from docking station SeAssignPrimaryTokenPrivilege Replace a process level token SeRestorePrivilege Restore files and directories SeShutdownPrivilege Shut down the system SeSyncAgentPrivilege Synchronize directory service data SeTakeOwnershipPrivilege Take ownership of files or other objects .EXAMPLE Revoke-TokenPrivilege SeIncreaseWorkingSetPrivilege Disables the "Increase a process working set" privilege for the current process. .INPUTS PS_LSA.Rights Right .OUTPUTS None .LINK http://msdn.microsoft.com/en-us/library/aa375202.aspx http://msdn.microsoft.com/en-us/library/bb530716.aspx #> [CmdletBinding()] param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)] [Alias('Right')] [PS_LSA.Rights[]] $Privilege ) process { foreach ($Priv in $Privilege) { try { [PS_LSA.TokenManipulator]::RemovePrivilege($Priv) } catch [System.ComponentModel.Win32Exception] { throw New-Object System.ComponentModel.Win32Exception("$($_.Exception.Message) ($Priv)", $_.Exception) } } } } # Disables privileges in the current process token function Get-DComPermission { <# .SYNOPSIS Gets DCOM Permissions for a specified Application ID .DESCRIPTION Retrieves either the "Access Permissions" or "Launch and Activation Permissions" for a specified Application ID .PARAMETER ApplicationID The Application ID for the DCOM object .PARAMETER Type Indicates which type of permissions to retrieve Valid options: Launch, Access .EXAMPLE Get-DCOMPermission -ApplicationID "{9CA88EE3-ACB7-47C8-AFC4-AB702511C276}" -Type Launch .INPUTS String ApplicationID String Type .OUTPUTS String ApplicationID String Type String[] Access Int AccessMask System.Security.Principal.SecurityIdentifier SID String Name #> param( [Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true)] [Alias("APPID")] [string[]] $ApplicationID, [Parameter(Position=1, Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [ValidateSet("Launch","Access")] [string] $Type ) begin { $ErrorActionPreference = "Stop" New-PSDrive -PSProvider Registry -Root HKEY_CLASSES_ROOT -Name HKCR -Scope Local -ErrorAction SilentlyContinue | Out-Null } process { foreach ($APPID in $ApplicationID) { Write-Verbose "Getting registry value HKCR:\AppID\$APPID\$($Type)Permission" $regkey = Get-Item -Path "HKCR:\AppID\$APPID" try { $reg_perms = ($regkey | Get-ItemProperty -Name "$($Type)Permission")."$($Type)Permission" } catch { if ($_.Exception.Message -match "Property $($Type)Permission does not exist") { return "Default $Type permissions are inherited for $APPID" } else {throw $_ } } $sd = New-Object System.Security.AccessControl.RawSecurityDescriptor($reg_perms, 0) foreach ($ace in $sd.DiscretionaryAcl) { Write-Verbose "Working on $($ace.SecurityIdentifier)" try { $User = (($ace.SecurityIdentifier).Translate([System.Security.Principal.NTAccount])).Value } catch { Write-Warning "Unable to map SID to name. $($ace.SecurityIdentifier)" ; $User=$null } $access = @() if ($Type -eq "Launch") { if ( ($ace.AccessMask -band $COM_RIGHTS_EXECUTE_LOCAL) -or (($ace.AccessMask -band $COM_RIGHTS_EXECUTE) -and -not ($ace.AccessMask -band ($COM_RIGHTS_EXECUTE_REMOTE -bor $COM_RIGHTS_ACTIVATE_REMOTE -bor $COM_RIGHTS_ACTIVATE_LOCAL))) ) { $access += "LocalLaunch" } if ( ($ace.AccessMask -band $COM_RIGHTS_EXECUTE_REMOTE) -or (($ace.AccessMask -band $COM_RIGHTS_EXECUTE) -and -not ($ace.AccessMask -band ($COM_RIGHTS_EXECUTE_LOCAL -bor $COM_RIGHTS_ACTIVATE_REMOTE -bor $COM_RIGHTS_ACTIVATE_LOCAL))) ) { $access += "RemoteLaunch" } if ( ($ace.AccessMask -band $COM_RIGHTS_ACTIVATE_LOCAL) -or (($ace.AccessMask -band $COM_RIGHTS_EXECUTE) -and -not ($ace.AccessMask -band ($COM_RIGHTS_EXECUTE_LOCAL -bor $COM_RIGHTS_EXECUTE_REMOTE -bor $COM_RIGHTS_ACTIVATE_REMOTE))) ) { $access += "LocalActivation" } if ( ($ace.AccessMask -band $COM_RIGHTS_ACTIVATE_REMOTE) -or (($ace.AccessMask -band $COM_RIGHTS_EXECUTE) -and -not ($ace.AccessMask -band ($COM_RIGHTS_EXECUTE_LOCAL -bor $COM_RIGHTS_EXECUTE_REMOTE -bor $COM_RIGHTS_ACTIVATE_LOCAL))) ) { $access += "RemoteActivation" } } else { if ( ($ace.AccessMask -band $COM_RIGHTS_EXECUTE_LOCAL) -or (($ace.AccessMask -band $COM_RIGHTS_EXECUTE) -and -not ($ace.AccessMask -band $COM_RIGHTS_EXECUTE_REMOTE)) ) { $access += "LocalAccess" } if ( ($ace.AccessMask -band $COM_RIGHTS_EXECUTE_REMOTE) -or (($ace.AccessMask -band $COM_RIGHTS_EXECUTE) -and -not ($ace.AccessMask -band $COM_RIGHTS_EXECUTE_LOCAL)) ) { $access += "RemoteAccess" } } New-Object -TypeName PSObject -Property @{ "ApplicationID" = $APPID "Type" = $ace.AceType ; "Access" = $access ; "AccessMask" = $ace.AccessMask ; "SID" = $ace.SecurityIdentifier ; "Name" = $User } } } } } function Grant-DComPermissionInternal { param( [string] $ApplicationID, [string] $Type, [System.Security.Principal.SecurityIdentifier] $SID, [string[]] $Permissions, [System.Security.AccessControl.AceType] $AceType, [Switch] $PassThru ) New-PSDrive -PSProvider Registry -Root HKEY_CLASSES_ROOT -Name HKCR -Scope Local -ErrorAction SilentlyContinue | Out-Null Write-Verbose "Getting registry value responsible for COM security" $regkey = Get-Item -Path "HKCR:\AppID\$ApplicationID" try { $reg_perms = ($regkey | Get-ItemProperty -Name "$($Type)Permission")."$($Type)Permission" $sd = New-Object System.Security.AccessControl.RawSecurityDescriptor($reg_perms, 0) } catch { Write-Verbose "Replacing default permissions with new security descriptor" $sd = New-Object System.Security.AccessControl.RawSecurityDescriptor( ([System.Security.AccessControl.ControlFlags]::DiscretionaryAclPresent -bor [System.Security.AccessControl.ControlFlags]::SelfRelative), $System_SID, $System_SID, $null, $(New-Object System.Security.AccessControl.RawAcl($ACL_REVISION,1)) ) } Write-Verbose "Determining new ACE properties" $AccessMask = $COM_RIGHTS_EXECUTE if ($Permissions -contains "ALL") { if ($Type -eq "Launch") { $AccessMask = $AccessMask -bor $COM_RIGHTS_EXECUTE_LOCAL -bor $COM_RIGHTS_EXECUTE_REMOTE -bor $COM_RIGHTS_ACTIVATE_LOCAL -bor $COM_RIGHTS_ACTIVATE_REMOTE } else { $AccessMask = $AccessMask -bor $COM_RIGHTS_EXECUTE_LOCAL -bor $COM_RIGHTS_EXECUTE_REMOTE } } else { if ($Permissions -contains "LocalLaunch") { $AccessMask = $AccessMask -bor $COM_RIGHTS_EXECUTE_LOCAL } if ($Permissions -contains "RemoteLaunch") { $AccessMask = $AccessMask -bor $COM_RIGHTS_EXECUTE_REMOTE } if ($Permissions -contains "LocalActivation") { $AccessMask = $AccessMask -bor $COM_RIGHTS_ACTIVATE_LOCAL } if ($Permissions -contains "RemoteActivation") { $AccessMask = $AccessMask -bor $COM_RIGHTS_ACTIVATE_REMOTE } if ($Permissions -contains "LocalAccess") { $AccessMask = $AccessMask -bor $COM_RIGHTS_EXECUTE_LOCAL } if ($Permissions -contains "RemoteAccess") { $AccessMask = $AccessMask -bor $COM_RIGHTS_EXECUTE_REMOTE } } Write-Verbose "Searching for existing ACE for this user" $acl = $sd.DiscretionaryAcl $found = $false foreach ($ace in $acl) { if ($ace.SecurityIdentifier -eq $SID -and $ace.AceType -eq $AceType) { $ace.AccessMask = $ace.AccessMask -bor $AccessMask $found = $true break } } if (-not $found) { Write-Verbose "Not found, creating new ACE entry" $ace = New-Object System.Security.AccessControl.CommonAce( [System.Security.AccessControl.AceFlags]::None, [System.Security.AccessControl.AceQualifier]$AceType.value__, $AccessMask, $SID, $false, $null) if ($AceType -match "denied") { $acl.InsertAce(0, $ace) } else { $acl.InsertAce($acl.Count, $ace) } } Write-Verbose "Convert to binary and save the ACL" $sd.DiscretionaryAcl = $acl $sdbytes = New-Object 'byte[]' $sd.BinaryLength $sd.GetBinaryForm($sdbytes, 0) $regkey | New-ItemProperty -Name "$($Type)Permission" -PropertyType Binary -Value $sdBytes -Force | Out-Null if ($PassThru) { New-Object -TypeName PSObject -Property @{ "ApplicationID" = $ApplicationID ; "Type" = $Type } } } function Revoke-DComPermissionInternal { param( [string] $ApplicationID, [string] $Type, [System.Security.Principal.SecurityIdentifier] $SID, [string[]] $Permissions, [System.Security.AccessControl.AceType] $AceType, [Switch] $PassThru ) New-PSDrive -PSProvider Registry -Root HKEY_CLASSES_ROOT -Name HKCR -Scope Local -ErrorAction SilentlyContinue | Out-Null Write-Verbose "Getting registry value responsible for COM security" $regkey = Get-Item -Path "HKCR:\AppID\$ApplicationID" try { $reg_perms = ($regkey | Get-ItemProperty -Name "$($Type)Permission")."$($Type)Permission" $sd = New-Object System.Security.AccessControl.RawSecurityDescriptor($reg_perms, 0) } catch { Write-Warning "Using default permissions (no changes made)" ; return } Write-Verbose "Searching for existing ACE for this user" $acl = $sd.DiscretionaryAcl $found = $false for ($index=0 ; $index -lt $acl.Count; $index++) { $ace = $acl[$index] if ($ace.SecurityIdentifier -eq $SID -and $ace.AceType -eq $AceType) { Write-Verbose "Found ACE for this user" if ($Permissions -contains "LocalLaunch" -and $ace.AccessMask -band $COM_RIGHTS_EXECUTE_LOCAL) { $ace.AccessMask = $ace.AccessMask -bxor $COM_RIGHTS_EXECUTE_LOCAL } if ($Permissions -contains "RemoteLaunch" -and $ace.AccessMask -band $COM_RIGHTS_EXECUTE_REMOTE) { $ace.AccessMask = $ace.AccessMask -bxor $COM_RIGHTS_EXECUTE_REMOTE } if ($Permissions -contains "LocalActivation" -and $ace.AccessMask -band $COM_RIGHTS_ACTIVATE_LOCAL) { $ace.AccessMask = $ace.AccessMask -bxor $COM_RIGHTS_ACTIVATE_LOCAL } if ($Permissions -contains "RemoteActivation" -and $ace.AccessMask -band $COM_RIGHTS_ACTIVATE_REMOTE) { $ace.AccessMask = $ace.AccessMask -bxor $COM_RIGHTS_ACTIVATE_REMOTE } if ($Permissions -contains "LocalAccess" -and $ace.AccessMask -band $COM_RIGHTS_EXECUTE_LOCAL) { $ace.AccessMask = $ace.AccessMask -bxor $COM_RIGHTS_EXECUTE_LOCAL } if ($Permissions -contains "RemoteAccess" -and $ace.AccessMask -band $COM_RIGHTS_EXECUTE_REMOTE) { $ace.AccessMask = $ace.AccessMask -bxor $COM_RIGHTS_EXECUTE_REMOTE } if ($Permissions -contains "ALL" -or $ace.AccessMask -eq 0 -or $ace.AccessMask -eq $COM_RIGHTS_EXECUTE) { $acl.RemoveAce($index) } $found = $true break } } if (-not $found) { Write-Verbose "ACE not found, no changes made" } else { Write-Verbose "Convert to binary and save the ACL" $sd.DiscretionaryAcl = $acl $sdbytes = New-Object 'byte[]' $sd.BinaryLength $sd.GetBinaryForm($sdbytes, 0) $regkey | New-ItemProperty -Name "$($Type)Permission" -PropertyType Binary -Value $sdBytes -Force | Out-Null } if ($PassThru) { New-Object -TypeName PSObject -Property @{ "ApplicationID" = $ApplicationID ; "Type" = $Type } } } function Wrapper-DComPermission { param( [Parameter(Mandatory=$true)] [ValidateSet("Grant","Revoke")] [string] $Purpose, [string] $ApplicationID, [string] $Type, [string] $Account, [string[]] $Permissions, [Switch] $Deny, [Switch] $PassThru, [Switch] $OverrideConfigurationPermissions ) if ($Type -eq "Launch") { if ($Permissions -contains "LocalAccess") { throw New-Object System.ArgumentException("LocalAccess is not a valid Launch permission") } if ($Permissions -contains "RemoteAccess") { throw New-Object System.ArgumentException("RemoteAccess is not a valid Launch permission") } } else { if ($Permissions -contains "LocalLaunch") { throw New-Object System.ArgumentException("LocalLaunch is not a valid Access permission") } if ($Permissions -contains "RemoteLaunch") { throw New-Object System.ArgumentException("RemoteLaunch is not a valid Access permission") } if ($Permissions -contains "LocalActivation") { throw New-Object System.ArgumentException("LocalActivation is not a valid Access permission") } if ($Permissions -contains "RemoteActivation") { throw New-Object System.ArgumentException("RemoteActivation is not a valid Access permission") } } $AceType = [System.Security.AccessControl.AceType]::AccessAllowed if ($Deny) { $AceType = [System.Security.AccessControl.AceType]::AccessDenied } Write-Verbose "Getting SID from account name" $UserNTAccount = New-Object System.Security.Principal.NTAccount($Account) [System.Security.Principal.SecurityIdentifier] $SID = ($UserNTAccount.Translate([System.Security.Principal.SecurityIdentifier])).Value try { if ($Purpose -eq "Grant") { Grant-DComPermissionInternal -ApplicationID $ApplicationID -SID $SID -Type $Type -Permissions $Permissions -AceType $AceType -PassThru:$PassThru } else { Revoke-DComPermissionInternal -ApplicationID $ApplicationID -SID $SID -Type $Type -Permissions $Permissions -AceType $AceType -PassThru:$PassThru } } catch [System.Security.SecurityException] { Write-Verbose "Access denied setting DCOM permissions (registry configuration permissions are lacking...)" if (-not $OverrideConfigurationPermissions) { Write-Verbose "...Override not specified, aborting" ; throw $_ } else { Write-Verbose "...Attempting to override" } if (-not [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")) { Write-Warning "No administrator rights (not elevated)" ; throw $_ } $OldOwner = $null $RevokePrivilege = $false # User has admin rights, but Admininstrators do not have rights to change values. Need to change permissions Write-Verbose "Opening registry key to change its permissions" try { $key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey("AppID\$ApplicationID", 'ReadWriteSubTree', 'ChangePermissions') } catch [System.Security.SecurityException] { Write-Verbose "Access denied opening registry key to change permissions (not owner)`n`tReopening registry key to take ownership" try { $key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey("AppID\$ApplicationID", 'ReadWriteSubTree', 'TakeOwnership') } catch [System.Security.SecurityException] { Write-Verbose "Access denied opening registry key to take ownership, enabling Token Privileges and trying again" Grant-TokenPrivilege -Privilege SeTakeOwnershipPrivilege,SeRestorePrivilege $RevokePrivilege = $true $key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey("AppID\$ApplicationID", 'ReadWriteSubTree', 'TakeOwnership') } Write-Verbose "Setting owner to Administrators" try { $acl = $key.GetAccessControl() $OldOwner = [System.Security.Principal.NTAccount]$acl.Owner $acl.SetOwner($Admins_SID) $key.SetAccessControl($acl) } catch { if ($RevokePrivilege) { try { Revoke-TokenPrivilege -Privilege SeTakeOwnershipPrivilege,SeRestorePrivilege } catch {} } throw $_ } finally { $key.Close() } Write-Verbose "Retry: opening registry key to change its permissions" try { $key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey("AppID\$ApplicationID", 'ReadWriteSubTree', 'ChangePermissions') } catch { Write-Verbose "Failed again (you should never see this). Restoring original owner" $key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey("AppID\$ApplicationID", 'ReadWriteSubTree', 'TakeOwnership') $acl = $key.GetAccessControl() $acl.SetOwner($OldOwner) $key.SetAccessControl($acl) $key.Close() if ($RevokePrivilege) { try { Revoke-TokenPrivilege -Privilege SeTakeOwnershipPrivilege,SeRestorePrivilege } catch {} } throw $_ } } Write-Verbose "Setting ACL to grant Administrators full control" $acl = $key.GetAccessControl() $acl_original = $key.GetAccessControl() $acl_original.SetAccessRuleProtection($acl_original.AreAccessRulesProtected, $true) # Must "change" ACL, or .NET won't save it $rule = New-Object System.Security.AccessControl.RegistryAccessRule($Admins_SID, "FullControl", "ContainerInherit", "None", "Allow") $acl.ResetAccessRule($rule) # Replace all ACEs for Administrators with one that grants full control $key.SetAccessControl($acl) try { if ($Purpose -eq "Grant") { Grant-DComPermissionInternal -ApplicationID $ApplicationID -SID $SID -Type $Type -Permissions $Permissions -AceType $AceType -PassThru:$PassThru } else { Revoke-DComPermissionInternal -ApplicationID $ApplicationID -SID $SID -Type $Type -Permissions $Permissions -AceType $AceType -PassThru:$PassThru } } catch { throw $_ } finally { # Set ACL back to original value Write-Verbose "Restoring original registry key permissions & owner" if ($OldOwner) { $acl_original.SetOwner($OldOwner) } $key.SetAccessControl($acl_original) $key.Close() if ($RevokePrivilege) { try { Revoke-TokenPrivilege -Privilege SeTakeOwnershipPrivilege,SeRestorePrivilege } catch {} } } } } function Grant-DComPermission { <# .SYNOPSIS Grants DCOM Permissions to a specified Application ID's Launch/Activation, or Access permissions .DESCRIPTION Grants individual "Access Permissions" or "Launch and Activation Permissions" to a specified Application ID for a specific account .PARAMETER ApplicationID The Application ID for the DCOM object .PARAMETER Type Indicates which type of permissions to grant Valid options: Launch, Access .PARAMETER Account Account in the form of "Domain\Username". Specify only the username for local accounts. .PARAMETER Permissions List of permissions to grant Valid options for Launch: ALL, LocalLaunch, LocalActivation, RemoteLaunch, RemoteActivation Valid options for Access: ALL, LocalAccess, RemoteAccess .PARAMETER Deny Create a DENY access control entry instead of an ALLOW entry .PARAMETER PassThru Outputs the ApplicationID and Type parameters. This is useful for piping to Get-DCOMPermission. If not specified, nothing is outputted. .PARAMETER OverrideConfigurationPermissions For some DCOM objects (such as RuntimeBroker), Administrators do not have the needed "Configuration Permissions" to change the Launch or Access permissions. In these cases, an access denied error is generated. To avoid this error, specify this option. If this option is enabled and an access denied error occurs, then the "Configuration Permissions" will be temporarily changed (taking ownership as needed) to allow the DCOM permission change to succeed. Once complete, the configuration permissions and ownership are restored to the original values. .EXAMPLE Grant-DCOMPermission -ApplicationID "{9CA88EE3-ACB7-47C8-AFC4-AB702511C276}" -Account "SYSTEM" -Type Launch -Permissions LocalLaunch,LocalActivation .INPUTS String ApplicationID String Type String Account String[] Permissions Switch Deny Switch PassThru Switch OverrideConfigurationPermissions .OUTPUTS String ApplicationID String Type #> param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [Alias("APPID")] [string] $ApplicationID, [Parameter(Mandatory=$true)] [ValidateSet("Launch","Access")] [string] $Type, [Parameter(Mandatory=$true)] [Alias('Acct','User','Username')] [string] $Account, [Parameter(Mandatory=$true)] [ValidateSet("LocalLaunch","RemoteLaunch","LocalActivation", "RemoteActivation","LocalAccess","RemoteAccess","ALL")] [string[]] $Permissions, [Switch] $Deny, [Switch] $PassThru, [Alias("Override")] [Switch] $OverrideConfigurationPermissions ) $ErrorActionPreference = "Stop" Wrapper-DComPermission -Purpose Grant -ApplicationID $ApplicationID -Account $Account -Type $Type -Permissions $Permissions -Deny:$Deny -PassThru:$PassThru -OverrideConfigurationPermissions:$OverrideConfigurationPermissions } function Revoke-DComPermission { <# .SYNOPSIS Revokes DCOM Permissions from a specified Application ID's Launch/Activation, or Access permissions .DESCRIPTION Removes individual "Access Permissions" or "Launch and Activation Permissions" form a specified Application ID for a specific account .PARAMETER ApplicationID The Application ID for the DCOM object .PARAMETER Type Indicates which type of permissions to revoke Valid options: Launch, Access .PARAMETER Account Account in the form of "Domain\Username". Specify only the username for local accounts. .PARAMETER Permissions List of permissions to revoke Valid options for Launch: ALL, LocalLaunch, LocalActivation, RemoteLaunch, RemoteActivation Valid options for Access: ALL, LocalAccess, RemoteAccess .PARAMETER Deny Revoke a DENY access control entry instead of an ALLOW entry .PARAMETER PassThru Outputs the ApplicationID and Type parameters. This is useful for piping to Get-DCOMPermission. If not specified, nothing is outputted. .PARAMETER OverrideConfigurationPermissions For some DCOM objects (such as RuntimeBroker), Administrators do not have the needed "Configuration Permissions" to change the Launch or Access permissions. In these cases, an access denied error is generated. To avoid this error, specify this option. If this option is enabled and an access denied error occurs, then the "Configuration Permissions" will be temporarily changed (taking ownership as needed) to allow the DCOM permission change to succeed. Once complete, the configuration permissions and ownership are restored to the original values. .EXAMPLE Revoke-DCOMPermission -ApplicationID "{9CA88EE3-ACB7-47C8-AFC4-AB702511C276}" -Account "SYSTEM" -Type Launch -Permissions LocalLaunch,LocalActivation .INPUTS String ApplicationID String Type String Account String[] Permissions Switch Deny Switch PassThru Switch OverrideConfigurationPermissions .OUTPUTS String ApplicationID String Type #> param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [Alias("APPID")] [string] $ApplicationID, [Parameter(Mandatory=$true)] [ValidateSet("Launch","Access")] [string] $Type, [Parameter(Mandatory=$true)] [Alias('Acct','User','Username')] [string] $Account, [Parameter(Mandatory=$true)] [ValidateSet("LocalLaunch","RemoteLaunch","LocalActivation", "RemoteActivation","LocalAccess","RemoteAccess","ALL")] [string[]] $Permissions, [Switch] $Deny, [Switch] $PassThru, [Alias("Override")] [Switch] $OverrideConfigurationPermissions ) $ErrorActionPreference = "Stop" Wrapper-DComPermission -Purpose Revoke -ApplicationID $ApplicationID -Account $Account -Type $Type -Permissions $Permissions -Deny:$Deny -PassThru:$PassThru -OverrideConfigurationPermissions:$OverrideConfigurationPermissions } Export-ModuleMember -Function Get-DComPermission, Grant-DComPermission, Revoke-DComPermission # SIG # Begin signature block # MIIcxAYJKoZIhvcNAQcCoIIctTCCHLECAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUF+g3EqM6uew2jE1X/qJvXbWA # myagghfzMIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1b5VQCDANBgkqhkiG9w0B # AQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgxMDIyMTIwMDAwWjByMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQg # Q29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA # +NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLXcep2nQUut4/6kkPApfmJ # 1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sjlOSRI5aQd4L5oYQjZhJUM1B0 # sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjfDPXiTWAYvqrEsq5wMWYzcT6s # cKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5Ng2Q7+S1TqSp6moKq4Tz # rGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8vYWxYoNzQYIH5DiLanMg # 0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckwEgYDVR0TAQH/BAgwBgEB/wIB # ADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMweQYIKwYBBQUH # AQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYI # KwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFz # c3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0 # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaG # NGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD # QS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0 # dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYE # FFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6en # IZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPzItEVyCx8JSl2qB1dHC06 # GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUPUbRupY5a4l4kgU4QpO4/cY5j # DhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1UcKNJK4kxscnKqEpKBo6cSgC # PC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjFEmifz0DLQESlE/DmZAwlCEIy # sjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM1ekN3fYBIM6ZMWM9CBoYs4Gb # T8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKyZqHnGKSaZFHvMIIFfDCC # BGSgAwIBAgIQAarMGW1/STo93o1TEWGeDjANBgkqhkiG9w0BAQsFADByMQswCQYD # VQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGln # aWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgQ29k # ZSBTaWduaW5nIENBMB4XDTE2MDgyMzAwMDAwMFoXDTE5MTEyMTEyMDAwMFowgbgx # CzAJBgNVBAYTAlVTMQ0wCwYDVQQIEwRPaGlvMRQwEgYDVQQHEwtCZWF2ZXJjcmVl # azEcMBoGA1UEChMTRWRpY3QgU3lzdGVtcywgSW5jLjEcMBoGA1UECxMTRWRpY3Qg # U3lzdGVtcywgSW5jLjEcMBoGA1UEAxMTRWRpY3QgU3lzdGVtcywgSW5jLjEqMCgG # CSqGSIb3DQEJARYbc2VydmVydGVhbUBlZGljdHN5c3RlbXMuY29tMIIBIjANBgkq # hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArIiBNxH+fwhHOImuhnPB8KkW7W2YOjs0 # jUPmBMCOz3tEGw+f3pxFY3excm6i2dpitj86tmtGkdg3eQFW83q0uRgSA8VYPyE5 # OiKoTwfJpt4RYbpcDXf7o7t/gwMEWh08A7I9bVyU4qtsUv5PF6SrdD4u7d16MxYm # 4M4qjLv+u9sI7/urfzxQhbzGhGEuqMJGkNyYGX3QYMXq+nZThAA1u2NNkJNzzSh5 # fcsiPv8utB4r4pIgtL64eUIuYkx+j2n3BI/6yNxKCLb6Uu8/aSjS7I8MVFwJAFAr # ueEflGCPi2Ab6CVwOrllEmxYVVqzPtXd+w376wxtc6cwZGcOqoWOzwIDAQABo4IB # xTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYE # FArHIjPvp9Tepl+BpM6rruu3OF9rMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK # BggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Axhi9odHRwOi8vY3JsMy5kaWdpY2Vy # dC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNybDA1oDOgMYYvaHR0cDovL2NybDQu # ZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwTAYDVR0gBEUwQzA3 # BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQu # Y29tL0NQUzAIBgZngQwBBAEwgYQGCCsGAQUFBwEBBHgwdjAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4GCCsGAQUFBzAChkJodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNzdXJlZElEQ29kZVNpZ25p # bmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAdHHzVcLG # dSA7XSBpDwHelcVX/UxMufr1KZ7QIRAANGJNm78wxr/qiaOTTMu0Yb4eumOIdcwn # K3L3kxlebUPh4vTiYcdaO5GbuGESS18xZ6qn0qFOCG25Grm2IJKU+cc2bl31XWdp # nCaDtCKa5XkRxFlk2VXuA52cdqmGK+Gc6H+J/1EBlNhBbdguvcZJ/U1+JBTeuCgM # MXbk5bRUEUrXjXwOt+XUXiqP2ENUAlv/4/uATxxE5VJAVeHulXtr7UsUcINIBD9w # z8BpzvLbBVNNCn7/WGvcvtif7ShIYQgZ28dvaMto3kNNhPvT9aMDkGowTdzjl5xn # ddzZhcJ0RxRr7jCCBmowggVSoAMCAQICEAMBmgI6/1ixa9bV6uYX8GYwDQYJKoZI # hvcNAQEFBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ # MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgQXNz # dXJlZCBJRCBDQS0xMB4XDTE0MTAyMjAwMDAwMFoXDTI0MTAyMjAwMDAwMFowRzEL # MAkGA1UEBhMCVVMxETAPBgNVBAoTCERpZ2lDZXJ0MSUwIwYDVQQDExxEaWdpQ2Vy # dCBUaW1lc3RhbXAgUmVzcG9uZGVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB # CgKCAQEAo2Rd/Hyz4II14OD2xirmSXU7zG7gU6mfH2RZ5nxrf2uMnVX4kuOe1Vpj # WwJJUNmDzm9m7t3LhelfpfnUh3SIRDsZyeX1kZ/GFDmsJOqoSyyRicxeKPRktlC3 # 9RKzc5YKZ6O+YZ+u8/0SeHUOplsU/UUjjoZEVX0YhgWMVYd5SEb3yg6Np95OX+Ko # ti1ZAmGIYXIYaLm4fO7m5zQvMXeBMB+7NgGN7yfj95rwTDFkjePr+hmHqH7P7IwM # Nlt6wXq4eMfJBi5GEMiN6ARg27xzdPpO2P6qQPGyznBGg+naQKFZOtkVCVeZVjCT # 88lhzNAIzGvsYkKRrALA76TwiRGPdwIDAQABo4IDNTCCAzEwDgYDVR0PAQH/BAQD # AgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwggG/BgNV # HSAEggG2MIIBsjCCAaEGCWCGSAGG/WwHATCCAZIwKAYIKwYBBQUHAgEWHGh0dHBz # Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwggFkBggrBgEFBQcCAjCCAVYeggFSAEEA # bgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABpAGYAaQBjAGEA # dABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBwAHQAYQBuAGMA # ZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQAC8AQwBQAFMA # IABhAG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQByAHQAeQAgAEEA # ZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0ACAAbABpAGEA # YgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwByAHAAbwByAGEA # dABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBlAG4AYwBlAC4w # CwYJYIZIAYb9bAMVMB8GA1UdIwQYMBaAFBUAEisTmLKZB+0e36K+Vw0rZwLNMB0G # A1UdDgQWBBRhWk0ktkkynUoqeRqDS/QeicHKfTB9BgNVHR8EdjB0MDigNqA0hjJo # dHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURDQS0xLmNy # bDA4oDagNIYyaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl # ZElEQ0EtMS5jcmwwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8v # b2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENBLTEuY3J0MA0GCSqGSIb3DQEB # BQUAA4IBAQCdJX4bM02yJoFcm4bOIyAPgIfliP//sdRqLDHtOhcZcRfNqRu8WhY5 # AJ3jbITkWkD73gYBjDf6m7GdJH7+IKRXrVu3mrBgJuppVyFdNC8fcbCDlBkFazWQ # EKB7l8f2P+fiEUGmvWLZ8Cc9OB0obzpSCfDscGLTYkuw4HOmksDTjjHYL+NtFxMG # 7uQDthSr849Dp3GdId0UyhVdkkHa+Q+B0Zl0DSbEDn8btfWg8cZ3BigV6diT5VUW # 8LsKqxzbXEgnZsijiwoc5ZXarsQuWaBh3drzbaJh6YoLbewSGL33VVRAA5Ira8JR # wgpIr7DUbuD0FAo6G+OPPcqvao173NhEMIIGzTCCBbWgAwIBAgIQBv35A5YDreoA # Cus/J7u6GzANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM # RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQD # ExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcN # MjExMTEwMDAwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg # SW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2Vy # dCBBc3N1cmVkIElEIENBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDogi2Z+crCQpWlgHNAcNKeVlRcqcTSQQaPyTP8TUWRXIGf7Syc+BZZ3561JBXC # mLm0d0ncicQK2q/LXmvtrbBxMevPOkAMRk2T7It6NggDqww0/hhJgv7HxzFIgHwe # og+SDlDJxofrNj/YMMP/pvf7os1vcyP+rFYFkPAyIRaJxnCI+QWXfaPHQ90C6Ds9 # 7bFBo+0/vtuVSMTuHrPyvAwrmdDGXRJCgeGDboJzPyZLFJCuWWYKxI2+0s4Grq2E # b0iEm09AufFM8q+Y+/bOQF1c9qjxL6/siSLyaxhlscFzrdfx2M8eCnRcQrhofrfV # dwonVnwPYqQ/MhRglf0HBKIJAgMBAAGjggN6MIIDdjAOBgNVHQ8BAf8EBAMCAYYw # OwYDVR0lBDQwMgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAwYIKwYBBQUH # AwQGCCsGAQUFBwMIMIIB0gYDVR0gBIIByTCCAcUwggG0BgpghkgBhv1sAAEEMIIB # pDA6BggrBgEFBQcCARYuaHR0cDovL3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1y # ZXBvc2l0b3J5Lmh0bTCCAWQGCCsGAQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMA # ZQAgAG8AZgAgAHQAaABpAHMAIABDAGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8A # bgBzAHQAaQB0AHUAdABlAHMAIABhAGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAA # dABoAGUAIABEAGkAZwBpAEMAZQByAHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAA # dABoAGUAIABSAGUAbAB5AGkAbgBnACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0A # ZQBuAHQAIAB3AGgAaQBjAGgAIABsAGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQA # eQAgAGEAbgBkACAAYQByAGUAIABpAG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgA # ZQByAGUAaQBuACAAYgB5ACAAcgBlAGYAZQByAGUAbgBjAGUALjALBglghkgBhv1s # AxUwEgYDVR0TAQH/BAgwBgEB/wIBADB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUH # MAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDov # L2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNy # dDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp # Z2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2NybDQuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDAdBgNVHQ4EFgQU # FQASKxOYspkH7R7for5XDStnAs0wHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6ch # nfNtyA8wDQYJKoZIhvcNAQEFBQADggEBAEZQPsm3KCSnOB22WymvUs9S6TFHq1Zc # e9UNC0Gz7+x1H3Q48rJcYaKclcNQ5IK5I9G6OoZyrTh4rHVdFxc0ckeFlFbR67s2 # hHfMJKXzBBlVqefj56tizfuLLZDCwNK1lL1eT7EF0g49GqkUW6aGMWKoqDPkmzmn # xPXOHXh2lCVz5Cqrz5x2S+1fwksW5EtwTACJHvzFebxMElf+X+EevAJdqP77BzhP # DcZdkbkPZ0XN1oPt55INjbFpjE/7WeAjD9KqrgB87pxCDs+R1ye3Fu4Pw718CqDu # LAhVhSK46xgaTfwqIa1JMYNHlXdx3LEbS0scEJx3FMGdTy9alQgpECYxggQ7MIIE # NwIBATCBhjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkw # FwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEy # IEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBAhABqswZbX9JOj3ejVMRYZ4OMAkG # BSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJ # AzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMG # CSqGSIb3DQEJBDEWBBRE2xWBbV6I0N5LOSBGIHphA8Qk2DANBgkqhkiG9w0BAQEF # AASCAQBx0NZepXFfXRZ5A2nf4rFBHDKPgK1obc0ZWZmxwquTCVMDcSyoFf0K5W9e # 7oEGmvtqSAWIUa1bSfAMvWOInSqVZbU6Vxg0Ks72kC9HrwuaD2AFWbmDSb4076NB # xuFG2JhCjzLli2CbN5k5Ac52rE2y4zoULqY2Llbzla2PXftd/d0LymUErcRYFwXU # AEoJIwizFj2esWoMYUU2yqRiLfrKtyiEEhKAqVwOL9FZio7vqcLm6ChMiR20xPvk # UUngKK5q0AFq9zpoDZSpQmmA8zUw7BdmZ8xx+S2Jrh1LiTO7sjH8klXyq1KjswQ6 # HeHt4QiJ7vILNzce+/Z8uCKhBBGSoYICDzCCAgsGCSqGSIb3DQEJBjGCAfwwggH4 # AgEBMHYwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcG # A1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgQXNzdXJl # ZCBJRCBDQS0xAhADAZoCOv9YsWvW1ermF/BmMAkGBSsOAwIaBQCgXTAYBgkqhkiG # 9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNzA5MjIyMjQzNDRa # MCMGCSqGSIb3DQEJBDEWBBTb3xeC3ZURhL6gg8EPIiQa72+yATANBgkqhkiG9w0B # AQEFAASCAQAbbHn3aJUt029rf16/hkcnU0Up6tFKNMN4CiwJnNLQ3CT8ZQo5LeRw # Q7f8nq4FXPTjjFBsEVmeBt88WCfaUQGkSksgpInr2wp8K1EYZZHde3TK2pZMOULv # EqU8ns/wgy9FUJOKyiwngo03L/Ne8gvYvjRkTxBAHRhprCbN5/1pZ3/pIZtbH9xK # 8AQcATnVwJ2c0V19IyZVyiINMeS0sxeBRA60fk/6zOtH9VSXv60Rslcf8q6VheE1 # aTzpfiZl7i73CtPlDOLPvTtESNP1PVAEKsT2OOP66YEOl2s1VWKUD2pxYrUem6R1 # qnauaTUnptzRyZbryRipWPN3iLzNUcXL # SIG # End signature block |