Last active
May 18, 2023 20:33
-
-
Save zjorz/a8995e9b6e9d3d091a04c5c7b952b05a to your computer and use it in GitHub Desktop.
Configuring New Or Existing GPO With The GenCounter System Service To NOT Start (i.e., Disable Generation ID)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#------- | |
# Configuring New Or Existing GPO With The GenCounter System Service To NOT Start (i.e., Disable Generation ID) | |
#------- | |
$gpoName = "<Name Of Existing Or New GPO>" # <=== CONFIGURE !!!! | |
Invoke-Command -ArgumentList $gpoName -Scriptblock { | |
Param ( | |
$gpoName | |
) | |
Clear-Host | |
$adDomain = Get-ADDomain | |
$adDomainDN = $adDomain.DistinguishedName | |
$rwdcPDCFSMOFQDN = $adDomain.PDCEmulator | |
Write-Host "======================== GPO '$gpoName' ========================" -ForegroundColor Magenta | |
$gpo = Get-GPO -All -Server $rwdcPDCFSMOFQDN | Where-Object {$_.DisplayName -eq $gpoName} | |
If ([String]::IsNullOrEmpty($gpo)) { | |
$gpo = New-GPO -Name $gpoName -Server $rwdcPDCFSMOFQDN | |
Write-Host " > ACTION..............................: 'Create GPO'" -ForegroundColor Yellow | |
} Else { | |
Write-Host " > ACTION..............................: 'Reuse Existing GPO'" -ForegroundColor Yellow | |
} | |
$gpoID = $gpo.Id.Guid | |
Write-Host " > GPO ID..............................: '$gpoID" -ForegroundColor Yellow | |
$localSysvolPath = (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares | Select -ExpandProperty SYSVOL | ?{$_ -match "Path"}).Split("=")[1] | |
$gptTmplInfFilePath = "$($localSysvolPath.Replace("SYSVOL\sysvol","SYSVOL\Domain"))\Policies\{$gpoID}\Machine\microsoft\windows nt\SecEdit\GptTmpl.inf" | |
Write-Host " > GptTmplInf File Path................: $gptTmplInfFilePath" -ForegroundColor Yellow | |
$gptIniFilePath = "$($localSysvolPath.Replace("SYSVOL\sysvol","SYSVOL\Domain"))\Policies\{$gpoID}\gpt.ini" | |
Write-Host " > GptIni File Path....................: $gptIniFilePath" -ForegroundColor Yellow | |
$gpoDN = "CN={$gpoID},CN=Policies,CN=System,$adDomainDN" | |
Write-Host " > GPO DN..............................: $gpoDN" -ForegroundColor Yellow | |
# Read Content Of INI Structured File For Further Processing | |
# Source: https://devblogs.microsoft.com/scripting/use-powershell-to-work-with-any-ini-file/ | |
Function readINIFile { | |
param( | |
[string]$iniFilePath | |
) | |
$anonymous = "NoSection" | |
$i = 0 | |
$ini = @{} | |
switch -regex -file $iniFilePath { | |
"^\[(.+)\]$" { # Section | |
$section = $matches[1] | |
$ini[$section] = @{} | |
$CommentCount = 0 | |
} | |
"^(;.*)$" { # Comment | |
if (!($section)) { | |
$section = $anonymous | |
$ini[$section] = @{} | |
} | |
$value = $matches[1] | |
$CommentCount = $CommentCount + 1 | |
$name = "Comment" + $CommentCount | |
$ini[$section][$name] = $value | |
} | |
"(.+?)\s*=\s*(.*)" { # Key | |
if (!($section)) { | |
$section = $anonymous | |
$ini[$section] = @{} | |
} | |
$name, $value = $matches[1..2] | |
$ini[$section][$name] = $value | |
} | |
'\"(.*)\",\d,\"(.*)\"' { # Special Key For GptTempl.inf files with "[Service General Setting]" section => | |
if (!($section)) { | |
$section = $anonymous | |
$ini[$section] = @() | |
} | |
$svcConfig = $matches[0] | |
$ini[$section]["svc$i"] = $svcConfig | |
$i++ | |
} | |
} | |
return $ini | |
} | |
# Write Content Of INI Structured File After Processing | |
# Source: https://devblogs.microsoft.com/scripting/use-powershell-to-work-with-any-ini-file/ | |
Function writeINIFile { | |
Param ( | |
$inputObject, | |
$iniFilePath, | |
$encoding | |
) | |
If([string]::IsNullOrEmpty($encoding)) { | |
$encoding = "Default" | |
} | |
New-Item -Path $iniFilePath -ItemType File -Force | Out-Null | |
ForEach ($i in $inputObject.keys) { | |
If (!($($inputObject[$i].GetType().Name) -eq "Hashtable")) { | |
# No Sections | |
Add-Content -Path $iniFilePath -Value "$i = $($inputObject[$i])" -Encoding $encoding | |
} Else { | |
# Sections | |
Add-Content -Path $iniFilePath -Value "[$i]" -Encoding $encoding | |
ForEach ($j in ($inputObject[$i].keys | Sort-Object)) { | |
If ($j -match "^Comment[\d]+") { | |
Add-Content -Path $iniFilePath -Value "$($inputObject[$i][$j])" -Encoding $encoding | |
} Else { | |
Add-Content -Path $iniFilePath -Value "$j = $($inputObject[$i][$j])" -Encoding $encoding | |
} | |
} | |
Add-Content -Path $iniFilePath -Value "" -Encoding $encoding | |
} | |
} | |
} | |
# Trigger The Creation Of The SYSVOL GPO Part By Configuring Some Setting And Removing It Again | |
If (!(Test-Path $gptIniFilePath)) { | |
Write-Host " > Triggering The Creation Of The GPO.INI..." -ForegroundColor Yellow | |
$params = @{ | |
Name = $gpoName | |
Context = 'Computer' | |
Key = 'HKLM\SYSTEM\CurrentControlSet\Services\gencounter' | |
ValueName = 'Start' | |
Value = 4 | |
Type = 'DWORD' | |
Action = 'Update' | |
} | |
Set-GPPrefRegistryValue @params | |
Start-Sleep -s 5 | |
Remove-GPPrefRegistryValue -Name $params.Name -Context $params.Context -Key $params.Key -ValueName $params.ValueName | |
} | |
# Read The GpTTmplInf File If It Exists, Otherwise Define One To Be Written Later | |
If (Test-Path $gptTmplInfFilePath) { | |
$gptTmplInfFileHT = readINIFile $gptTmplInfFilePath | |
} Else { | |
$gptTmplInfFileHT = @{} | |
$gptTmplInfFileHT["Version"] = @{} | |
$gptTmplInfFileHT["Version"]["signature"] = '$CHICAGO$' | |
$gptTmplInfFileHT["Version"]["Revision"] = "1" | |
$gptTmplInfFileHT["Unicode"] = @{} | |
$gptTmplInfFileHT["Unicode"]["Unicode"] = "yes" | |
} | |
If ([string]::IsNullOrEmpty($gptTmplInfFileHT["Service General Setting"])) { | |
# Add Section And Service Config | |
$gptTmplInfFileHT["Service General Setting"] = @{} | |
$gptTmplInfFileHT["Service General Setting"]["svc0"] = "`"GenCounter`",4,`"`"" | |
$updateGptTmplInfFile = $true | |
} Else { | |
# Check If Section Contains The Correct Service Config | |
If ([string]::IsNullOrEmpty($gptTmplInfFileHT["Service General Setting"].Values -match "GenCounter")) { | |
$numSvcs = ($gptTmplInfFileHT["Service General Setting"].Values | Measure-Object).count | |
$gptTmplInfFileHT["Service General Setting"]["svc$numSvcs"] = "`"GenCounter`",4,`"`"" | |
$updateGptTmplInfFile = $true | |
} Else { | |
$svcItem = ($gptTmplInfFileHT["Service General Setting"].GetEnumerator() | Where-Object {$_.Value -match "GenCounter"}).Name | |
If ($gptTmplInfFileHT["Service General Setting"][$svcItem] -notmatch '\"GenCounter\",4,\"(.*)\"') { | |
$gptTmplInfFileHT["Service General Setting"][$svcItem] = $($gptTmplInfFileHT["Service General Setting"][$svcItem].Split(",")[0]) + ",4," + $($gptTmplInfFileHT["Service General Setting"][$svcItem].Split(",")[2]) | |
$updateGptTmplInfFile = $true | |
} Else { | |
$updateGptTmplInfFile = $false | |
} | |
} | |
} | |
If ($updateGptTmplInfFile -eq $true) { | |
# Write Content To GptTmplInfFile | |
Write-Host " > Writing The GptTmplInf File '$gptTmplInfFilePath'" -ForegroundColor Yellow | |
writeINIFile $gptTmplInfFileHT $gptTmplInfFilePath | |
Set-Content -Path $gptTmplInfFilePath -Value $((Get-Content $gptTmplInfFilePath) -replace 'svc(.*) = ','') | |
# Get AD GPO, Version And Machine Extensions | |
$adGPO = Get-ADObject -Identity $gpoDN -Properties gPCMachineExtensionNames,versionNumber -Server $rwdcPDCFSMOFQDN | |
$adGPOVersion = [int]$adGPO.versionNumber | |
Write-Host " > GPO AD Version......................: $adGPOVersion" -ForegroundColor Yellow | |
$adGPOMachineExtensions = $adGPO.gPCMachineExtensionNames | |
Write-Host " > GPO Machine Extensions..............: $(If ([string]::IsNullOrEmpty($adGPOMachineExtensions)) {"NONE"} Else {$adGPOMachineExtensions})" -ForegroundColor Yellow | |
# Get SYSVOL GPO Version | |
$gptIniFileHT = readINIFile $gptIniFilePath | |
$sysvolGPOVersion = [int]$gptIniFileHT["General"]["Version"] | |
Write-Host " > GPO SYSVOL Version..................: $sysvolGPOVersion" -ForegroundColor Yellow | |
# Calculate The New Version | |
If ($adGPOVersion -gt $sysvolGPOVersion) { | |
$gpoVersionCurrent = $adGPOVersion | |
} ElseIf ($adGPOVersion -lt $sysvolGPOVersion) { | |
$gpoVersionCurrent = $sysvolGPOVersion | |
} Else { | |
$gpoVersionCurrent = $sysvolGPOVersion | |
} | |
$gpoVersionNew = $gpoVersionCurrent + 1 | |
Write-Host " > GPO AD/SYSVOL Version (New).........: $gpoVersionNew" -ForegroundColor Yellow | |
# Required Extensions For A GPO To Be Able To Configure The Required System Service | |
$gpoRequiredExtensions = @{} | |
$gpoRequiredExtensions["Security"] = "[{827D319E-6EAC-11D2-A4EA-00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}]" | |
# Define The NEW Machine Extensions Of The GPO | |
$gpoADObjectMachineExtensionList = $null | |
If ((-not [String]::IsNullOrEmpty($adGPOMachineExtensions))) { | |
$gpoADObjectMachineExtensionList = $adGPOMachineExtensions.Replace("][","]|[").Split("|") | |
} Else { | |
$gpoADObjectMachineExtensionList = @() | |
} | |
If ($gpoADObjectMachineExtensionList -notcontains $gpoRequiredExtensions["Security"]) { | |
$gpoADObjectMachineExtensionList += $gpoRequiredExtensions["Security"] | |
} | |
$gpoADObjectMachineExtensionNames = $null | |
$gpoADObjectMachineExtensionNames = $($($gpoADObjectMachineExtensionList | Sort-Object) -join "") | |
Write-Host " > GPO Machine Extensions (New)........: $gpoADObjectMachineExtensionNames" -ForegroundColor Yellow | |
# Set AD GPO Version And Machine Extensions | |
Write-Host " > Configuring The GPO AD Version And Machine Extensions" -ForegroundColor Yellow | |
Set-ADObject -Identity $gpoDN -Replace @{gPCMachineExtensionNames = $gpoADObjectMachineExtensionNames; versionNumber = $gpoVersionNew} | |
# Set SYSVOL GPO Version | |
$gptIniFileHT["General"]["Version"] = $gpoVersionNew | |
Write-Host " > Configuring The GPO SYSVOL Version" -ForegroundColor Yellow | |
writeINIFile $gptIniFileHT $gptIniFilePath | |
Write-Host "" | |
Write-Host " > Done!" -ForegroundColor Yellow | |
Write-Host "You May Still Need To Link The GPO '$gpoName' To The Domain Controllers OU, If Not Already Done!" -Foregroundcolor Magenta | |
Write-Host "" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment