Indented.ComSecurity.psm1
using namespace System.Security.AccessControl using namespace System.Security.Principal #Region '.\enum\ComRight.ps1' 0 [Flags()] enum ComRight { Read = 1 LocalLaunch = 2 RemoteLaunch = 4 LocalActivation = 8 RemoteActivation = 16 All = 31 } #EndRegion '.\enum\ComRight.ps1' 10 #Region '.\enum\ComType.ps1' 0 enum ComType { DefaultLaunchPermission = 1 MachineAccessRestriction MachineLaunchRestriction } #EndRegion '.\enum\ComType.ps1' 6 #Region '.\private\GetOlePath.ps1' 0 function GetOlePath { <# .SYNOPSIS Get the path to OLE. .DESCRIPTION Get the path to OLE depending on the current process and the requested registry view. #> [CmdletBinding()] param ( # Set to true if the 32-bit registry view should be used to get the ACL. [Switch]$Is32Bit ) if (($Is32Bit -and [IntPtr]::Size -eq 8) -or (-not $Is32Bit -and [IntPtr]::Size -eq 4)) { return 'HKLM:\Software\Wow6432Node\Microsoft\Ole' } return 'HKLM:\Software\Microsoft\Ole' } #EndRegion '.\private\GetOlePath.ps1' 20 #Region '.\public\Get-ComAcl.ps1' 0 #using namespace System.Security.AccessControl #using namespace System.Security.Principal function Get-ComAcl { <# .SYNOPSIS Get security descriptors associated with COM. .DESCRIPTION Get-ComAcl can be used to read the access control lists which make up COM Security. .EXAMPLE Get-ComAcl -Type MachineLaunchRestriction Get the ACL used to describe launch restrictions. #> [CmdletBinding()] [OutputType([System.Security.AccessControl.CommonSecurityDescriptor])] param ( # The permission set which should be retrieved. [Parameter(Mandatory, Position = 1)] [ComType]$Type, # Set to true if the 32-bit registry view should be used to get the ACL. [Switch]$Is32Bit ) $path = GetOlePath -Is32Bit:$Is32Bit $aclObject = [CommonSecurityDescriptor]::new( $false, $false, (Get-ItemPropertyValue -Path $path -Name $Type), 0 ) $aclObject | Add-Member -NotePropertyName Type -NotePropertyValue $Type $aclObject | Add-Member -NotePropertyName Is32Bit -NotePropertyValue $Is32Bit.ToBool() $aclObject | Add-Member Access -MemberType ScriptProperty -Value { foreach ($ace in $this.DiscretionaryAcl) { [PSCustomObject]@{ ComAccessRights = [ComRight]$ace.AccessMask AccessControlType = [AccessControlType]$ace.AceType IdentityReference = $ace.SecurityIdentifier.Translate([NTAccount]) } | Add-Member ToString -MemberType ScriptMethod -Force -PassThru -Value { '{0} {1} {2}' -f @( $this.IdentityReference.ToString().PadRight(32), $this.AccessControlType.ToString().PadRight(10), $this.ComAccessRights ) } } } $aclObject | Add-Member AccessToString -MemberType ScriptProperty -Value { ($this.Access | ForEach-Object { $_.ToString() }) -join [Environment]::NewLine } $aclObject } #EndRegion '.\public\Get-ComAcl.ps1' 61 #Region '.\public\Grant-ComPermission.ps1' 0 #using namespace System.Security.Principal function Grant-ComPermission { <# .SYNOPSIS Grant a COM right. .DESCRIPTION Grant a right to an identity in a COM ACL. .EXAMPLE Grant-ComPermission -Type MachineLaunchRestriction -Right RemoteLaunch -Identity (whoami) Grant the RemoteLaunch right to the current user. .EXAMPLE Grant-ComPermission -Type MachineLaunchRestriction -Right RemoteLaunch, RemoteActivation -Identity EVERYONE Grant the RemoteLaunch and RemoteActivation rights to everyone. #> [CmdletBinding(SupportsShouldProcess)] param ( # The ACL to modify. Must be one of DefaultLaunchPermission, MachineAccessRestriction, or MachineLaunchRestriction. [Parameter(Mandatory, Position = 1)] [ComType]$Type, # The access type which should be granted. The value can be Allow or Deny, by default AccessType is set to Allow. [Parameter(ValueFromPipelineByPropertyName)] [AccessControlType]$AccessType = 'Allow', # The identity which should have rights granted. [Parameter(ValueFromPipelineByPropertyName)] [IdentityTransformationAttribute()] [SecurityIdentifier]$Identity, # The right to grant. One or more of Read, LocalLaunch, RemoteLaunch, LocalActivation, RemoteActivation, or All. [Parameter(ValueFromPipelineByPropertyName)] [ComRight]$Right, # Set to true if the 32-bit registry view should be used to set the ACL. [Switch]$Is32Bit ) begin { $aclObject = Get-ComAcl -Type $Type -Is32Bit:$Is32Bit } process { try { $aclObject.DiscretionaryAcl.AddAccess( $AccessType, $Identity, [Int]$Right, 'None', 'None' ) } catch { Write-Error -ErrorRecord $_ } } end { if ($pscmdlet.ShouldProcess('Applying changes to discretionary ACL for {0}' -f $Type)) { $aclObject | Set-ComAcl } } } #EndRegion '.\public\Grant-ComPermission.ps1' 66 #Region '.\public\Revoke-ComPermission.ps1' 0 #using namespace System.Security.Principal function Revoke-ComPermission { <# .SYNOPSIS Revoke a COM right. .DESCRIPTION Revoke a right granted to an identity in a COM ACL. Entries may be added to the ACL if the revoked rights describe less than the rights assigned to a principal. .EXAMPLE Revoke-ComPermission -Type MachineLaunchRestriction -Right All -Identity $env:USERNAME Revoke all rights which have been explicitly granted to the current user. #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'FromFields')] param ( # The ACL to modify. Must be one of DefaultLaunchPermission, MachineAccessRestriction, or MachineLaunchRestriction. [Parameter(Mandatory)] [ComType]$Type, # The access type which should be removed. Allow or Deny. [Parameter(ValueFromPipelineByPropertyName, ParameterSetname = 'FromFields')] [AccessControlType]$AccessType = 'Allow', # The identity for which rights should be revoked. [Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetname = 'FromFields')] [IdentityTransformationAttribute()] [SecurityIdentifier]$Identity, # The rights to revoke. One or more of Read, LocalLaunch, RemoteLaunch, LocalActivation, RemoteActivation, or All. [Parameter(ValueFromPipelineByPropertyName, ParameterSetname = 'FromFields')] [ComRight]$Right, # A CommonAce object from the DiscretionaryACL. [Parameter(ValueFromPipeline, ParameterSetName = 'FromACE')] [CommonAce]$Ace, # Set to true if the 32-bit registry view should be used to set the ACL. [Switch]$Is32Bit ) begin { $aclObject = Get-ComAcl -Type $Type -Is32Bit:$Is32Bit } process { try { if ($pscmdlet.ParameterSetName -eq 'FromFields') { $aceRemoved = $aclObject.DiscretionaryAcl.RemoveAccess( $AccessType, $Identity, [Int]$Right, 'None', 'None' ) try { $name = $Identity.Translate([NTAccount]) } catch { $name = $Identity } } else { try { $name = $ace.IdentityReference.Translate([NTAccount]) } catch { $name = $ace.IdentityReference } $aceRemoved = $aclObject.DiscretionaryAcl.RemoveAccess($ace) } if (-not $aceRemoved) { throw 'Failed to remove {0} from {1} ACL' -f $name, $Type } } catch { Write-Error -ErrorRecord $_ } } end { if ($pscmdlet.ShouldProcess('Applying changes to discretionary ACL for {0}' -f $Type)) { $aclObject | Set-ComAcl } } } #EndRegion '.\public\Revoke-ComPermission.ps1' 86 #Region '.\public\Set-ComAcl.ps1' 0 #using namespace System.Security.AccessControl function Set-ComAcl { <# .SYNOPSIS Set a COM Security ACL. .DESCRIPTION Apply an updated ACL to COM Security. .EXAMPLE Set-ComAcl -Type MachineLaunchRestriction -AclObject $aclObject Set a modified ACL for MachineLaunchRestriction. #> [CmdletBinding(SupportsShouldProcess)] param ( # The permission set which should be changed. [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [ComType]$Type, # The ACL object to apply. [Parameter(Mandatory, ValueFromPipeline)] [CommonSecurityDescriptor]$AclObject, # Set to true if the 32-bit registry view should be used to set the ACL. [Parameter(Mandatory, ValueFromPipelineByPropertyName)] [Switch]$Is32Bit ) begin { $path = GetOlePath -Is32Bit:$Is32Bit } process { try { $bytes = [Byte[]]::new($AclObject.BinaryLength) $AclObject.GetBinaryForm($bytes, 0) $existingBytes = Get-ItemPropertyValue -Path $path -Name $Type if (Compare-Object $bytes $existingBytes -SyncWindow 0) { if ($pscmdlet.ShouldProcess('Setting the {0} ACL' -f $Type)) { Set-ItemProperty -Path $path -Name $Type -Value $bytes } } } catch { $pscmdlet.ThrowTerminatingError($_) } } } #EndRegion '.\public\Set-ComAcl.ps1' 50 |