I use PSVersion 5.1.19041.1320.
I'm getting a security descriptor of Windows Service and truing to replace access rights in it (in this example with 'TEST') for a specific user (in the example for 'AU').
My general logic is:
- Take a service's Security Descriptor
- Extract a part between 'D:' and 'S:' (with regex '(?<=D:)(.*)(?=S:)')
- Extract access rights for Authenticated Users (AU) (with regex '(([^()]*))' the )
- Replace access rights
- Assemble 3. and 2. back to a new security descriptor
Example:
$user = 'AU'
[string]$newAccessRights = 'TEST'
$sddl = sc.exe sdshow wuauserv | Where-Object {$_}
$dacl = [RegEx]::Matches($sddl,'(?<=D:)(.*)(?=S:)') | ForEach-Object {$_.Value}
$dacl = $dacl -replace ([RegEx]::Matches($dacl,"(\([^()]*\))") | Where-Object {$_.Value.split(';')[-1] -eq "${user})"} | ForEach-Object {$_.Value.split(';')[2]}), $newAccessRights
$sddl -replace ([RegEx]::Matches($sddl,"(?<=D:)(.*)(?=S:\()") | ForEach-Object {$_.Value}), $dacl
my expectation is that Security Descriptor:
D:(A;;CCLCSWRPLORC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)S:(AU;FA;CCDCLCSWRPWPDTLOSDRCWDWO;;;WD)
will be replaced with:
D:(A;;TEST;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)S:(AU;FA;CCDCLCSWRPWPDTLOSDRCWDWO;;;WD)
but it is not: Example
What am I doing wrong? Why the only last replace doesn't work?
CodePudding user response:
You can use
$sddl = $sddl -replace "(\((?:[^();]*;){2})\w ((?:;[^()]*)?;$user\))", "`$1$newAccessRights`$2"
See the regex demo. Details:
(\((?:[^();]*;){2})
- Group 1 ($1
): a(
char, then two occurrences of any zero or more chars other than(
,)
and;
followed with a;
char\w
- one or more word chars (or,[^;]*
matching zero or more chars other than a;
char, it will work here, too)((?:;[^()]*)?;$user\))
- Group 2 ($2
): an optional sequence of a;
and then any zero or more chars other than(
and)
and then;
,$user
variable, and a)
char.
NOTE: If $user
has no special chars, no need to Regex.Escape
it. Else, escape it, [regex]::Escape($user)
. And if there is a $
char in the $newAccessRights
followed with a digit, you will need to escape it, too, $newAccessRights.Replace('$', '$$')
(this can be done before using it in the replacement pattern).