Home > Enterprise >  PowerShell replace doesn't work in the last line in my script
PowerShell replace doesn't work in the last line in my script

Time:03-08

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:

  1. Take a service's Security Descriptor
  2. Extract a part between 'D:' and 'S:' (with regex '(?<=D:)(.*)(?=S:)')
  3. Extract access rights for Authenticated Users (AU) (with regex '(([^()]*))' the )
  4. Replace access rights
  5. 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).

  • Related