The HKCU Registry Bridge On the River PowerShell.

Last Updated on February 21, 2023 by rudyooms

This blog will show you the options you have when you need to deploy Hkey_Current_User (HKCU) Registry changes when you are blocking PowerShell!

I will divide this blog into multiple parts

  1. Introduction
  2. Using Reg.exe
  3. ProActive Remediations
  4. PowerShell Script
  5. Conclusion

1. Introduction

When you are blocking PowerShell in the user context with Applocker, deploying HKCU registry changes could be difficult! Why? Because when running a PowerShell script or a Proactive Remediation as the logged-in user, it will be blocked!

As shown below, you will notice the error 0x8004005 in your agentexecutor.log mentioning that the program is blocked by group policy.

So how are we going to solve this issue because sometimes you really want to push a simple HKEY_Current_User (HKCU) setting that isn’t available in the Intune Settings Catalog or Administrative templates?

As an example: When you are using OneDrive and you configured the settings to Automount team sites and you want to speed things up a little bit

Normally that is not a problem when you are NOT blocking PowerShell.The only thing you need to do is to configure the “Run this script using the logged-on credentials” option to “yes”

But in my opinion.. not blocking PowerShell for the non-admins is a no-go. It’s just my opinion but if you want to read more about this…

If you have read the blog above you will know why I prefer to block PowerShell. It’s because malware/cryptoware/privilege escalation uses most of the time Powershell. And a normal user.. does not need access to PowerShell (except for loading user scripts.…)

So how can you make sure a user always gets the registry keys necessary? We also need to beware of the fact, the TimerAutoMount key will be reset, when OneDrive has successfully mounted the Sharepoint sites. So we need to have a solution that changes this key for each logon or each hour

I will show you the options we have got:

2. Using Reg.exe

I know deploying a PowerShell script in Intune is very simple to do… this is a little bit different. This is the PowerShell script that needs to be run in the system context instead of the user context, which you normally do when you want to deploy an HKCU key.

PowerShell Script:

$content = @'
 Windows Registry Editor Version 5.00
 [HKEY_CURRENT_USER\Software\Microsoft\OneDrive]
 "Test"=dword:00000001
 '@

$path = $(Join-Path $env:ProgramData CustomScripts)
 if (!(Test-Path $path))
 {
 New-Item -Path $path -ItemType Directory -Force -Confirm:$false
 }
 Out-File -FilePath $(Join-Path $env:ProgramData CustomScripts\onedrive.reg) -Encoding unicode -Force -InputObject $content -Confirm:$false

$WshShell = New-Object -comObject WScript.Shell
 $Shortcut = $WshShell.CreateShortcut("$env:ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\config.lnk")
 $Shortcut.TargetPath = '"c:\windows\System32\reg.exe"'
 $Shortcut.Arguments = "import c:\programdata\CustomScripts\onedrive.reg"
 $Shortcut.WorkingDirectory = '"c:\programdata\CustomScripts\"'
 $Shortcut.Save()

As shown above, you can see I just make use of reg.exe to import the .reg file and create a shortcut to all user’s startup folders to make sure this reg file is imported on startup.

You can also create an intunewin installer to make sure this is done when the device is deployed to Azure ad for the first time.

Please note: You can’t change/add/remove a registry key in the HKEY_CURRENT_USER\Software\Policies path. It will not work, because it would be very weird if you could change the policies that have been applied as a regular user!

3. ProActive Remediations

A way better option than the reg.exe option would be to use Proactive remediations. So let’s do some magic with the use of ProActive remediations. If you want to see my other ideas with ProActive Remediations…

https://call4cloud.nl/category/proactive-remediations/

But how are we going to make sure we can read the TimerAutoMount key in the HKEY_Current_User registry section when running the remediations in a system context?

Because when we don’t know which user to look for… how are we going to change that setting? Here is how!

Detection Script:

New-PSDrive HKU Registry HKEY_USERS | out-null
$user = get-wmiobject -Class Win32_Computersystem | select Username;
$sid = (New-Object System.Security.Principal.NTAccount($user.UserName)).Translate([System.Security.Principal.SecurityIdentifier]).value;
$key = "HKU:\$sid\Software\Microsoft\OneDrive\Accounts\Business1"
$val = (Get-Item "HKU:\$sid\Software\Microsoft\OneDrive\Accounts\Business1");
$Timer = $val.GetValue("TimerAutoMount");

##################################
#Launch Timer Detection         #
##################################

if($Timer -ne 1)
{
    Write-Host "TimerAutoMount Needs to be changed!"
    Exit 1
}
else
{
    Write-Host "TimerAutoMount doesn't need to be changed"
    Exit 0
}

