Last active
February 14, 2024 01:51
-
-
Save jborean93/98004a0c5a2fedd250a4d450424e8aaf to your computer and use it in GitHub Desktop.
Get the Service SecurityDescriptor in a human friendly format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright: (c) 2024, Jordan Borean (@jborean93) <jborean93@gmail.com> | |
# MIT License (see LICENSE or https://opensource.org/licenses/MIT) | |
Function Get-ServiceDacl { | |
<# | |
.SYNOPSIS | |
Gets the service DACL entries. | |
.DESCRIPTION | |
Gets all the DACL entries for the service(s) specified. | |
A DACL entry is an individual rule that specifies the rule type, identity | |
it is for and the rights associated with that rule. | |
.PARAMETER Name | |
The service(s) to get the rules for. | |
.EXAMPLE | |
Get-ServiceDacl -Name WinRM | |
'WinRM', 'TrustedInstaller' | Get-ServiceDacl | |
.NOTES | |
Each output object is a DACL entry. | |
It has the following properties: | |
Service = 'Name of the service the rule is for' | |
Account: The NTAccount or SID if untranslatable the rule is for | |
Access: The access enum value describing what the rule can do | |
AccessMask: The hex representation of the access mask | |
AceType: The type of ACE, either AccessAllowed or AccessDenied. | |
#> | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory, ValueFromPipeline)] | |
[String[]] | |
$Name | |
) | |
begin { | |
[Flags()] enum ServiceAccessMask { | |
UNKNOWN = 0x00000000 | |
SERVICE_ALL_ACCESS = 0x000F01FF | |
SERVICE_CHANGE_CONFIG = 0x00000002 | |
SERVICE_ENUMERATE_DEPENDENTS = 0x00000008 | |
SERVICE_INTERROGATE = 0x00000080 | |
SERVICE_PAUSE_CONTINUE = 0x00000040 | |
SERVICE_QUERY_CONFIG = 0x00000001 | |
SERVICE_QUERY_STATUS = 0x00000004 | |
SERVICE_START = 0x00000010 | |
SERVICE_STOP = 0x00000020 | |
SERVICE_USER_DEFINED_CONTROL = 0x00000100 | |
ACCESS_SYSTEM_SECURITY = 0x01000000 | |
DELETE = 0x00010000 | |
READ_CONTROL = 0x00020000 | |
WRITE_DAC = 0x00040000 | |
WRITE_OWNER = 0x00080000 | |
STANDARD_RIGHTS_REQUIRED = 0x000F0000 | |
STANDARD_RIGHTS_READ = 0x00020000 | |
STANDARD_RIGHTS_WRITE = 0x00020000 | |
STANDARD_RIGHTS_EXECUTE = 0x00020000 | |
GENERIC_READ = 0x0002008D | |
GENERIC_WRITE = 0x00020002 | |
GENERIC_EXECUTE = 0x00020170 | |
} | |
} | |
process { | |
foreach ($service in $Name) { | |
$sddl = ((sc.exe sdshow $service) -join "").Trim() | |
if ($LASTEXITCODE) { | |
$err = [System.Management.Automation.ErrorRecord]::new( | |
[Exception]::new("Failed to get SDDL for service '$service', rc: $LASTEXITCODE, error: $sddl"), | |
'FailedToRetreiveSddl', | |
'NotSpecified', | |
$service) | |
$PSCmdlet.WriteError($err) | |
continue | |
} | |
$sd = ConvertFrom-SddlString -Sddl $sddl | |
$sd.RawDescriptor.DiscretionaryAcl | ForEach-Object { | |
$sid = $_.SecurityIdentifier | |
try { | |
$account = $sid.Translate([Security.Principal.NTAccount]) | |
} | |
catch [Security.Principal.IdentityNotMappedException] { | |
$account = $sid | |
} | |
try { | |
$access = [ServiceAccessMask]$_.AccessMask | |
} | |
catch [Management.Automation.PSInvalidCastException] { | |
$access = [ServiceAccessMask]::UNKNOWN | |
} | |
[PSCustomObject]@{ | |
Service = $service | |
Account = $account | |
Access = $access | |
AccessMask = '0x{0:X8}' -f $_.AccessMask | |
AceType = $_.AceType | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment