Skip to content

Instantly share code, notes, and snippets.

@jborean93
Last active February 14, 2024 01:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jborean93/98004a0c5a2fedd250a4d450424e8aaf to your computer and use it in GitHub Desktop.
Save jborean93/98004a0c5a2fedd250a4d450424e8aaf to your computer and use it in GitHub Desktop.
Get the Service SecurityDescriptor in a human friendly format
# 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