Remediation Script

New-PSDrive HKU Registry HKEY_USERS | out-null
$user = get-wmiobject -Class Win32_Computersystem | select Username;
$sid = (New-Object System.Security.Principal.NTAccount($user.UserName)).Translate([System.Security.Principal.SecurityIdentifier]).value;
$key = "HKU:\$sid\Software\Microsoft\OneDrive\Accounts\Business1"
$val = (Get-Item "HKU:\$sid\Software\Microsoft\OneDrive\Accounts\Business1") | out-null
$reg = Get-Itemproperty -Path $key -Name TimerAutoMount -erroraction 'silentlycontinue'

##################################
#Launch timer  detection       #
##################################

if(-not($reg))
	{
		Write-Host "Registry key didn't exist, creating it now"
                New-Itemproperty -path $Key -name "TimerAutoMount" -value "1"  -PropertyType "qword" | out-null
		exit 1
	} 
else
	{
 		Write-Host "Registry key changed to 1"
		Set-ItemProperty  -path $key -name "TimerAutomount" -value "1" | out-null
		Exit 0  
	}
 

Go open the ProActive Remediations and take a look at the outcome!

And yes, of course, it has been remediated!

Isn’t this cool? With this solution, you could change the user registry key each hour (when it’s not configured to 1).

Do you know what else is great? When you don’t want a policy to be targeted at the device (HKLM:\software\policies) maybe you could even change HKCU:\software\policies settings with this idea.

4. PowerShell Script

Another option to get the current logged-in Azure Ad user would be to query the User who is running Explorer.exe and convert that username to the well-known SID to change the registry values! To be sure I am getting the only correct username I am using a word boundary -match “\b$CurrentUser\b” to perform a search for “whole words only”

