Tags:
In general, I find working with the Windows Registry pretty frustrating. It's organized like a file system, but not as accessible. That is, until I discovered that you can treat the registry just like the file system in PowerShell. Almost.
If you want the TL/DR version; press End/FN+DownArrow and skip to the bottom of this article for a table summary of commands!
For this article, it's best if you practice the commands in all of the examples. Open a PowerShell session on Windows and enter the commands as shown to follow along and reinforce the concepts here.
To start, open PowerShell on Windows and run the Get-PSDrive cmdlet:
PS C:\Users\Sec504> Get-PSDrive Name Used (GB) Free (GB) Provider Root CurrentLocation ---- --------- --------- -------- ---- --------------- Alias Alias C 29.81 10.19 FileSystem C:\ Users\Sec504 Cert Certificate \ D FileSystem D:\ Env Environment Function Function HKCU Registry HKEY_CURRENT_USER HKLM Registry HKEY_LOCAL_MACHINE Variable Variable WSMan WSMan
In PowerShell we have PowerShell providers, ".NET programs that provide access to specialized data stores for easier viewing and management." (source: about_Providers) This includes the Windows Registry. We can access all of the registry data by accessing the top-level registry keys HKCU and HKLM (for HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE) as drive letters:
PS C:\Users\Sec504> Set-Location HKLM: PS HKLM:\>
BEHOLD! The Windows Registry.
List Registry Keys and Values
With the HKLM: and HKCU: drives, we can list the contents of registry keys using Get-ChildItem:
PS HKLM:\> Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion Hive: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion Name Property ---- -------- AccountPicture ActionCenter AdvertisingInfo Enabled : 0 App Management App Paths AppHost EnableWebContentEvaluation : 1 Applets ...
You may see the error Requested registry access is not allowed. in this output. This is because your current privileges cannot access the protected registry keys, and not a cause for alarm.
We can also use Set-Location (e.g., cd) to change to a working location:
PS HKLM:\> Set-Location HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion PS HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion> Get-ChildItem Hive: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion Name Property ---- -------- AccountPicture ActionCenter AdvertisingInfo Enabled : 0 App Management App Paths AppHost EnableWebContentEvaluation : 1 ...
When we run Get-ChildItem, we'll see both registry keys and values. If you only want to see subkeys, use Select-Object PSChildName in the pipeline:
PS HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion> Get-ChildItem | Select-Object PSChildName PSChildName ----------- AccountPicture ActionCenter AdvertisingInfo App Management App Paths AppHost
If you only want to see values but not sub-keys, use Get-ItemProperty (using the relative location . or the fully-qualified key location, shown here):
PS HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion> Get-ItemProperty . ProgramFilesDir : C:\Program Files CommonFilesDir : C:\Program Files\Common Files ProgramFilesDir (x86) : C:\Program Files (x86) CommonFilesDir (x86) : C:\Program Files (x86)\Common Files CommonW6432Dir : C:\Program Files\Common Files DevicePath : C:\WINDOWS\inf MediaPathUnexpanded : C:\WINDOWS\Media ProgramFilesPath : C:\Program Files ProgramW6432Dir : C:\Program Files SM_ConfigureProgramsName : Set Program Access and Defaults SM_GamesName : Games PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows PSChildName : CurrentVersion PSDrive : HKLM PSProvider : Microsoft.PowerShell.Core\Registry PS HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion> Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion ProgramFilesDir : C:\Program Files CommonFilesDir : C:\Program Files\Common Files ProgramFilesDir (x86) : C:\Program Files (x86) CommonFilesDir (x86) : C:\Program Files (x86)\Common Files CommonW6432Dir : C:\Program Files\Common Files DevicePath : C:\WINDOWS\inf ...
When enumerating registry values, you will see the values themselves (ProgramFilesDir, CommonFilesDir, etc., in this example, as well as several PowerShell properties beginning with PS.
If you want to see the value of a specific registry key value, use Get-ItemPropertyValue, specifying both the registry key (as a default argument, or with the -Path parameter), as well as the registry value name with the -Name parameter (again in this example I use the relative location . and the fully-qualified location to show how both can be used):
PS HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion> Get-ItemPropertyValue . -Name ProgramFilesDir C:\Program Files PS HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion> Get-ItemPropertyValue HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name ProgramFilesDir C:\Program Files
Create Registry Keys
Let's take a look at creating registry keys. We'll stick with the non-privileged PowerShell session, and create (then later, remove) a temporary registry key in HKEY_CURRENT_USER. First, change to the HKCU: drive provider and the SOFTWARE key, then list the sub-keys:
PS HKLM:\> Set-Location HKCU:\SOFTWARE PS HKCU:\SOFTWARE> Get-ChildItem | Select-Object -Property PSChildName PSChildName ----------- 7-Zip APN PIP AppDataLow Bogosoft Cygwin Google Intel JavaSoft Local AppWizard-Generated Applications Microsoft Monobob2022 ...
You can test if a registry key exists using Test-Path. Let's see how this looks; run Test-Path MyKey:
PS HKCU:\SOFTWARE> Test-Path MyKey False
To create the key, use New-Item with the -Path and -Name arguments.
PS HKCU:\SOFTWARE> New-Item -Path . -Name MyKey Hive: HKEY_CURRENT_USER\SOFTWARE Name Property ---- -------- MyKey PS HKCU:\SOFTWARE> Test-Path MyKey True
We used the relative location . here to specify the current location; you could optionally specify a fully-qualified path such as HKCU:\SOFTWARE if desired.
Set a Registry Value
Every registry key has a default value (this is a holdover from the days when a registry key could only hold one value per key. To specify a default value, use New-Item:
PS HKCU:\SOFTWARE> Set-Item -Path .\MyKey\ -Value "My default key value" PS HKCU:\SOFTWARE> Get-ItemProperty -Path .\MyKey\ (default) : My default key value PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\MyKey\ PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE PSChildName : MyKey PSDrive : HKCU PSProvider : Microsoft.PowerShell.Core\Registry
To add a new value in the key, use New-ItemProperty with the -Path, -Name, and -Value arguments:
PS HKCU:\SOFTWARE> New-ItemProperty -Path .\MyKey\ -Name MyCustomKeyValue -Value "My custom data" MyCustomKeyValue : My custom data PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\MyKey\ PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE PSChildName : MyKey PSDrive : HKCU PSProvider : Microsoft.PowerShell.Core\Registry PS HKCU:\SOFTWARE> Get-ItemProperty -Path .\MyKey\ (default) : My default key value MyCustomKeyValue : My custom data PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\MyKey\ PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE PSChildName : MyKey PSDrive : HKCU PSProvider : Microsoft.PowerShell.Core\Registry
So far, we've only been working with string objects. We can specify other data types, such as the DWORD integer type by adding -PropertyType:
PS HKCU:\SOFTWARE> New-ItemProperty -Path .\MyKey\ -Name MyCustomKeyValueDWORD -PropertyType DWORD -Value 12345 MyCustomKeyValueDWORD : 12345 PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\MyKey\ PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE PSChildName : MyKey PSDrive : HKCU PSProvider : Microsoft.PowerShell.Core\Registry PS HKCU:\SOFTWARE> Get-ItemProperty -Path .\MyKey\ (default) : My default key value MyCustomKeyValue : My custom data MyCustomKeyValueDWORD : 12345 PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\MyKey\ PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE PSChildName : MyKey PSDrive : HKCU PSProvider : Microsoft.PowerShell.Core\Registry
Delete a Registry Value
To delete a value in a registry key, use Remove-ItemProperty:
PS HKCU:\SOFTWARE> Remove-ItemProperty -Path .\MyKey\ -Name MyCustomKeyValueDWORD PS HKCU:\SOFTWARE> Get-ItemProperty -Path .\MyKey\ (default) : My default key value MyCustomKeyValue : My custom data PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\MyKey\ PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE PSChildName : MyKey PSDrive : HKCU PSProvider : Microsoft.PowerShell.Core\Registry PS HKCU:\SOFTWARE> Remove-ItemProperty -Path .\MyKey\ -Name MyCustomKeyValue PS HKCU:\SOFTWARE> Get-ItemProperty -Path .\MyKey\ (default) : My default key value PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\MyKey\ PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE PSChildName : MyKey PSDrive : HKCU PSProvider : Microsoft.PowerShell.Core\Registry
Excellent!
Delete a Registry Key
To clean up, let's remove the registry key MyKey with Remove-Item. I've added the -Confirm option for safety; you can delete the key without being prompted to confirm by omitting -Confirm.
Caution: Be careful about the path you specify when you remove a registry key! If you delete the wrong key, you could make the system unusable. Consider cutting-and-pasting the command shown below for safety.
PS HKCU:\SOFTWARE> Remove-Item .\MyKey\ -Confirm Confirm Are you sure you want to perform this action? Performing the operation "Remove Key" on target "Item: HKEY_CURRENT_USER\SOFTWARE\MyKey\". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): y PS HKCU:\SOFTWARE>
Search for a Registry Key
Next, let's take a look at the steps to search for a registry key. Let's search for a key named BrowserEmulation (associated with Microsoft Edge, which everyone will have on their Windows systems).
Unfortunately, not all drive providers support the same parameters. While searching for a file on the file system with Get-ChildItem is pretty straightforward (Get-ChildItem -Path C:\ -Name mimikatz.exe -Recurse will find all files with the name mimikatz.exe, for example), this won't work with registry keys:
PS HKCU:\SOFTWARE> Get-ChildItem -Recurse -Path . -Name "BrowserEmulation" Get-ChildItem : Cannot call method. The provider does not support the use of filters. At line:1 char:1 + Get-ChildItem -Recurse -Path . -Name "BrowserEmulation" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotImplemented: (:) [Get-ChildItem], PSNotSupportedException + FullyQualifiedErrorId : NotSupported,Microsoft.PowerShell.Commands.GetChildItemCommand
As an alternative, we can perform the recursive search for keys and use the pipeline to filter the results. This is not ideal for performance reasons, but it works reasonably well if you are patient:
PS HKCU:\SOFTWARE> Get-ChildItem -Recurse -Path . | Where-Object -Property Name -Like '*BrowserEmulation*' | Select-Object -Property PSPath PSPath ------ Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\BrowserEmulation Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\BrowserEmulation\LowMic Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\MicrosoftEdge\BrowserEmulation Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Storage\microsoft.microsoftedge_8wekyb3d8bbwe\MicrosoftEdge\BrowserEmulation Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Storage\microsoft.microsoftedge_8wekyb3d8bbwe\MicrosoftEdge\BrowserEmulat...
We use the wildcard BrowserEmulation here to match any portion of the Name property which will be the fully-qualified location string.
Search for a Registry Value Name
If you want to find a registry value by name, we can use a similar Get-ChildItem command, filtering by the Property property instead of Name. For example, to search for a registry value name called LastLogonTime-Machine, use the following command:
PS HKCU:\SOFTWARE> Get-ChildItem -Recurse -Path . | Where-Object -Property Property -EQ 'LastLogonTime-Machine' Hive: HKEY_CURRENT_USER\SOFTWARE\Microsoft Name Property ---- -------- EdgeUpdate LastLogonTime-Machine : 133009855555826276
TIP: We changed the Where-Property comparison operator from -Like to -EQ here, since we can match a complete value name. If you want to use a wildcard in your search for a value name, use -Like with the * wildcard instead.
Summary
Here's a summary of the commands we reviewed to access and manipulate the Windows Registry.
Task | Command |
---|---|
Change location to HKEY_CURRENT_USER | Set-Location HKCU: |
Change location to HKEY_LOCAL_MACHINE | Set-Location HKLM: |
List registry subkeys and values | Get-ChildItem |
List registry subkeys only | Get-ChildItem | Select-Object PSChildName |
List registry values only | Get-ItemProperty . |
Access the registry data for a specific value | Get-ItemPropertyValue (specify -Path and -Name) |
Test is a registry key exists | Test-Path |
Create a registry key | New-Item (specify -Path and -Name) |
Set a default registry key value | Set-Item (specify -Path and -Value, omitting -Name) |
Set a named registry key value | Set-Item (specify -Path, -Value, and -Name) |
Delete a registry value | Remove-ItemProperty (specify -Path and -Name) |
Delete a registry key | Remove-Item |
Search for a registry key | Get-ChildItem -Recurse (specify -Path and -Name where -Name uses wildcards) |
Search for a registry value name | Get-ChildItem -Recurse -Path . | Where-Object -Property Property -EQ 'SearchValueName' |
We'll continue to look at how to apply these commands to interrogate and manipulate the registry throughout the
#monthofpowershell.-Joshua Wright
Return to Getting Started With PowerShell
Joshua Wright is the author of SANS SEC504: Hacker Tools, Techniques, and Incident Handling, a faculty fellow for the SANS Institute, and a senior technical director at Counter Hack.