Import-Clixml Error - The data is invalid (continued from older post)

https://powershell.org/forums/topic/import-clixml-error-the-data-is-invalid/

I’ve got the same issue on hand as the OP did in the linked thread. I was hoping to give Dave Wyatt’s Get-DPAPIMasterKey function a try so I could compare my master key guids. However, I’m hitting an issue with that and the error is:

parsing "(?< =\G.{2})" - Invalid group name: Group names must begin with a word character.
At line:16 char:5
+ $encryptedByteStrings = [string[]]($EncryptedSecureString -split ...

The relevant section of the function is:

 $encryptedByteStrings = [string[]]($EncryptedSecureString -split '(?< =\G.{2})' -match '\S')

The problem specifically being this:

-split '(?< =\G.{2})'

I tried to make sense of the answer from this external thread - c# - Invalid group name: Group names must begin with a word character - Stack Overflow - but I’m struggling to determine in Dave’s function, whether we are wanting to have a named group at all, or if that question mark is meant to be used as a single character wildcard.

Without knowing the pattern Dave was trying to capture with that -split code (statement?), I’m not finding much success making forward progress from here. Anyone able to spot anything and help me out? Much appreciated and thanks in advance.

You’re running into a formatting issue on this forum. That’s not meant to be a group name, it’s meant to be a regex look-back. The anti-XSS code on this site is extremely overzealous and inserts spaces to break anything that looks remotely like HTML tags, and it really messes with scripts sometimes. I’ll embed the pattern using a gist to show you what it should actually look like:

Basically a look-back (or lookahead) ensures it splits at the right place, but the pattern never captures any characters, so it makes sure that no characters are actually removed before the string is split. Normally if you split on a character, it’ll just remove the delimiter from the final strings when you’re done. Lookarounds are zero-width matches, so no characters are removed.

In typical me fashion, I’m back with my own first reply, and a workaround solution / FYI to share. I had this problem (with Import-Clixml) when I was running Windows Task Scheduler tasks with the option “Do not store password. This task will only have access to local computer resources.” selected. If I run the task this way, Import-Clixml fails with the error in the OP (and the original thread’s OP). In the local Security event log, and event is generated:

Event ID: 4693 - Recovery of Data Protection Master Key was attempted

I found two workarounds, the first just peculiar so being mentioned, but not really a feasible workaround:

  1. Have any other program running as the same user that is set on the scheduled task (whose password is not stored with the tasks), WHEN the task is run. This fools Windows into being able to contact AD to do whatever does directly before it access the Master Key from %AppData%\Microsoft\Protect\<SID>.
  2. Store the password with the scheduled task.
Note, I checked GPO's with GPResult /h and couldn't find anything related to rotating keys (for lack of better words to describe that). I couldn't find anything. It was when I looked in the Event Log Microsoft-Windows-Crypto-DPAPI/Operational that I could see the only time DPAPI was generating a new Master Key for any user was either when they first logged on, or their next logon to that system after a password change. Upon that occurring there is an event with ID 1 that shows "DPAPI created Master key." as well as the guid of the new Master Key for that user (on that system).

Dave Wyatt’s function was going to help me verify if my password in my xml file created with Export-Clixml was encrypted using the Master Key with the same guid as the one in my %AppData%\Microsoft\Protect&lt;SID>. In the end I drew the conclusion that my key hadn’t changed, based on no event showing so in the aforementioned event log. It was (finally) at that time that I realized this most likely is a problem with needing to reach outside of the local system (i.e. AD) while not actually able to do so due to no password being stored in the scheduled task. Bummer, but clarity/closure, so not a total loss.

[quote quote=153230]You’re running into a formatting issue on this forum. That’s not meant to be a group name, it’s meant to be a regex look-back. The anti-XSS code on this site is extremely overzealous and inserts spaces to break anything that looks remotely like HTML tags, and it really messes with scripts sometimes. I’ll embed the pattern using a gist to show you what it should actually look like:

<script src=“https://gist.github.com/vexx32/6742d4a27aa5b61126968e57ca3b9612.js”></script>

$encryptedByteStrings = [string[]]($EncryptedSecureString -split '(?<=\G.{2})' -match '\S')
view raw JeremyB.ps1 hosted with ❤ by GitHub
<script>jQuery(document).ready(function(){jQuery("td.line-numbers").remove();});</script>

Basically a look-back (or lookahead) ensures it splits at the right place, but the pattern never captures any characters, so it makes sure that no characters are actually removed before the string is split. Normally if you split on a character, it’ll just remove the delimiter from the final strings when you’re done. Lookarounds are zero-width matches, so no characters are removed.

[/quote]

Thanks very much! I just took that space after the less-than out and tested the function successfully. And to confirm - my Master Key’s current Guid was indeed the one that the Get-DPAPIMasterKey function returned when I tested my secure string from my xml file.

Much appreciated for the explanation of the look-back/lookahead/lookaround. I have some regex homework to do.