Introduction
Update 21 September 2024
We are happy and proud that we could have influence on the decision to wait with this implementation. Microsoft just announced that they will postpone this rollout π
Microsoft recently announced that we soon will be patched when we go through OOBE. You can read more about that here. While this seems like a very good idea to make the device secure as fast as possible, there are use cases where this will create more frustration than happiness. Rudy wrote a good blog post around this new feature which you can read more about here
In the tech community post it is stated that at this time, there is no option to control or disable quality patching from happening in OOBE, but they haven’t read this blog post π
I have use cases where I cannot afford to extend the onboarding time further than it already is even though a device will be vulnerable for the brief first moment the user enter the desktop. This is how it has been working up until now. Let’s dive into the good stuff!
Working with the new NDUP Feature
Tech community says:
Windows updates are essential for keeping your devices secure and up to date with the latest security, performance, and reliability improvements. One of the top customer requests we receive is to enable Windows updates during provisioning in the out-of-box experience (OOBE), so that devices are fully patched and ready to use as soon as they are enrolled with mobile device management (MDM).
So after the device has enrolled during autopilot, in my case I am using a Windows 11 24H2 build 26100 to test, it will indeed kick in with updating the device. It looks like this:
Let’s have a look behind this shell to see what actually is going on.
If we browse into eventlog and into Shell-core we will be able to see that the cloud experience host is the one driving this UI change for quality updates. Same host is being used for many other things like authentication, windows hello etc.
We will see it kick off the new feature OOBENDUP (Out-of-box-experience New Device Update Page)
It will then reach out to https://sdx.microsoft.com/frx/cloud-ndup to find out if the device is online. It would be odd, if the device was offline at this point, as we would assume the device just went through autopilot which funny enough needs internet.
But the internet could strike, so this check makes sense to have to ensure it will be able to start updating.
Cloud experience host will read a lot of things locally from the client to determine what it needs to consider.
It will reach out to certain endpoints to grab json files that it will use for different purposes.
sdx.microsoft.com/areas/frx/resources/json/NDUP_error_lottie.json
sdx.microsoft.com/areas/frx/resources/json/cloudndup/expeditedUpdatelottie.json
sdx.microsoft.com/areas/frx/resources/json/cloudndup/mercurylossAversionLottie.json
sdx.microsoft.com/areas/frx/resources/json/cloudndup/windowsLogoLottie.json
you can even look it up by typing the adress in edge, but it doesn’t give you much insight of anything other than it is parameters that will make cloud experience host do different things.
Next up we can see that the device found out which KB it needed to download and install
When this process kicks in, in OOBE, it will write this key in registry – EnableExpeditedUpdate equals 1.
Windows update engine will start to kick in and if it finds any updates it will start to download it.
Once it start to download the patch(es) you will see the next registry appear under the same library in registry. EnableExpeditedUpdateSyncDownloadCompleted equals 1
You will see the progress in the UI like this
And once it has finalized installing the patches it will create a third registry called – EnableExpeditedUpdateSyncInstallCompleted equals 1
We will also see that it was done in eventlog and the value is set to “success”
After that, the device will reboot.
Your device will start up with the Windows logon screen and you are finally ready to use your device after setting up Windows hello
Taking away internet from the device
What will happen if we take away internet on the box? It is obvious, since it is reaching to sdx.microsoft.com I would think it should fail. But how will the device then react if this is the case?
If we take a closer look at the CloudExperienceHost which is running the NDUP feature, we will discover that it immediately will find that the device have not internet
The final result of this will be “offline” and the NDUP feature will stop trying to get updates for your computer.
It will tell you it is done and succeeded the process.
It will finalize OOBE and show you the login screen as it normally would do prior this new NDUP feature was introduced.
And the end result is surprisingly the known windows login page.
What would happen if it started to update and then internet is taken away?
In this use case the device started off with internet, but I remove internet while it was trying to get the update downloaded to the device. We can see that the download started:
If internet disappear from the device and it will stay in this state for 10 minutes. After that it will continue as it could not download anything and continue.
It will return back that the OOBE NDUP failed to install the quality patch.
It will instruct the device that it needs to reboot (but hey it didn’t install anything why do we need to reboot???)
Login screen shows up.
How to shutdown NDUP from forcing your device to update during OOBE first try
To test out if we can tamper the OOBE let’s try the obvious. If you read the blog you would think the same – Try to set the EnableExpeditedUpdate to 0.
Let’s first try this manually to check it out and see if we can prohibit the quality update from coming down.
It will continue to check for updates
We see that the NDUP feature starts up
It queries sdx.microsoft.com
It test if it should skip the WU scan and the value is false, surprisingly or not? Microsoft wrote that we cannot control it, so not really any surprise.
Scan started
Scan succeeded
But it seems like the scan somehow fail, it will retry this 3 times before continuing.
But why did it fail in the first place? because of the setting we changed? NO
It failed because I was doing this in a session on WP Ninja where my battery was running low and that windows will not patch when the battery is in a low state.
and eventually fail.
Result: your device continued to Windows Hello without updating.
How to shutdown NDUP from forcing your device to update during OOBE. (the manual way)
This solution is not in any way supported, so before you proceed doing this, please be aware that you do this on your own risk!
The idea is to prohibit from accessing the vital information it needs.
To start with, we know that it reaches out to sdx.microsoft.com. We can also ping it
What if we introduced a long working trick to redirect this URL to ping the device itself? Let’s try out that theory. Starting the command prompt in OOBE after the device finalized Autopilot, and browse to the hosts file.
Adding in a loop so sdx.microsoft.com will redirect to itself.
After saving the file, let’s try to ping the adress again
Success, we got the desired result.
Starting the OOBE flow, it will start up NDUP and start the flow
It will try to reach out to the sdx.microsoft.com URL, but because we told it to ping itself, it now recieves the famous error 404. Good or bad?
Cloud experience host will take this signal and fail it and continue immediatly to next stage.
But this time because it did not start the flow, it will not reboot the device. It will simply continue after exiting OOBE NDUP and it successfully exited OOBE.
We see the Windows hello screen as we did prior to the NDUP feature being introduced. Despite no controls given, we can manage this with a bit of modification in the hosts file.
How to shutdown NDUP from forcing your device to update during OOBE. (The automatic way)
This solution is not in any way supported, so before you proceed doing this, please be aware that you do this on your own risk.
To make sure we target our device as early as possible, we can build a platform script. Grab the script here and save it e.g. to a file and call it Invoke-Disable-NDUP.ps1
To give you a bit more insight to what is does.
- Define Variables: Sets the IP address, hostname, paths for the hosts file and log file, and the entry to add.
- Logging Function: Defines a function to write messages to the log file with timestamps.
- Check and Add Entry: Checks if the entry exists in the hosts file. If not, it adds the entry and logs the action.
- New Script Content: Defines a new script to check and remove the entry from the hosts file if it exists, and logs the actions.
- Save New Script: Saves the new script to a specified path.
We do this to be able to have it on the disc to clean up after our selves, so we only need to import this single script. - Create Scheduled Task: Creates a scheduled task to run the new script at logon, with the highest privileges, and logs the creation of the task. The schedule task will run after you logon the first time and remove the blocking entry, making your device “normal” again and without any custom none supported entries that might break stuff at a later point.
- Delete scheduled Task: The script we put on the disc which is run by the schedule task will clean up, so we have no more running schedule task.
<# .SYNOPSIS Prohibit the use of the NDUP feature to patch Quality updates in OOBE .DESCRIPTION This script is designed to be run as a platform script in Intune. This will add an entry to the hosts file to prevent the NDUP feature from getting any content from its URL and create a scheduled task to remove the entry at logon. .PARAMETER .EXAMPLE Invoke-Disable-NDUP.ps1 (Required to run as System or Administrator) .NOTES Author: Mattias Melkersen Date: 19-09-2024 twitter @Mmelkersen Operational Changelog: ---------------------- 19-09-2024 - v1.0 - Original Release #> # Define the IP address and hostname $ipAddress = "127.0.0.1" $hostname = "sdx.microsoft.com" # Path to the hosts file $hostsFilePath = "$env:SystemRoot\System32\drivers\etc\hosts" # Path to the log file $logFilePath = "$env:SystemRoot\Temp\NDUP.log" # Entry to add $entry = "$ipAddress`t$hostname" # Function to write to log file function Write-Log { param ( [string]$message ) $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logMessage = "$timestamp`t$message" Add-Content -Path $logFilePath -Value $logMessage } # Check if the entry already exists if (-not (Select-String -Path $hostsFilePath -Pattern $hostname)) { # Add the entry to the hosts file Add-Content -Path $hostsFilePath -Value $entry Write-Log "Entry added: $entry" Write-Output "Entry added: $entry" } else { Write-Log "Entry already exists. $entry" Write-Output "Entry already exists." } # Define the content of the new script $newScriptContent = @' # Define the IP address and hostname to check $ipAddress = "127.0.0.1" $hostname = "sdx.microsoft.com" # Path to the hosts file $hostsFilePath = "$env:SystemRoot\System32\drivers\etc\hosts" # Path to the log file $logFilePath = "$env:SystemRoot\Temp\NDUP.log" # Entry to check $entry = "$ipAddress`t$hostname" # Function to write to log file function Write-Log { param ( [string]$message ) $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logMessage = "$timestamp`t$message" Add-Content -Path $logFilePath -Value $logMessage } # Read the hosts file $hostsFileContent = Get-Content -Path $hostsFilePath # Check if the entry exists if ($hostsFileContent -contains $entry) { # Remove the entry $updatedHostsFileContent = $hostsFileContent | Where-Object { $_ -ne $entry } # Write the updated content back to the hosts file $updatedHostsFileContent | Set-Content -Path $hostsFilePath Write-Log "Entry removed: $entry" Write-Output "Entry removed: $entry" } else { Write-Log "Entry does not exist: $entry" Write-Output "Entry does not exist." } # Remove the scheduled task if it exists $taskName = "Cleanup_NDUP" if (Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue) { Unregister-ScheduledTask -TaskName $taskName -Confirm:$false Write-Log "Scheduled task '$taskName' removed." Write-Output "Scheduled task '$taskName' removed." } else { Write-Log "Scheduled task '$taskName' does not exist." Write-Output "Scheduled task '$taskName' does not exist." } '@ # Path to save the new script $newScriptPath = "$env:SystemRoot\temp\Cleanup_NDUP.ps1" # Save the new script content to the file Set-Content -Path $newScriptPath -Value $newScriptContent Write-Log "New script created at $newScriptPath" Write-Output "New script created at $newScriptPath" # Define the task name and action $taskName = "Cleanup_NDUP" $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-Executionpolicy bypass -File `"$newScriptPath`"" # Define the trigger to run at logon $trigger = New-ScheduledTaskTrigger -AtLogOn # Define the principal to run the task as SYSTEM $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest # Register the scheduled task Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal Write-Log "Scheduled task '$taskName' created to run at logon." Write-Output "Scheduled task '$taskName' created to run at logon." # End of script
Go to Intune and browse to platform scripts
Upload your script and set your settings like this:
assign it to your entra group where you ADE policy is targetted.
Browse to your Autopilot preparation policies and edit it
Edit Settings
Click on add scripts
Add the script invoke-Disable-NDUP and click save
Click next and save, you should be able to locate your script in the overview of ADE
The experience will look like this:
If we take a closer look in the log file created by the script we see it successfully went through the initiation and the cleanup.
Looking into the hosts file, we can see it cleaned for us and the sdx block has been removed nicely.
If we take a look into scheduled task, we also see here, that we cleaned up nicely after ourselves.
and this concludes a happy device
It can patch just as we are used to from the old experience.
Summary
During the Out-of-Box Experience (OOBE), we will soon be required to install quality updates. For me, this added 26 minutes to the Autopilot onboarding process, which was frustrating and extended my non-productive time. This impacts my ability to have a quick onboarding experience. I would prefer to start with a less patched device, as long as I can access my desktop and allow updates to install in the background, as they have done previously.
Currently, there is no official way to control this behavior, but this post demonstrates that it is possible.
Hello!
Thanks for the great article!
I wonder if you have tried setting “EnableExpeditedUpdateSyncInstallCompleted” registry value to 1 using the powershell script. Would that make the NDUP process from skip the installation?
Regards
Thanks Jared.
Yes I have tried that, the registry is just overwritten in the moment it start π
Not really a work around that will help.
You can discharge all of your laptops to under 40% battery and it will not try to install. π