<# Get the Active Directory permissions of any AD object from the distinguishedName This does not require admin permissions or modules Get-ObjPermissions.ps1 Alan Kaplan Public version 12/25/21 Convert-GuidToName is rewrite of Convert-ADACL by Nathan Linley - http://myitpath.blogspot.com/2012/04/decoding-ad-acls-powershell.html #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [String]$objDN ) #Create a hashtable for GUIDs so repeat values aren't looked up twice $Script:schemaIDGUID = @{} #add all and missing name $schemaIDGUID.add('00000000-0000-0000-0000-000000000000', 'All') $schemaIDGUID.Add('9b51a1ef-79b7-4ae5-9ac8-d14c47daca46', 'Deleted Exchange GUID') #hashtable for name lookups $Script:SIDtoName = @{} $objRootDSE = [System.DirectoryServices.DirectoryEntry] "LDAP://rootDSE" $SchemaNamingNC = $objRootDSE.schemaNamingContext $ConfigurationNC = $objRootDSE.configurationNamingContext function Convert-GUIDToName { param( [parameter(mandatory = $true)][string]$guid, [switch]$extended ) Write-Progress "Getting name of property with GUID $guid" if ($schemaIDGUID.ContainsKey($GUID) ) { $schemaIDGUID[$Guid] Return } $GuidName = $info = $bytestr = "" #for extended rights, we can check in the configuration container $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.SearchRoot = "LDAP://CN=Extended-Rights,$ConfigurationNC" $Searcher.filter = "(rightsguid=$guid)" $result = $Searcher.findone() if ($result.count -eq 0) { #Search schema for possible matches for this GUID $guidval = [Guid]$guid $bytearr = $guidval.tobytearray() foreach ($byte in $bytearr) { $str = "\" + "{0:x}" -f $byte $bytestr += $str } $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.SearchRoot = "LDAP://$SchemaNamingNC" $Searcher.filter = "(schemaidguid=$bytestr)" $result = $Searcher.FindOne() } if ($null -eq $result) { Clear-Host Write-Warning "Unable to get name for GUID: $guid" $GuidName = $guid } else { if ($extended) { $GuidName = $result.properties.cn } else { $GuidName = $result.properties.cn } #$result.Properties if ($result.properties.Keys -contains 'LDAPDisplayName') { $info = (($result.Properties['LDAPDisplayName']).trim() ) } if ($result.Properties.keys -contains 'DisplayName') { $info = (($result.Properties['DisplayName']).trim() ) } if ($info) { $GuidName = "$GuidName `($info`)" } } if (!$schemaIDGUID.ContainsKey($GUID) ) { $schemaIDGUID.add($GUID, $GUIDname) } $GuidName } Function Test-IsSID($strID) { #Perfect match, does not match O:SID, etc $strRegex = '^S-\d-(\d+-){1,14}\d+$' [RegEx]::IsMatch($strID, $strRegex) } Function Convert-SIDtoNTName($sidVal) { Write-Progress "Getting name for user with SID $sidval" if ($SIDtoName.ContainsKey($SidVal) ) { $SIDtoName[$SidVal] Return } $objSID = New-Object System.Security.Principal.SecurityIdentifier ($sidVAl) Try { $Identity = $objSID.Translate([System.Security.Principal.NTAccount]) $Lookup = $Identity.Value } catch { $LDAPpath = "LDAP://" if ([adsi]::Exists($LDAPpath)) { $IDRef = ([adsi]$LDAPpath) $SamName = [string]$IDRef.SamAccountName $DN = [string]$IDRef.distinguishedName #8/24/21 - if critical object, show in user's domain if ($idref.isCriticalSystemObject.value) { $Dom = $objDN.Substring($objDN.IndexOf(",DC")).Replace(",DC=", ".").Substring(1) } Else { $Dom = $DN.Substring($DN.IndexOf(",DC")).Replace(",DC=", ".").Substring(1) } $Lookup = "$Dom\$SamName" } Else { Clear-Host Write-warning "AD search for name of group or user with SID $sidVAl failed." $Lookup = $sidVal } } $Lookup if (!$SIDtoName.ContainsKey($SidVal) ) { $SIDtoName.add($SidVal, $Lookup) } } ## Script starts here $o = [adsi]"LDAP://$objDN" $NTS = $o.Psbase.ObjectSecurity.access $PermList = $NTS | foreach-object { $guid = $_.objectType.guid $ID = [string]$_.identityReference $identity = if (Test-IsSID $id) { Convert-SIDtoNTName $ID } Else { $ID } $objectTypeName = if ($_.ActiveDirectoryRights -eq "ExtendedRight") { Convert-GUIDToName $guid -extended } Else { Convert-GUIDToName $guid } if ($_.isInherited){ $inheritedType = Convert-GUIDToName $_.InheritedObjectType }Else{ $inheritedType = '' } [PSCustomObject]@{ "Group or User" = $identity "Object Type" = $objectTypeName "AD Rights" = $_.ActiveDirectoryRights "Inherited" = $_.isInherited "Inherited Type" = $inheritedType "Access Control Type" = $_.AccessControlType GUID = $guid } } Write-Progress -Completed 'Done' Clear-Host $objName = $o.Name $PermList | Sort-object "Group or User", "Object Type" | Select-object * -unique | out-gridview -Title "NT Security for $objName`. Selected values are copied to your clipboard" -PassThru