Skip to content

Instantly share code, notes, and snippets.

@zett42
Last active November 17, 2022 16:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zett42/dc87c4c6d1342ee9fa8a531f8e938307 to your computer and use it in GitHub Desktop.
Save zett42/dc87c4c6d1342ee9fa8a531f8e938307 to your computer and use it in GitHub Desktop.
List registry string values that unexpectedly contain embedded null characters
<#
.SYNOPSIS
List registry string values that unexpectedly contain embedded null characters.
.DESCRIPTION
Enumerates the given registry key recursively, outputting information about all registry string values (REG_SZ and REG_EXPAND_SZ)
that unexpectedly contain embedded null characters.
.PARAMETER Hive
The registry hive.
.PARAMETER View
The registry view.
.PARAMETER SubKey
Path of a sub key.
.OUTPUTS
An object with these properties:
RegPath = Full path of the current registry key
ValueName = Name of the current value
Value = Current value
ValueSZ = Current value, trimmed at first null character
ValueLen = Length of Value property
ValueSZLen = Length of ValueSZ property
.EXAMPLE
.\Get-RegStringsWithEmbeddedNull.ps1 -Hive CurrentUser -EA Ignore
.\Get-RegStringsWithEmbeddedNull.ps1 -Hive LocalMachine -View Registry32 -SubKey Software -EA Ignore
#>
[CmdletBinding()]
param (
[Parameter(Mandatory)] [Microsoft.Win32.RegistryHive] $Hive,
[Microsoft.Win32.RegistryView] $View = [Microsoft.Win32.RegistryView]::Default,
[string] $SubKey
)
Function Get-RegValuesRecursive( [Parameter(Mandatory)] [Microsoft.Win32.RegistryKey] $RegKey ) {
<#
.SYNOPSIS
Enumerate registry value names recursively
.DESCRIPTION
Enumerate registry keys and their values recursively.
For each registry value, an object containing the registry key and the value name is output.
.PARAMETER RegKey
Registry key where to start enumeration.
.OUTPUTS
An object with these properties:
[Microsoft.Win32.RegistryKey] $RegKey
[string] $ValueName
#>
class RegStackItem {
[Microsoft.Win32.RegistryKey] $RegKey
[bool] $HasValuesProcessed = $false
[Collections.Generic.List[string]] $SubKeyNames
[Collections.Generic.IEnumerator[string]] $SubKeyEnumerator
RegStackItem( [Microsoft.Win32.RegistryKey] $regKey ) {
$this.RegKey = $regKey
$this.SubKeyNames = $regKey.GetSubKeyNames()
$this.SubKeyEnumerator = $this.SubKeyNames.GetEnumerator()
}
}
class RegValueOutput {
[Microsoft.Win32.RegistryKey] $RegKey
[string] $ValueName
}
# Using a stack for better performance by avoiding recursive function calls, which are comparatively slow in PowerShell.
$stack = [Collections.Generic.Stack[RegStackItem]]::new()
$stack.Push( [RegStackItem]::new( $regKey ) )
:stackLoop while( $stack.Count ) {
$item = $stack.Peek()
if( -not $item.HasValuesProcessed ) {
$item.HasValuesProcessed = $true
try {
foreach( $valueName in $item.RegKey.GetValueNames() ) {
[RegValueOutput] @{ RegKey = $item.RegKey; ValueName = $valueName }
}
}
catch {
$PSCmdlet.WriteError( [Management.Automation.ErrorRecord]::new(
[Exception]::new("Could not get value names from registry key `"$($item.RegKey.Name)`"", $_.Exception ),
'GetRegValuesRecursiveError',
[Management.Automation.ErrorCategory]::ReadError,
$item.RegKey.Name
))
}
}
while( $item.SubKeyEnumerator.MoveNext() ) {
try {
$child = $item.RegKey.OpenSubKey( $item.SubKeyEnumerator.Current )
$stack.Push( [RegStackItem]::new( $child ) )
# "Recurse" into subkey
continue stackLoop
}
catch {
$subKeyPath = Join-Path $item.RegKey.Name $item.SubKeyEnumerator.Current
$PSCmdlet.WriteError( [Management.Automation.ErrorRecord]::new(
[Exception]::new("Could not open registry sub key `"$subKeyPath`"", $_.Exception ),
'GetRegValuesRecursiveError',
[Management.Automation.ErrorCategory]::OpenError,
$subKeyPath
))
}
}
$null = $stack.Pop()
}
}
$regKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey( $Hive, $View )
if( $SubKey ) {
$regKey = $regKey.OpenSubKey( $subKey )
}
Get-RegValuesRecursive $regKey | & { process {
if( $_.RegKey.GetValueKind( $_.ValueName ) -in 'String', 'ExpandString' ) {
$value = $_.RegKey.GetValue( $_.ValueName )
if( ( $nullPos = $value.IndexOf( [char] 0 ) ) -ge 0 ) {
$valueSZ = $value.SubString( 0, $nullPos )
[PSCustomObject]@{
RegPath = $_.RegKey.Name
ValueName = $_.ValueName
Value = $value
ValueSZ = $valueSZ
ValueLen = $value.Length
ValueSZLen = $valueSZ.Length
}
}
}
}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment