This blog introduces a new Intune feature: ConfigRefresh, also known as Config Refresh, designed to enhance device security without the need for regular service check-ins.
1. Introduction
It’s always smart to keep an eye out for what’s new in Intune development. This time, something caught my attention.
ConfigRefresh was added to the in-development and, at that time, was only available for Windows Insiders!
The article above mentions that this config refresh feature will let you set a cadence (time frame) for Windows devices to reapply previously received policy settings without requiring devices to check in to Intune. Config Refresh sounds like magic!!
At first, I had the stupid idea that this feature would use the Windows Declared Configuration service because it looked and smelled like ConfigLock. ConfigLock seems to perform the same actions and could be the father of “ConfigRefresh,” in my opinion.
WinDC | MMP-C | SecuredCore | ConfigLock | WCOS | EPM (call4cloud.nl)
But then again, the Declared Configurations already had their dedicated schedule to refresh any setting on the device (Declared Configuration Policies like EPM settings) I guess it’s safe to assume the Config Refresh was the beta version of this WINDC refresh schedule.
https://call4cloud.nl/2023/07/the-windc-refresh-schedule-and-the-dudes
So, what else does Config Refresh use or abuse? I installed the latest Insider “canary” preview and started testing. After a few minutes, I noticed that the Enterprisecsps.dll only held one function: creating the node instance of the ConfigRefresh.
So, trying to enable the ConfigRefresh or trying to perform a get on the node will fail with the error status 404
Luckily last weekend I noticed that my Insider Canary Preview Windows VM just got updated to the latest build (25941.1000)
I immediately copied the enterprisecsps.dll to my own device and opened it with IDA. YES!!!! All the functions and related nodes are mentioned in it!
So, I guess Dano was right. 🙂 The required functions were included in the enterprisecsps.dll with the KB5037853 update. Let’s take a look at the famous Config Refresh!
2. Enable Config Refresh
When looking at the DMClient CSP, we can enable config refresh using a CSP or the settings catalog. When configuring config refresh with the settings catalog, just search for config refresh and make sure it’s enabled (not disabled)
But that wouldn’t be fun, right? Enabling it with a CSP and syncing the device with Intune will give me a lot of false information and a lot that is not related to ConfigRefresh. So I fired up a PowerShell MTA session in system context and fired off this SyncML message with the send-localmdmrequest command
This time no 404 error but an excellent and expected 200 status. Please note that I needed to use “replace” and not “add”…
While trying to enable ConfigRefresh manually, I was also already looking at the code, so I knew where to start looking.
When you enable config refresh, a new scheduled task named: “schedule created by DM client to refresh settings” will be created inside the Enterprisemgtmtnoncritical scheduled tasks folder. After clearing the garbage, I noticed the scheduled task to refresh settings was being created.
Besides this task being created, the “ConfigRefresh” registry key in the corresponding enrollment will also be set. You will spot the ConfigRefresh registry key inside the Intune enrollment GUID
I have a funny thing to add here: when ConfigRefresh was first released, this ConfigRefresh key was created in the DMClient key instead. Weird, isn’t it? Well, that was because a bug had been found. Please read my additional blog about that bug here:
Config Refresh Bug | Failed to Enroll | EmmDeviceID | Intune (call4cloud.nl)
Once the CSP enabled Config Refresh, I opened the scheduled tasks and started searching for that specific task. As shown below, there it is! Inside a new folder called EnterpriseMgtmNonCritical, a new task was created. (The same folder as in which the queued task was created when we remotely sync our device from Intune)
When we take a closer look at that task, we will notice that it (OF COURSE!!) uses fightclub, the device enroller, to trigger the /ConfigRefresh with some parameters. /o and the enrollmentguid that belongs to the Intune enrollment.
If we decide to take a closer look at the “triggers” we will notice that this scheduled task is repeated every 90 minutes
These 90 minutes correspond with the default cadence time from the DMClient CSP Docs
Of course, we can change them from 30-1440 minutes (but you could also change the scheduled task?)
But of course, that’s not allowed, and you are not an admin, right? Don’t do that in production! So before we are going to take a closer look at what happens when the scheduled task to refresh it all, we need to take a good look at how we could pause ConfigRefresh when we want to test something
3. Let’s pause the Refresh
When we look at the DMClient CSP I showed you earlier, we will notice that we can also pause the refresh for a while when we don’t want our policies refreshed. To do so, we need to configure the PausePeriod CSP. Hopefully, the settings catalog will also contain this option in the future.
./Device/Vendor/MSFT/DMClient/Provider/MS%20DM%20Server/ConfigRefresh/PausePeriod
If we configured this CSP with an integer value of 1440, the scheduled task created in the enterprisemgtnoncritical scheduled task folder would be postponed for….. yes, you guessed correctly! 1440 Minutes. When we examine the Config Refresh registry keys, we will notice that the PausePeriod has been set.
After the pause period has ended and the schedule to refresh the policies has been run, the deviceenroller.exe would kick out that registry key as if it never existed!
We could also spot this on the fly when we are running Procmon
Looking at what’s new in Intune, we will spot that we will have the option to perform a remote action to pause the config refresh enforcement! That sounds way better than creating a CSP to pause the refresh for a while!
Let’s take a look at the Intune Custom Roles we could define. We will also notice that we now have an option to disable the possibility of pause configuration refresh remotely!
Now we know how we can enable it/configure it and how we pause it, let’s find out how it behaves when we launch the scheduled task to refresh the policies
4. Launching the scheduled refresh task
Before launching the scheduled task, just like first, I wanted to know what to monitor. I opened another IDA session and opened the deviceenroller.exe
As shown above, after searching for the ConfigRefresh part, I stumbled upon a function inside the main one. This function first uses the known issue rollback/KIR (if GetCachedFeatureEnabledState is mentioned, I know there is something brand new being added.. The fun thing is, you can search for that keyword with IDA)
From there on, it imports a function from the PolicyManager called “RefreshAll”.
We will notice this by looking at Procmon. First, it will load the policymanager.dll. So, the real power behind ConfigRefesh lies in the RefreshAll function from the PolicyManager, not in the deviceenroller.exe! (which makes perfect sense)
Let’s open the policymanager.dll and start searching for RefreshAll. When taking a look at the RefreshAll function below, I noticed some things.
When the scheduled task is executed, it will try to find all the related policies that are set at the device and user level (GetActiveUserSid) in the Policymanager registry key
So by the looks of it, it only refreshes the policies configured in the PolicyManager\Current registry key…. So for example no Applocker Refresh! The deviceenroller.exe will look up all the providers and the corresponding ADMX settings and will “flag” them all as “dirty”!
After all the policies are flagged as dirty, it will start to search for all the “dirty” policies and delete all of them!! Yeah, all of them! I was also amazed that it would first get rid of all existing configured policies (values) even though there is nothing wrong with them.
I was expecting it would try to determine if there is a mismatch between the configured and the applied policies. Still, by the looks of it, it just trashes all of the policies and values and sets them again within a couple of milliseconds!
So after removing the OneDrive in the software\policies registry key as shown below, I fired off the scheduled task to refresh all settings, and, within a second or 2, the policies came back to life!
The funny thing is that I also tried it with some security-related settings mentioned in the ConfigLock I mentioned at the start of this blog post.
Secured-core configuration lock – Windows Client Management | Microsoft Learn
Guess what came back after clearing all of the Defender Security Center subkeys? Yeah, you guessed correctly!
Shall we look at the corresponding flow, i was just talking about before exploring the source of the refreshed policies?
5. The Flow
In this flow, I monitored the OneDrive KFMSilentOptin policy to determine the flow and what happens. Looking closely at the timeframe… within a couple of milliseconds, everything is refreshed!
- Queries policymanager\providers for all settings (cache with the last known good config policies?)
- Queries the policymanager\ADMXdefault and looks up all settings and in which registry key they are configured
- Flags the policies in the policymanager\current as dirty and detects if there are missing one
- Queries policies in the policymanager\providers for the lastwrite dword
- Refreshes (deletes/sets) the policy in the policymanager\current registry key (aka brings it back to life) and sets the ADMX instance data
- Refreshes (deletes/sets) the policy again in the software\policies registry node
6. Provider Policy Cache
And now I guess everyone is thinking the same. That’s a nice ProcMon flow, but can you explain better how ConfigRefresh knows what the policy looked like before it was deleted? There must be a cache, right? I moved this part to a different blog as it needed more explanation to tell the whole story about the provider’s cache.
Read the blog below for more details about the provider’s cache!
Config Refresh | Cache | Providers | Policymanager (call4cloud.nl)
Conclusion
It’s just refreshing! I love it! This refresh task doesn’t exactly use a desired state config, but it does the same thing. It will ensure the policies are refreshed on the device without contacting Intune!
A small side note: It looks like only policies that live in the PolicyManager and the corresponding PolicyCSP settings are refreshed
You are a mad man. nice.
Hahaha thanks ;)… the mad hatter to be precize 🙂
Hi Rudy, looks like a nice feature.
I can understand the need for making sure all machines are receiving and setting the same settings, like we are used to with GPO in AD.
Did you experience problems with Intune devices where this feature would have helped you / solved the issue?
We now have 700 machines enrolled, and so far they seam quite stable and not making problems by them self.
/Morten Wiingreen
Its more like an antitempering solution, to make sure that if somehow something bad happened on the device and some required policies are deleted, it could get back even when the device is offline.
And thats what problem it will solve 🙂
Great writeup as always. I wonder what it does for VPN configs, will it refresh those with the correct settings if they’re changed?
Crazy in depth! But even still i’m getting error 65000 when I assign the Config Refresh policy >.<
yep… there is an addtional blog that mentions this issue.. i will add a link to that blog in this blog later on today
Ah cheer, found your blog:
https://call4cloud.nl/2024/04/2024-03-update-config-refresh/#:~:text=Error%20code%2086000002%20can%20occur,Provider%2FMS%20DM%20Server%2F.
tl;dr fixed with the preview KB:
https://support.microsoft.com/nl-nl/topic/29-mei-2024-kb5037853-os-builds-22621-3672-en-22631-3672-preview-dcf14fd8-84d6-4234-9d5b-784c319cd7cf
Hi.. thanks.. yeah i already added it to the https://call4cloud.nl/2024/04/2024-03-update-config-refresh/ blog. I also added it on top of this blog also
Hey, ran into a problem with config refresh, and I think it’s to do with the user context that config refresh runs in.
I’ve been using the DriveMapping.admx Administrative Template to map some drives in a client environment, including a drive using a %username% variable.
When this profile is applied from Intune the first time, it sets the drive mapping to \\server\dir\Username without any problem. However as soon as Config Refresh runs, the drive mapping switches to \\server\dir\SYSTEM (which doesn’t exist of course).
This happens if I assign the Configuration Profile to a user group or device group. So far I haven’t found a fix for this, and it’s keeping me from using Config Refresh for this customer. Have you encountered this (or anything similar)? Any idea why the variable evaluation is different for the different processes?
Hi… Mmm i also have config refresh in place and that admx. And it seems to be still connected to the %username% variable after running the config refresh task
I assume the user is not a local admin on his device?
Yes the user is not a local admin.
Just to close the loop on this, after some troubleshooting Rudy pointed out to me that this problem seemed very similar to a problem he’s noted about the DriveMapping.admx file already:
https://call4cloud.nl/2021/03/willy-wonka-and-the-drive-letter-factory/#part6
I checked the ADMX I have deployed, and it had the provider flags set to 0, which lead to exactly the outcome described in his other blog post. After fixing this, Config Refresh + Drivemapping.admx works great!
Thanks Rudy!