When deploying Windows 10 in your organization, it’s strongly recommended to take a look at the new security features Windows brings to the table. One specific feature that I recommend all of my customers looking at Windows 10 to implement is Credential Guard. It’s a feature that uses virtualization-based security to isolate secrets so that only privileged system software can access them. Meaning, no more pass-the-hash attacks, hopefully. Anyway, we can easily turn this on during the deployment of a Windows 10 device by using PowerShell. Basically, what you need to do is to add the Hyper-V Hypervisor and Isolated User Mode features, set a couple of registry values and you’re set. In this post I’ll demonstrate how you can enable Credential Guard by running the script below and how you have to configure it in your task sequence for a successful deployment.

If you want to read up on Credential Guard, you’ll be able to find more information on the link below:

https://technet.microsoft.com/itpro/windows/keep-secure/credential-guard

Script to enable Credential Guard

I’ve put together a PowerShell script that you’ll find below that will enable Credential Guard during Windows 10 deployment.

2017-07-03 – Updated the script so that it doesn’t enable Hyper-V on Windows 10 version 1607 or higher.

2016-08-10  – With the release of Windows 10 version 1607, it’s no longer a requirement to add the Isolated User Mode feature when enabling Credential Guard, since it’s now embedded in the Hypervisor. Therefor, I’ve updated the script below to only add the Isolated User Mode feature when the BuildNumber property in Win32_OperatingSystem is less than 14393.

<#
.SYNOPSIS
    Enable Credential Guard on Windows 10 during OS Deployment with ConfigMgr

.DESCRIPTION
    This script will enable a Windows 10 device being installed through OS Deployment with ConfigMgr to leverage Credential Guard
    in order to prevent pass-the-hash attacks.

.EXAMPLE
    .\Enable-CredentialGuard.ps1

.NOTES

    Version history:
    1.0.0 - (2016-06-08) Script created
    1.0.1 - (2016-08-10) Script updated to support Windows 10 version 1607 that no longer required the Isolated User Mode feature, since it's embedded in the hypervisor
    1.0.2 - (2017-07-03) Script updated since Windows 10 version 1607 and higher no longer needs Hyper-V feature for enablind Credential Guard

.NOTES
    FileName:    Enable-CredentialGuard.ps1
    Author:      Nickolaj Andersen
    Contact:     @NickolajA
    Created:     2016-06-08
    Updated:     2017-07-03
    Version:     1.0.2
