Create a GPO for PowerShell 5.0 settings

I’ve written the following piece of code to automate the creation of a Group Policy that would configure all the new PowerShell 5 settings – ScriptBlock Logging, Protected EventLog and Transcripts – that Lee Holmes mentioned in the PowerShell ♥ the Blue Team post.

It should be run from a Windows 10 computer joined to the domain where you’ve the Remote Server Administration Tools (RSAT) installed because of the New-SelfsignedCertificate cmdlet and the GroupPolicy module requirement. If you’ve a PKI, you don’t need the self-signed certificate and may prefer using a certificate issued by your PKI. In this case, you start by enrolling the certificate from your PKI and the demo code below will use that one instead.

Last warning, the C:\Transcripts folder should exist on the computer targeted by the GPO and the NTFS security should be adjusted before applying the GPO.
Unfortunately the GPO doesn’t handle that requirement.

#Requires -RunasAdministrator
#Requires -Modules ActiveDirectory,GroupPolicy
# Make sure we can reach the PDC
$PDC = (Get-ADDomainController -Service 1 -Discover -ErrorAction SilentlyContinue).Hostname
if ($PDC) {
# Get the domain name
$DomainName = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name
# Create the GPO
try {
$GPO = New-GPO -Name 'PowerShell 5 Settings' -Domain "$($DomainName)" -ErrorAction Stop
} catch {
Write-Warning -Message "Failed to create PS5 GPO because $($_.Exception.Message)"
}
if ($GPO) {
# Don't need user settings
$GPO.GpoStatus = [Microsoft.GroupPolicy.GpoStatus]::UserSettingsDisabled
if (-not(Get-ChildItem -Path Cert:\LocalMachine\My\ -DocumentEncryptionCert -EA SilentlyContinue) {
# Create a self signed certificate
$CertHT = @{
Subject = "CN=ProtectedEventLog@$($DomainName)";
KeyLength = 2048;
KeySpec = 'KeyExchange';
HashAlgorithm = 'SHA1';
KeyExportPolicy = 'Exportable';
KeyUsage = 'KeyEncipherment','DataEncipherment' ;
NotAfter = (Get-Date).AddYears(1);
TextExtension = '2.5.29.37={text}1.3.6.1.4.1.311.80.1';
}
try {
$SSCert = New-SelfSignedCertificate @CertHT -ErrorAction Stop
} catch {
Write-Warning -Message "Self signed certificate issue because $($_.Exception.Message)"
}
} else {
# Use the first ocumentEncryption capable certificate (the one enrolled by a PKI, if any)
$SSCert = Get-ChildItem -Path Cert:\LocalMachine\My\ -DocumentEncryptionCert | Select -First 1
}
if ($SSCert) {
# Export the public and private key
try {
Export-Certificate -Type CERT -Cert $SSCert -FilePath "$($HOME)\Documents\publickeyGPO.cer" -ErrorAction Stop
Export-PfxCertificate -Cert $SSCert -Password (ConvertTo-SecureString -AsPlainText '12345678' -Force) -FilePath "$($HOME)\Documents\privatekeyGPO.pfx" -ErrorAction Stop
} catch {
Write-Warning -Message "Exporting certificate failed because $($_.Exception.Message)"
}
# Get a base-64 encoded blob
$B64CertString = @"
-----BEGIN CERTIFICATE-----
$(
[Convert]::ToBase64String(
($SSCert).Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert),
'InsertLineBreaks'
)
)
-----END CERTIFICATE-----
"@
# Main hashtable
$HT = @{ GUID = ($GPO).Id ; ErrorAction = 'Stop' }
# Array that stores each setting as a hashtable
@(
# Script Block Logging
@{ Key = 'HKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' ;
ValueName = 'EnableScriptBlockLogging' ; Type = 'String' ; Value = '1'
},
# Do not enable script block invocation logging
@{ Key = 'HKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging' ;
ValueName = 'EnableScriptBlockInvocationLogging' ; Type = 'String' ; Value = '0'
},
# Enable Protected Eventlog
@{ Key = 'HKLM\Software\Policies\Microsoft\Windows\EventLog\ProtectedEventLogging' ;
ValueName = 'EnableProtectedEventLogging' ;Type = 'String' ; Value = '1'
},
# Set its base-64 public key
@{ Key = 'HKLM\Software\Policies\Microsoft\Windows\EventLog\ProtectedEventLogging' ;
ValueName = 'EncryptionCertificate' ; Type = 'String' ; Value = $B64CertString
},
# Transcript
@{ Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription' ;
ValueName = 'EnableTranscripting' ; Type = 'DWORD'; Value = 1
},
# Set its path
@{ Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription' ;
ValueName = 'OutputDirectory' ; Type = 'String' ; Value = 'C:\Transcripts'
},
# Do not enable invocation header
@{ Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription' ;
ValueName = 'EnableInvocationHeader' ; Type = 'DWORD' ; Value = 0
}
) | ForEach-Object {
$reg = $_
try {
Set-GPRegistryValue @HT @reg
} catch {
Write-Warning -Message "Faile to set GPO setting because $($_.Exception.Message)"
}
}
}
}
}
view raw PS5GPO.ps1 hosted with ❤ by GitHub

2 thoughts on “Create a GPO for PowerShell 5.0 settings

  1. Pingback: Create a GPO for PowerShell 5.0 settings | Tim Bolton - MCITP - MCTS

  2. Pingback: Dew Drop - July 29, 2016 (#2298) - Morning Dew

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com 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

This site uses Akismet to reduce spam. Learn how your comment data is processed.