Use PowerShell to search for string in registry keys and values

后端 未结 2 1407
囚心锁ツ
囚心锁ツ 2021-01-13 19:14

I\'d like to use PowerShell to find all registry keys and values within a particular hive that contain a string foo, possibly embedded within a longer string. F

相关标签:
2条回答
  • 2021-01-13 19:51

    Each key has a GetValueNames(), GetValueKind(), and GetValue() method that let you enumerate child values. You can also use the GetSubKeyNames() instead of depending on Get-ChildItem -Recurse to enumerate keys.

    To answer your question about searching multiple hives: if you start with Get-ChildItem Registry::\, you can see all hives and start your search there. You'll probably want to stick with HKLM and HKCU (maybe HKU if there are other user hives loaded).

    Here's a sample implementation that I created a while back on the TechNet gallery:

    function Search-Registry { 
    <# 
    .SYNOPSIS 
    Searches registry key names, value names, and value data (limited). 
    
    .DESCRIPTION 
    This function can search registry key names, value names, and value data (in a limited fashion). It outputs custom objects that contain the key and the first match type (KeyName, ValueName, or ValueData). 
    
    .EXAMPLE 
    Search-Registry -Path HKLM:\SYSTEM\CurrentControlSet\Services\* -SearchRegex "svchost" -ValueData 
    
    .EXAMPLE 
    Search-Registry -Path HKLM:\SOFTWARE\Microsoft -Recurse -ValueNameRegex "ValueName1|ValueName2" -ValueDataRegex "ValueData" -KeyNameRegex "KeyNameToFind1|KeyNameToFind2" 
    
    #> 
        [CmdletBinding()] 
        param( 
            [Parameter(Mandatory, Position=0, ValueFromPipelineByPropertyName)] 
            [Alias("PsPath")] 
            # Registry path to search 
            [string[]] $Path, 
            # Specifies whether or not all subkeys should also be searched 
            [switch] $Recurse, 
            [Parameter(ParameterSetName="SingleSearchString", Mandatory)] 
            # A regular expression that will be checked against key names, value names, and value data (depending on the specified switches) 
            [string] $SearchRegex, 
            [Parameter(ParameterSetName="SingleSearchString")] 
            # When the -SearchRegex parameter is used, this switch means that key names will be tested (if none of the three switches are used, keys will be tested) 
            [switch] $KeyName, 
            [Parameter(ParameterSetName="SingleSearchString")] 
            # When the -SearchRegex parameter is used, this switch means that the value names will be tested (if none of the three switches are used, value names will be tested) 
            [switch] $ValueName, 
            [Parameter(ParameterSetName="SingleSearchString")] 
            # When the -SearchRegex parameter is used, this switch means that the value data will be tested (if none of the three switches are used, value data will be tested) 
            [switch] $ValueData, 
            [Parameter(ParameterSetName="MultipleSearchStrings")] 
            # Specifies a regex that will be checked against key names only 
            [string] $KeyNameRegex, 
            [Parameter(ParameterSetName="MultipleSearchStrings")] 
            # Specifies a regex that will be checked against value names only 
            [string] $ValueNameRegex, 
            [Parameter(ParameterSetName="MultipleSearchStrings")] 
            # Specifies a regex that will be checked against value data only 
            [string] $ValueDataRegex 
        ) 
    
        begin { 
            switch ($PSCmdlet.ParameterSetName) { 
                SingleSearchString { 
                    $NoSwitchesSpecified = -not ($PSBoundParameters.ContainsKey("KeyName") -or $PSBoundParameters.ContainsKey("ValueName") -or $PSBoundParameters.ContainsKey("ValueData")) 
                    if ($KeyName -or $NoSwitchesSpecified) { $KeyNameRegex = $SearchRegex } 
                    if ($ValueName -or $NoSwitchesSpecified) { $ValueNameRegex = $SearchRegex } 
                    if ($ValueData -or $NoSwitchesSpecified) { $ValueDataRegex = $SearchRegex } 
                } 
                MultipleSearchStrings { 
                    # No extra work needed 
                } 
            } 
        } 
    
        process { 
            foreach ($CurrentPath in $Path) { 
                Get-ChildItem $CurrentPath -Recurse:$Recurse |  
                    ForEach-Object { 
                        $Key = $_ 
    
                        if ($KeyNameRegex) {  
                            Write-Verbose ("{0}: Checking KeyNamesRegex" -f $Key.Name)  
    
                            if ($Key.PSChildName -match $KeyNameRegex) {  
                                Write-Verbose "  -> Match found!" 
                                return [PSCustomObject] @{ 
                                    Key = $Key 
                                    Reason = "KeyName" 
                                } 
                            }  
                        } 
    
                        if ($ValueNameRegex) {  
                            Write-Verbose ("{0}: Checking ValueNamesRegex" -f $Key.Name) 
    
                            if ($Key.GetValueNames() -match $ValueNameRegex) {  
                                Write-Verbose "  -> Match found!" 
                                return [PSCustomObject] @{ 
                                    Key = $Key 
                                    Reason = "ValueName" 
                                } 
                            }  
                        } 
    
                        if ($ValueDataRegex) {  
                            Write-Verbose ("{0}: Checking ValueDataRegex" -f $Key.Name) 
    
                            if (($Key.GetValueNames() | % { $Key.GetValue($_) }) -match $ValueDataRegex) {  
                                Write-Verbose "  -> Match!" 
                                return [PSCustomObject] @{ 
                                    Key = $Key 
                                    Reason = "ValueData" 
                                } 
                            } 
                        } 
                    } 
            } 
        } 
    } 
    

    I haven't looked at it in a while, and I can definitely see some parts of it that should be changed to make it better, but it should work as a starting point for you.

    0 讨论(0)
  • 2021-01-13 19:54

    This is a replacement for get-itemproperty that dumps out the registry in a simple manner. It's easy to use with where-object. You can also pipe it to set-itemproperty.

    function get-itemproperty2 {
      # get-childitem skips top level key, use get-item for that
      # set-alias gp2 get-itemproperty2
      param([parameter(ValueFromPipeline)]$key)
      process {
        $key.getvaluenames() | foreach-object {
          $value = $_
          [pscustomobject] @{
            Path = $Key -replace 'HKEY_CURRENT_USER',
              'HKCU:' -replace 'HKEY_LOCAL_MACHINE','HKLM:'
            Name = $Value
            Value = $Key.GetValue($Value)
            Type = $Key.GetValueKind($Value)
          }
        }
      }
    }
    
    
    ls -r hkcu:\key1 | get-itemproperty2 | where name -eq name
    
    Path            Name Value  Type
    ----            ---- -----  ----
    HKCU:\key1\key2 name     1 DWord
    
    
    ls -r hkcu:\key1 | get-itemproperty2 | where name -eq name | set-itemproperty -value 0
    ls -r hkcu:\key1 | get-itemproperty2 | where name -eq name
    
    Path            Name Value  Type
    ----            ---- -----  ----
    HKCU:\key1\key2 name     0 DWord
    
    
    # pipe 2 commands to one
    $(get-item hkcu:\key1; ls -r hkcu:\key1 ) | get-itemproperty2
    
    Path                 Name  Value               Type
    ----                 ----  -----               ----
    HKCU:\key1           multi {hi, there}  MultiString
    HKCU:\key1\key2      name  0                  DWord
    HKCU:\key1\key2      name2 0                 String
    HKCU:\key1\key2\key3 name3 {18, 52, 80}      Binary
    

    EDIT:

    This where construction isn't bad for searching both property names and values (and the key name is a value). (Watch out for Netbeans. It creates an invalid registry dword key that causes an exception in get-itemproperty.)

    get-childitem -recurse HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | 
      get-itemproperty | where { $_  -match 'Office16.PROPLUS' }
    
    0 讨论(0)
提交回复
热议问题