PSA: Locating Bad/Corrupt Registry.POL Files

For several months – a good chunk of 2017 in fact – we’ve encountered machines where Group Policy failed as evidenced by the following on affected machines:

  • Seeing errors like the following when runing gpupdate /force:

    Computer policy could not be updated successfully.   The following errors were encountered:
    The processing of Group Policy failed.  Windows could not apply the registry-based settings for the Group Policy object LocalGPO.  Group Policy settings will not be resolved until this event is resolved.  View the event details for more information on the file name and path that caused the failure.
    To diagnose the failure, review the event log or run GPRESULT /H GPReport.html from the command line to access information about Group Policy results.

  • Event ID 1096 which itself would show ErrorCode 13 with an ErrorDescription of ‘The data is invalid.’ along with the problematic Registry.POL file.

This is a well known and well documented problem:

The cause: Unknown but we have some suspects.

The fix is easy: Delete or rename the problematic Registry.pol file, which so far is always in %SystemRoot%\System32\GroupPolicy\Machine

But that’s reactionary and we want to be as proactive as possible.

Enter: Test-IsRegistryPOLGood

I spent a bunch of time trying to figure out an intelligent manner of doing this, and after a lot of trial & error I was seeing inconsistent results.  After really getting into the weeds I wondered whether or not the structure/format of the file was documented.  Turns out it is:

The header contains the REGFILE_SIGNATURE expressed as 0x67655250 which is 80, 82, 101, 103 in bytes:


The header is in the first 4 bytes of the file so we read that and evaluate the bytes

Get-Content -Encoding Byte -Path 'path\to\someRegistry.pol' -TotalCount 4

On a good file, this returns an array consisting of 80, 82, 101, 103 which is exactly what we want.

On a bad file – or at least all the ones I had access to – it returned all zero’s.

To examine the file via PowerShell:

Function Test-IsRegistryPOLGood
                    [string[]]$PathToRegistryPOLFile = $(Join-Path $env:windir 'System32\GroupPolicy\Machine\Registry.pol')

        if(!(Test-Path -Path $PathToRegistryPOLFile -PathType Leaf)) { return $null }

        [Byte[]]$FileHeader = Get-Content -Encoding Byte -Path $PathToRegistryPOLFile -TotalCount 4

        if(($FileHeader -join '') -eq '8082101103') { return $true } else { return $false }


However, I wasn’t sure how we were going to implement this, so I explored doing this via VBScript and found ADO to be the ideal (only?) way:

Option Explici
Dim arrRegistryPolFiles
if(WScript.Arguments.Count > 0) then
    arrRegistryPolFiles = Array(WScript.Arguments(0))
    arrRegistryPolFiles  = Array(CreateObject("WScript.Shell").ExpandEnvironmentStrings("%WINDIR%") & "\System32\GroupPolicy\Machine\Registry.pol")
end if

Dim POLFile
For each POLFile in arrRegistryPolFiles
    if (CreateObject("Scripting.FileSystemObject").FileExists(POLFile)) then

        if(Join(ReadBinaryData(POLFile,3),"") = "8082101103") then
            wscript.echo True & vbtab & POLFile
            wscript.echo False & vbtab & POLFile
        end if
    end if


Function ReadBinaryData(Required_File,Int_Byte_Count)

Const adTypeBinary = 1

' Requires Read/Write, otherwise it fails with Operation is not allowed in this context.
Const adModeReadWrite = 3

Dim arrByteArray : arrByteArray = Array(-1)
With CreateObject("ADODB.Stream")
    .Mode = adModeReadWrite
    .Type = adTypeBinary
    .LoadFromFile Required_File

    Dim i
    For i=0 To Int_Byte_Count
        arrByteArray(i) = AscB(.Read(1))
        ReDim Preserve arrByteArray(UBound(arrByteArray)+1)
End With

ReadBinaryData = arrByteArray
end function


After testing this out on our known good and known bad registry.pol files, we cast our rod (the code) into a special script all machines run to see if we’d catch any fish and sure enough we did!

From there it was just a matter of deciding how to handle the bad files: Alert IT for manual remediation or fix it during execution.

Here’s something ‘odd’ to me: When I convert the bits 80, 82, 101, 103 into HEX, I get 50, 52, 65, 67 which is the reverse of 67655250. Does anyone know why that is? I think it has something to do with Intel processors being ‘Little Endian’, which results in the bytes in memory not appearing in the same order as they do when fetched into a register but I don’t know; That’s a more than little beyond me!

In any event, hopefully someone will find this as useful as we did!

Good Providence to you!

One comment

Leave a Reply to 221northlondon Cancel reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s