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;,$uservariable, 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).
