mirror of
				https://github.com/NetSPI/PowerHuntShares.git
				synced 2025-11-04 05:24:51 +01:00 
			
		
		
		
	Update PowerHuntShares.psm1
Added cisco startup / running config parser, and type7 encoder/decoder.
This commit is contained in:
		@@ -4,7 +4,7 @@
 | 
			
		||||
#--------------------------------------
 | 
			
		||||
# Author: Scott Sutherland, 2024 NetSPI
 | 
			
		||||
# License: 3-clause BSD
 | 
			
		||||
# Version: v1.143
 | 
			
		||||
# Version: v1.144
 | 
			
		||||
# References: This script includes custom code and code taken and modified from the open source projects PowerView, Invoke-Ping, and Invoke-Parrell. 
 | 
			
		||||
function Invoke-HuntSMBShares
 | 
			
		||||
{    
 | 
			
		||||
@@ -1539,6 +1539,8 @@ function Invoke-HuntSMBShares
 | 
			
		||||
        $FileNamePatternsAll.Rows.Add("jboss-logmanager.properties*","","None.","Secret","")                 | Out-Null
 | 
			
		||||
        $FileNamePatternsAll.Rows.Add("jenkins.model.JenkinsLocationConfiguration.*","","None.","Secret","") | Out-Null
 | 
			
		||||
        $FileNamePatternsAll.Rows.Add("machine.config*","","None.","Secret","Get-PwMachineConfig")           | Out-Null
 | 
			
		||||
	$FileNamePatternsAll.Rows.Add("startup*","","None.","Secret","Get-PwCiscoConfig")                    | Out-Null
 | 
			
		||||
 	$FileNamePatternsAll.Rows.Add("running*","","None.","Secret","Get-PwCiscoConfig")                    | Out-Null
 | 
			
		||||
        $FileNamePatternsAll.Rows.Add("my.*","","None.","Secret","Get-PwMySQLConfig")                        | Out-Null
 | 
			
		||||
        $FileNamePatternsAll.Rows.Add("mysql.user*","","None.","Secret","")                                  | Out-Null
 | 
			
		||||
        $FileNamePatternsAll.Rows.Add("nginx.conf*","","None.","Secret","")                                  | Out-Null
 | 
			
		||||
@@ -26271,3 +26273,236 @@ function Get-PrivateKeyFilePath {
 | 
			
		||||
 | 
			
		||||
    return $result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Author: Scott Sutherland, NetSPI (@_nullbind / nullbind)
 | 
			
		||||
# Intended input: cisco configurations files (startup/run)
 | 
			
		||||
function  Get-PwCiscoConfig {
 | 
			
		||||
    param (
 | 
			
		||||
        [string]$ComputerName = $null,   # Optional
 | 
			
		||||
        [string]$ShareName    = $null,   # Optional
 | 
			
		||||
        [string]$UncFilePath  = $null,   # Optional
 | 
			
		||||
        [string]$FileName     = $null,   # Optional
 | 
			
		||||
        [string]$FilePath                # Required
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # Cisco Type 7 encryption key 
 | 
			
		||||
    $xlat = @(
 | 
			
		||||
        0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f, 0x41, 0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72, 0x6b, 0x6c, 0x64,
 | 
			
		||||
        0x4a, 0x4b, 0x44, 0x48, 0x53, 0x55, 0x42, 0x73, 0x67, 0x76, 0x63, 0x61, 0x36, 0x39, 0x38, 0x33, 0x34, 0x6e, 0x63,
 | 
			
		||||
        0x78, 0x76, 0x39, 0x38, 0x37, 0x33, 0x32, 0x35, 0x34, 0x6b, 0x3b, 0x66, 0x67, 0x38, 0x37
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # Cisco Type 7 Password Decoder
 | 
			
		||||
    function Decode-Type7 {
 | 
			
		||||
        param (
 | 
			
		||||
            [string]$EncodedPassword
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # Initialize decoded password
 | 
			
		||||
        $decodedPassword = ''
 | 
			
		||||
 | 
			
		||||
        # Extract the seed and the encrypted portion
 | 
			
		||||
        $seed = [convert]::ToInt32($EncodedPassword.Substring(0, 2))  # The first two characters as the seed
 | 
			
		||||
        $encryptedPart = $EncodedPassword.Substring(2)
 | 
			
		||||
 | 
			
		||||
        # Loop through the encrypted part and decrypt each byte
 | 
			
		||||
        for ($i = 0; $i -lt $encryptedPart.Length; $i += 2) {
 | 
			
		||||
            $currentByte = HexToInt $encryptedPart.Substring($i, 2)
 | 
			
		||||
            $decodedChar = [char]($currentByte -bxor $xlat[$seed])
 | 
			
		||||
            $decodedPassword += $decodedChar
 | 
			
		||||
            $seed = ($seed + 1) % $xlat.Length  # Reset seed if it reaches 51
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $decodedPassword
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Read the file content
 | 
			
		||||
    $fileContent = Get-Content -Path $FilePath
 | 
			
		||||
 | 
			
		||||
    # Regex patterns for different password types and usernames
 | 
			
		||||
    $regexEnablePassword = '(?<=enable password\s)(\d*)\s*([^\s]+)'        # Matches enable password (cleartext or encoded)
 | 
			
		||||
    $regexEnableSecret = '(?<=enable secret\s5\s)([^\s]+)'                 # Matches enable secret 5 (encrypted password)
 | 
			
		||||
    $regexUsernamePassword = 'username\s([^\s]+)\s(?:password|secret)\s(\d)\s([^\s]+)'  # Matches username passwords (cleartext, encrypted, or encoded)
 | 
			
		||||
    $regexGeneralPassword = '(?<=password\s)(\d*)\s*([^\s]+)'              # Matches generic password lines, including ones without type indicator
 | 
			
		||||
    $regexConsolePassword = '(?<=line con 0\s+password\s)(\d*)\s*([^\s]+)' # Matches console passwords
 | 
			
		||||
    $regexSnmpCommunity = 'snmp-server community\s([^\s]+)\s(RO|RW)'       # Matches SNMP community strings
 | 
			
		||||
    $regexWpaPsk = 'wpa-psk ascii 0\s([^\s]+)'                             # Matches WPA PSK Wi-Fi passwords
 | 
			
		||||
 | 
			
		||||
    # Array to store the parsed objects
 | 
			
		||||
    $parsedPasswords = @()
 | 
			
		||||
 | 
			
		||||
    foreach ($line in $fileContent) {
 | 
			
		||||
        $object = [PSCustomObject]@{
 | 
			
		||||
            ComputerName = $ComputerName
 | 
			
		||||
            ShareName    = $ShareName
 | 
			
		||||
            UncFilePath  = $UncFilePath
 | 
			
		||||
            FileName     = $FileName
 | 
			
		||||
            Section      = "NA"
 | 
			
		||||
            ObjectName   = 'Secret'
 | 
			
		||||
            TargetURL    = "NA"
 | 
			
		||||
            TargetServer = "NA"
 | 
			
		||||
            TargetPort   = "NA"
 | 
			
		||||
            Database     = "NA"
 | 
			
		||||
            Domain       = "NA"
 | 
			
		||||
            Username     = "NA"
 | 
			
		||||
            Password     = "NA"
 | 
			
		||||
            PasswordEnc  = "NA"
 | 
			
		||||
            KeyFilePath  = "NA"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # Check for Enable secret 5 (encrypted, non-decodable)
 | 
			
		||||
        if ($line -match $regexEnableSecret) {
 | 
			
		||||
            $object.PasswordEnc = $matches[1].Trim()
 | 
			
		||||
            $object.ObjectName = "EnableSecret (MD5 Encrypted)"
 | 
			
		||||
            $parsedPasswords += $object
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # Check for Enable password (cleartext or Type 7)
 | 
			
		||||
        if ($line -match $regexEnablePassword) {
 | 
			
		||||
            if ($matches[1] -eq "0" -or !$matches[1]) {  # Handle both cleartext and cases without type indicator
 | 
			
		||||
                $object.Password = $matches[2].Trim()
 | 
			
		||||
                $object.ObjectName = "EnablePassword (Cleartext)"
 | 
			
		||||
            }
 | 
			
		||||
            elseif ($matches[1] -eq "7") {
 | 
			
		||||
                $encodedPassword = $matches[2].Trim()
 | 
			
		||||
                $decodedPassword = Decode-Type7 -EncodedPassword $encodedPassword
 | 
			
		||||
                $object.Password = $decodedPassword
 | 
			
		||||
                $object.PasswordEnc = $encodedPassword
 | 
			
		||||
                $object.ObjectName = "EnablePassword (Type 7 Decrypted)"
 | 
			
		||||
            }
 | 
			
		||||
            $parsedPasswords += $object
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # Check for Username passwords (cleartext, Type 7, or secret 5/MD5)
 | 
			
		||||
        if ($line -match $regexUsernamePassword) {
 | 
			
		||||
            $object.Username = $matches[1].Trim()
 | 
			
		||||
            if ($matches[2] -eq "0") {
 | 
			
		||||
                $object.Password = $matches[3].Trim()
 | 
			
		||||
                $object.ObjectName = "Username Password (Cleartext)"
 | 
			
		||||
            }
 | 
			
		||||
            elseif ($matches[2] -eq "7") {
 | 
			
		||||
                $encodedPassword = $matches[3].Trim()
 | 
			
		||||
                $decodedPassword = Decode-Type7 -EncodedPassword $encodedPassword
 | 
			
		||||
                $object.Password = $decodedPassword
 | 
			
		||||
                $object.PasswordEnc = $encodedPassword
 | 
			
		||||
                $object.ObjectName = "Username Password (Type 7 Decrypted)"
 | 
			
		||||
            }
 | 
			
		||||
            elseif ($matches[2] -eq "5") {
 | 
			
		||||
                # MD5 encrypted password (not decodable)
 | 
			
		||||
                $object.PasswordEnc = $matches[3].Trim()
 | 
			
		||||
                $object.ObjectName = "Username Password (MD5 Encrypted)"
 | 
			
		||||
            }
 | 
			
		||||
            $parsedPasswords += $object
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # Check for General password lines (cleartext or Type 7)
 | 
			
		||||
        if ($line -match $regexGeneralPassword) {
 | 
			
		||||
            if ($matches[1] -eq "0" -or !$matches[1]) {  # Handle both cleartext and cases without type indicator
 | 
			
		||||
                $object.Password = $matches[2].Trim()
 | 
			
		||||
                $object.ObjectName = "Password (Cleartext)"
 | 
			
		||||
            }
 | 
			
		||||
            elseif ($matches[1] -eq "7") {
 | 
			
		||||
                $encodedPassword = $matches[2].Trim()
 | 
			
		||||
                $decodedPassword = Decode-Type7 -EncodedPassword $encodedPassword
 | 
			
		||||
                $object.Password = $decodedPassword
 | 
			
		||||
                $object.PasswordEnc = $encodedPassword
 | 
			
		||||
                $object.ObjectName = "Password (Type 7 Decrypted)"
 | 
			
		||||
            }
 | 
			
		||||
            $parsedPasswords += $object
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # Check for Console password (cleartext or Type 7)
 | 
			
		||||
        if ($line -match $regexConsolePassword) {
 | 
			
		||||
            if ($matches[1] -eq "0" -or !$matches[1]) {  # Handle both cleartext and cases without type indicator
 | 
			
		||||
                $object.Password = $matches[2].Trim()
 | 
			
		||||
                $object.ObjectName = "ConsolePassword (Cleartext)"
 | 
			
		||||
            }
 | 
			
		||||
            elseif ($matches[1] -eq "7") {
 | 
			
		||||
                $encodedPassword = $matches[2].Trim()
 | 
			
		||||
                $decodedPassword = Decode-Type7 -EncodedPassword $encodedPassword
 | 
			
		||||
                $object.Password = $decodedPassword
 | 
			
		||||
                $object.PasswordEnc = $encodedPassword
 | 
			
		||||
                $object.ObjectName = "ConsolePassword (Type 7 Decrypted)"
 | 
			
		||||
            }
 | 
			
		||||
            $parsedPasswords += $object
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # Check for SNMP community strings (public/private with RO/RW)
 | 
			
		||||
        if ($line -match $regexSnmpCommunity) {
 | 
			
		||||
            $object.Password = $matches[1].Trim()
 | 
			
		||||
            $object.ObjectName = "SNMP Community String ($($matches[2]))"
 | 
			
		||||
            $parsedPasswords += $object
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # Check for WPA PSK Wi-Fi passwords (cleartext)
 | 
			
		||||
        if ($line -match $regexWpaPsk) {
 | 
			
		||||
            $object.Password = $matches[1].Trim()
 | 
			
		||||
            $object.ObjectName = "Wi-Fi WPA Pre-Shared Key (Cleartext)"
 | 
			
		||||
            $parsedPasswords += $object
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # Output the results
 | 
			
		||||
    return $parsedPasswords
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
<# Cisco Configuration Bonus Functions - PowerShell Type 7 Encoder/Decoder
 | 
			
		||||
 | 
			
		||||
# Cisco Type 7 encryption key 
 | 
			
		||||
$xlat = @(
 | 
			
		||||
    0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f, 0x41, 0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72, 0x6b, 0x6c, 0x64,
 | 
			
		||||
    0x4a, 0x4b, 0x44, 0x48, 0x53, 0x55, 0x42, 0x73, 0x67, 0x76, 0x63, 0x61, 0x36, 0x39, 0x38, 0x33, 0x34, 0x6e, 0x63,
 | 
			
		||||
    0x78, 0x76, 0x39, 0x38, 0x37, 0x33, 0x32, 0x35, 0x34, 0x6b, 0x3b, 0x66, 0x67, 0x38, 0x37
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Helper function to convert hex string to int
 | 
			
		||||
function HexToInt($hexStr) {
 | 
			
		||||
    return [convert]::ToInt32($hexStr, 16)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Cisco Type 7 Password Decoder
 | 
			
		||||
function Decode-Type7 {
 | 
			
		||||
    param (
 | 
			
		||||
        [string]$EncodedPassword
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # Initialize decoded password
 | 
			
		||||
    $decodedPassword = ''
 | 
			
		||||
 | 
			
		||||
    # Extract the seed and the encrypted portion
 | 
			
		||||
    $seed = [convert]::ToInt32($EncodedPassword.Substring(0, 2))  # The first two characters as the seed
 | 
			
		||||
    $encryptedPart = $EncodedPassword.Substring(2)
 | 
			
		||||
 | 
			
		||||
    # Loop through the encrypted part and decrypt each byte
 | 
			
		||||
    for ($i = 0; $i -lt $encryptedPart.Length; $i += 2) {
 | 
			
		||||
        $currentByte = HexToInt $encryptedPart.Substring($i, 2)
 | 
			
		||||
        $decodedChar = [char]($currentByte -bxor $xlat[$seed])
 | 
			
		||||
        $decodedPassword += $decodedChar
 | 
			
		||||
        $seed = ($seed + 1) % $xlat.Length  # Reset seed if it reaches 51
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $decodedPassword
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Cisco Type 7 Password Encoder
 | 
			
		||||
function Encode-Type7 {
 | 
			
		||||
    param (
 | 
			
		||||
        [string]$PlainPassword
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # Generate random seed between 0 and 15
 | 
			
		||||
    $seed = Get-Random -Minimum 0 -Maximum 15
 | 
			
		||||
    $encodedPassword = "{0:D2}" -f $seed  # Append seed in two-digit format
 | 
			
		||||
 | 
			
		||||
    # Encrypt each character
 | 
			
		||||
    for ($i = 0; $i -lt $PlainPassword.Length; $i++) {
 | 
			
		||||
        $charValue = [byte][char]$PlainPassword[$i]
 | 
			
		||||
        $encodedByte = $charValue -bxor $xlat[$seed]
 | 
			
		||||
        $encodedPassword += "{0:X2}" -f $encodedByte
 | 
			
		||||
        $seed = ($seed + 1) % $xlat.Length  # Reset seed if it reaches 51
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return $encodedPassword
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user