$currentUser = (Get-Process -IncludeUserName -Name explorer | Select-Object -First 1 | Select-Object -ExpandProperty UserName).Split("\")[1] 

$Data = $currentUser
$Keys = GCI "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\" -Recurse
Foreach($Key in $Keys){
    IF(($key.GetValueNames() | %{$key.GetValue($_)}) -match "\b$CurrentUser\b" ){$sid = $key}
}

$sid = $sid.pschildname

New-PSDrive HKU Registry HKEY_USERS | out-null
$key = "HKU:\$sid\Software\Microsoft\OneDrive\Accounts\Business1"
set-Itemproperty -path $Key -name "TimerAutoMount" -value "1" | out-null

If you don’t want to rely on who has the process explorer.exe opened or having multiple SIDs in the OUTPUT we could also call upon the registry to directly fetch the LastLoggedOnUserSID

$sid = (Get-ItemProperty -Path hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI -Name LastLoggedOnUserSID).LastLoggedOnUserSID

New-PSDrive HKU Registry HKEY_USERS | out-null
$key = "HKU:\$sid\Software\Microsoft\OneDrive\Accounts\Business1"
set-Itemproperty -path $Key -name "TimerAutoMount" -value "1" | out-null

Conclusion:

Blocking Powershell is very important but it can put you in a difficult situation when you need to change some HKCU settings… Because it could be hard to apply the settings to the logged-in user and not to the system account!

Deploy 1 of these ideas and watch it pour down to the devices!

Funny Animated The Simpsons Gifs

Of course, you will know I prefer the pro-active remediations…. they are great!

19 thoughts on “The HKCU Registry Bridge On the River PowerShell.

  1. Pingback: Once upon a time in the automount of OneDrive team sites - Call4Cloud
  2. Hi
    I have tried to implement this using intunewin and System install behavior, but it fails to run.
    I have tested running the script on my Windows 10 lab PC and it does work.
    I am using the following command in the Win32 App config to run the ps1 file:
    powershell.exe -executionpolicy bypass -Windowstyle Hidden -file “.\Test.ps1.ps1”
    Can you please assist?

    1. Hi

      I have created an install.cmd inside the folder where the powershell script is located.

      install.cmd content:
      powershell.exe -executionpolicy bypass -command “& ‘.\Windows10_Onedrive.ps1′”

      The install.cmd is called upon in the install command inside intune

  3. I’m thinking about a better way to get the remediation reporting success.

    If we change both exits to 0, or just removed them, and then added another check like

    $Timer = $val.GetValue(“TimerAutoMount”)

    if($Timer -ne 1)
    {
    Write-Host “TimerAutoMount hasn’t been changed”
    Exit 1
    }
    else
    {
    Write-Host “TimerAutoMount has been changed”
    Exit 0
    }

    Do you think that would work to show actual success or failure?

  4. Re: 4. The Powershell Script

    I believe this is still missing New-PSDrive at the start to set up the HKU reference, it isn’t available by default in a Powershell sessions.

    And for getting the SID, the current -Match statement returns only the last hit, while it can give multiple hits in a row (partial matches), so it cannot guarantee to get the right SID if a machine has a bunch of userprofiles on it with similar names.
    %{$Profile.GetValue($_)}) -match “\b$CurrentUser\b” makes it only return an exact match instead.

    1. Hi,

      True.. the New-psdrive needed to be added. I guess I didn’t closed my previous powershell session … But you are totally right about the $currenuser part is better to use word boundaries like your example -match “\b$CurrentUser\b”

      Updated the blog

    2. This PowerShell detection method is the foundation of many Intune app deployments and I love you for providing this to the community. It worked well, until it didn’t. I managed to debug where the problem is but I lack the PowerShell skillz to enhance the script to counter this scenario. LEt me set up the scene:
      John Doe is logged in.
      $currentUser variable gets the correct user name John.Doe
      Due to various reasons, there are 2 SID’s for John and Foreach($Key in $Keys) will return 2 matches, John.Doe and John.Doe.DOMAIN.
      For reasons I cant decode from the script, -match “\b$CurrentUser\b” returns the SID for John.Doe.DOMAIN, which is the incorrect one.
      How should the script be changed, so the returned SID would be for John.Doe not John.Doe.DOMAIN?

      1. Mmm .. i get it… not sure if this would work… but just looping through the sids and setting that timer for all sids instead?

        $currentUser = (Get-Process -IncludeUserName -Name explorer | Select-Object -First 1 | Select-Object -ExpandProperty UserName).Split(“\”)[1]

        $Data = $currentUser
        $Keys = GCI “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\” -Recurse
        Foreach($Key in $Keys){
        IF(($key.GetValueNames() | %{$key.GetValue($_)}) -match “\b$CurrentUser\b” ){$sids = $key}
        }

        Foreach($sid in $sids){
        $sids = $sids.pschildname
        remove-psdrive HKU | out-null
        New-PSDrive HKU Registry HKEY_USERS | out-null
        $key = “HKU:\$sids\Software\Microsoft\OneDrive\Accounts\Business1”
        set-Itemproperty -path $Key -name “TimerAutoMount” -value “1” | out-null
        }

        1. Another option would be to fetch the sid directly from
          HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI

          LastLoggedOnUserSID

          $sid = (Get-ItemProperty -Path hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI -Name LastLoggedOnUserSID).LastLoggedOnUserSID

      2. Thanks for the reply’s!
        I figured it out and the correct answer is:
        -match “\b$CurrentUser\b” -notmatch “\b$CurrentUser.DOMAIN\b”
        This will return John.Doe and not John.Doe.DOMAIN, handy in a AD to AAD migrated scenario.

  5. Hi,
    I’ve just found this, really like it. One thing that kind of bothers me though is that further executions of the script will generate an error as the drive ‘HKU’ will already exist – is there merit to checking for existence of the drive with an exit return so that there’s no errors at all?

  6. Pingback: Simon does... How to use Intune to enable sensitivity labels on PDF files
  7. Hi,

    Here’s a little puzzle I’m currently tackling: I’m noodling around with HKCU Settings, specifically trying to manipulate HKU:\$userSID\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer, within a Multi-Session AVD environment. My mission is to set specific settings that aren’t quite yet supported by Intune within the AVD Multi Session framework.

    Your article and approach are brilliant, but here’s the hitch: since the script runs in the system context, it’s not performing cleanly in a Multi-Session environment. Ideally, the keys should be set instantly upon each user login. Have you, by any chance, juggled with this scenario before?

  8. Thanks for the very helpful article!

    I’m trying to think of a way where we can deploy a registry key to disable Copilot on the device with a local standard user right.

    This is the script that I ran:

    New-Item -Path HKCU:\Software\Policies\Microsoft\Windows\WindowsCopilot
    New-ItemProperty -Path HKCU:\Software\Policies\Microsoft\Windows\WindowsCopilot -Name TurnOffWindowsCopilot -PropertyType DWord -Value 1

    It worked perfectly when the users are local admins, but not standard users unfortunately. (Run this script using the logged on credentials: Yes)

    It would be appreciated if we can have it configured!

    1. Yeah … configuring the policies from the hkcu, in the hkcu isnt going to cut it… you will need to run it as system and finding te logged in user (sid) and change the key in the hkey_users\sid …

Leave a Reply

Your email address will not be published. Required fields are marked *

  +  78  =  86