#>
Begin {
    # Construct TSEnvironment object
    try {
        $TSEnvironment = New-Object -ComObject Microsoft.SMS.TSEnvironment -ErrorAction Stop
    }
    catch [System.Exception] {
        Write-Warning -Message "Unable to construct Microsoft.SMS.TSEnvironment object" ; exit 1
    }
}
Process {
    # Functions
    function Write-CMLogEntry {
      param(
        [parameter(Mandatory=$true, HelpMessage="Value added to the smsts.log file.")]
        [ValidateNotNullOrEmpty()]
        [string]$Value,

        [parameter(Mandatory=$true, HelpMessage="Severity for the log entry. 1 for Informational, 2 for Warning and 3 for Error.")]
        [ValidateNotNullOrEmpty()]
            [ValidateSet("1", "2", "3")]
        [string]$Severity,

        [parameter(Mandatory=$false, HelpMessage="Name of the log file that the entry will written to.")]
        [ValidateNotNullOrEmpty()]
        [string]$FileName = "EnableCredentialGuard.log"
      )
      # Determine log file location
        $LogFilePath = Join-Path -Path $Script:TSEnvironment.Value("_SMSTSLogPath") -ChildPath $FileName

        # Construct time stamp for log entry
        $Time = -join @((Get-Date -Format "HH:mm:ss.fff"), "+", (Get-WmiObject -Class Win32_TimeZone | Select-Object -ExpandProperty Bias))

        # Construct date for log entry
        $Date = (Get-Date -Format "MM-dd-yyyy")

        # Construct context for log entry
        $Context = $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)

        # Construct final log entry
        $LogText = "<![LOG[$($Value)]LOG]!><time=""$($Time)"" date=""$($Date)"" component=""CredentialGuard"" context=""$($Context)"" type=""$($Severity)"" thread=""$($PID)"" file="""">"
  
      # Add value to log file
        try {
          Add-Content -Value $LogText -LiteralPath $LogFilePath -ErrorAction Stop
        }
        catch [System.Exception] {
            Write-Warning -Message "Unable to append log entry to EnableCredentialGuard.log file"
        }
    }

    # Write beginning of log file
    Write-CMLogEntry -Value "Starting configuration for Credential Guard" -Severity 1

    if ([int](Get-WmiObject -Class Win32_OperatingSystem).BuildNumber -lt 14393) {
        try {
            # For version older than Windows 10 version 1607 (build 14939), enable required Windows Features for Credential Guard
            Enable-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V-HyperVisor -Online -All -LimitAccess -NoRestart -ErrorAction Stop
            Write-CMLogEntry -Value "Successfully enabled Microsoft-Hyper-V-HyperVisor feature" -Severity 1

            # For version older than Windows 10 version 1607 (build 14939), add the IsolatedUserMode feature as well
            Enable-WindowsOptionalFeature -FeatureName IsolatedUserMode -Online -All -LimitAccess -NoRestart -ErrorAction Stop
            Write-CMLogEntry -Value "Successfully enabled IsolatedUserMode feature" -Severity 1
        }
        catch [System.Exception] {
            Write-CMLogEntry -Value "An error occured when enabling required windows features" -Severity 3
        }
    }
    
    # Add required registry key for Credential Guard
    $RegistryKeyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard"
    if (-not(Test-Path -Path $RegistryKeyPath)) {
        Write-CMLogEntry -Value "Creating HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard registry key" -Severity 1
        New-Item -Path $RegistryKeyPath -ItemType Directory -Force
    }

    # Add registry value RequirePlatformSecurityFeatures - 1 for Secure Boot only, 3 for Secure Boot and DMA Protection
    Write-CMLogEntry -Value "Adding HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard\RequirePlatformSecurityFeatures value as DWORD with data 1" -Severity 1
    New-ItemProperty -Path $RegistryKeyPath -Name RequirePlatformSecurityFeatures -PropertyType DWORD -Value 1

    # Add registry value EnableVirtualizationBasedSecurity - 1 for Enabled, 0 for Disabled
    Write-CMLogEntry -Value "Adding HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard\EnableVirtualizationBasedSecurity value as DWORD with data 1" -Severity 1
    New-ItemProperty -Path $RegistryKeyPath -Name EnableVirtualizationBasedSecurity -PropertyType DWORD -Value 1

    # Add registry value LsaCfgFlags - 1 enables Credential Guard with UEFI lock, 2 enables Credential Guard without lock, 0 for Disabled
    Write-CMLogEntry -Value "Adding HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\LsaCfgFlags value as DWORD with data 1" -Severity 1
    New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name LsaCfgFlags -PropertyType DWORD -Value 1

    # Write end of log file
    Write-CMLogEntry -Value "Successfully enabled Credential Guard" -Severity 1
}

 

Configure The task Sequence

Adding this script to your task sequence is no big deal really, we simply just have to call a PowerShell script with the Run PowerShell Script step and point that to a Package that contains the script file. However, there’s a catch to enabling Credential Guard during OS deployment. When adding the Windows features, by using dism.exe for example like I do in my script, an exit code of 3010 will be returned. This is not something extraordinary, but the Hyper-V Hypervisor requires an extra restart. This would eventually prevent the task sequence to break if you would add a Restart Computer step right after the step that runs the script. To work around this, we can let the script that enables Credential Guard return 3010 and enforce a restart once the task sequence has completed by using the SMSTSPostAction variable. This way, when the task sequence has successfully completed, the dual restart enforced by the Hyper-V Hypervisor feature will not break the sequence.

1. Save the above script as e.g. Enable-CredentialGuard.ps1 in folder called EnableCredentialGuard in your Content Library.
2. Create a Package without any Program and set the Data Source location to the folder you just created. Remember to distribute the content to your Distribution Points.
3. Edit your task sequence used to deploy Windows 10.
4. Add a Run PowerShell Script step somewhere at the end of your task sequence, and configure it like in the picture below:
203_1
5. At the very top of your task sequence, add a Set Task Sequence Variable step and configure it like in the picture below:
203_2
6. Save the changes and start deploying!

Results

This script will log the output of the operations if performs in a log called EnableCredentialGuard.log that is stored together with the other task sequence logs. Eventually, once the deployment has completed, you’ll find it in C:\Windows\CCM\logs. Below is how a successful deployment that enabled Credential Guard looks like:
203_4
If you’d like to verify that Credential Guard actually was enabled on the device that you’ve deployed, open msinfo32.exe and scroll down in the System Summary section. You should see that Credential Guard is present in the value section, like shown below:
203_5
That’s it, I hope that you try this out and enables Credential Guard in your Windows 10 deployment. As usual, if you have any questions, feel free to comment below or send me an email.

 

(3691)

Nickolaj Andersen
Principal Consultant and Enterprise Mobility MVP since 2016. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows devices and deployments including automation. Currently working for TrueSec as a Principal Consultant. Awarded as PowerShell Hero in 2015 by the community for his script and tools contributions. Creator of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService to name a few. Frequent speaker at conferences and user groups.
comments
  • Aaron
    Posted at 14:29 August 4, 2016
    Aaron
    Reply
    Author

    Seems to be failing in 1607 deployments

    • Bill Moore
      Posted at 15:53 August 4, 2016
      Bill Moore
      Reply
      Author

      Just a guess. I think IsolatedUserMode is not part of the Hypervisor in 1607. I would try removing that installation section of the script to see if it’s successful.

  • Bill Moore
    Posted at 15:54 August 4, 2016
    Bill Moore
    Reply
    Author

    Haha. Should read *now* part of the hypervisor. Apologies.

  • Steve Whitcher
    Posted at 16:11 August 10, 2016
    Steve Whitcher
    Reply
    Author

    In a domain joined scenario, is there an advantage to enabling credential guard during using this script OSD versus using a group policy to enable credential guard?

  • Murat Kaya
    Posted at 14:36 February 15, 2017
    Murat Kaya
    Reply
    Author

    Great post, i could not remove hyper v gui/tools etc during TS so i need just hyper v hypervisor for credential guard. any idea?

  • Steve Whitcher
    Posted at 13:38 June 30, 2017
    Steve Whitcher
    Reply
    Author

    Is it still necessary to enable the hypervisor feature in order to enable credential guard? This article has a note which seems to imply that it is not:
    https://docs.microsoft.com/en-us/windows/access-protection/credential-guard/credential-guard-manage

    “If you enable Credential Guard by using Group Policy, the steps to enable Windows features through Control Panel or DISM are not required. Group Policy will install Windows features for you.”

    It doesn’t specifically mention the Hypervisor feature, but I do seem to have computers which show credential guard as running despite not having the hypervisor feature enabled.

  • Steve Whitcher
    Posted at 13:41 June 30, 2017
    Steve Whitcher
    Reply
    Author

    Oops, pasted the wrong quote in my previous comment. The article was right, but the section I meant to quote was:

    “Starting with Windows 10, version 1607 and Windows Server 2016, enabling Windows features to use virtualization-based security is not necessary and this step can be skipped.”

    https://docs.microsoft.com/en-us/windows/access-protection/credential-guard/credential-guard-manage

    • Nickolaj Andersen
      Posted at 22:00 July 3, 2017
      Nickolaj Andersen
      Reply
      Author

      Hi Steve,

      Yes, you’re correct. This is a great addition/change in the requirements for Credential Guard. It will now allow for other applications to leverage the virtualization as well and not only allow Hyper-V access.

      Regards,
      Nickolaj

  • Jose
    Posted at 01:35 July 4, 2017
    Jose
    Reply
    Author

    What is the obstacle of attempting to implement this on a “build and capture” TS ?

    • Nickolaj Andersen
      Posted at 07:31 July 4, 2017
      Nickolaj Andersen
      Reply
      Author

      Hi Jose,

      Why would you want to do that? Simply run this script in your TS used to deploy your systems.

      Regards,
      Nickolaj

      • Jose
        Posted at 13:56 July 5, 2017
        Jose
        Reply
        Author

        In my environment, we capture WIMs monthly to include updates, and consequently minimize the time it takes to build a device. Every time we have to make changes to OSD, we always consider its possibility during capture TS. Your approach involves a couple of restarts which is totally fine by me, but you know how “initializing agent…” takes a while during TS after every restart. It sounds trivial, but if I can save minutes on build time for end-users, that would be a preference for us.

        • Nickolaj Andersen
          Posted at 14:03 July 5, 2017
          Nickolaj Andersen
          Reply
          Author

          I get your point, but as a matter of fact, with Windows 10 version 1607 and higher you don’t need to add the Hyper-V features which removes the need to restart. A final restart at the end of your task sequence is considered best practice, and even fixes a few old but known issues. All of this should be enough for enabling this in the task sequence during deployment.

          Regards,
          Nickolaj

  • Lauri
    Posted at 13:54 August 22, 2017
    Lauri
    Reply
    Author

    The script enables all of Hyper-V features but is it possible to disable other features like Managements Tools and Hyper-V Services so that only Hyper-V Hypervisor is left enabled?

    • Nickolaj Andersen
      Posted at 08:17 August 23, 2017
      Nickolaj Andersen
      Reply
      Author

      It will only enable those features for Windows 10 1511 and below. For 1607 and above they’re no longer required.

      Regards,
      Nickolaj

  • Chris
    Posted at 15:45 September 19, 2017
    Chris
    Reply
    Author

    Hi Nickolaj, are your sure in not enabling Hyper-V?
    2017-07-03 – Updated the script so that it doesn’t enable Hyper-V on Windows 10 version 1607 or higher
    i tried enabling CG without installation of HyperV – Image version was 1703, rebuilt ISO from June 17 – but it doesn’t matter, CG wasn’t active yet until i enabled the Hyper-V HyperVisor manually.
    Kind regards
    Chris

  • Leave a Reply