Detect SMB1 version via powershell for all OSes

-3

My workflow:

  • check if server is pingable
  • find if they are domain connected or not and perform a task accordingly. if Operating system 2012 and/or R2 ,2016 or 2019 newer OSes then I will run Get-SmbServerConfiguration cmdlet. if machine is not a part of default domain then else block will run.
  • if Operating system 2003 or 2008 oldest OSes then I will run Get-Wmi cmdlet. if machine is not a part of default domain then else block will run.

Finally , I will concentanate $results variable.

My question is :

1- How can we get remotely regedit value for 2003 or 2008 oldest OSes IS NOT a part of default domain insie else block?

Also , Condition will be like below.

 if SMB1 value is "0" then result will be `false`
 if SMB1 value is "1" then result will be `true`
 if SMB1 value is not exist then result will be `not exist value`

2- How can I create object properties $SMBAudit variable ? because , I will concentanate all outputs inside $results variable.

$reg = [wmiclass]"\\$computer\root\default:StdRegProv"
$SMBAudit = $reg.GetStringValue($basekey, $subkey, $value).sValue

My desired output :

Computername,SMB1Enabled
Host01,True
Host02,False

I will write so far a script like below. but I am stucking somethings.

Script :

# Computer List
$allComputers = Get-Content .\path\to\computers.txt

read-host -assecurestring | convertfrom-securestring | out-file C:\mysecurestring_domain.txt

read-host -assecurestring | convertfrom-securestring | out-file C:\mysecurestring_local.txt

# Create empty array of results
$Results = @()

# Loop through computers
foreach($computer in $allComputers) {

    
        # check if server is pingable before running the query on the server
        if (Test-Connection $computer -Count 1 -Quiet) {  

            Write-Host "`n`n$computer is online!" -BackgroundColor Green -ForegroundColor Black
            
        }
        if(Get-ADComputer -Filter {Name -eq $computer -and OperatingSystem -notlike '*Windows*Server*2003*' -and OperatingSystem -notlike '*Windows*Server*2008*'})
            {
        #"machine $_ is a part of default domain"
            # The command we want to run
            
            $username = "domain01\admin01"
$password = Get-Content 'C:\mysecurestring_domain.txt' | ConvertTo-SecureString
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
    $SMB = Invoke-Command -ComputerName $computer -Credential $cred -ScriptBlock {Get-SmbServerConfiguration | Select EnableSMB1Protocol }
    
    # Create properties
    $Properties = @{
        # Populate the properties "Computername" and "SMB1Enabled" with variables
        Computername = $Computer
        SMB1Enabled = $SMB.EnableSMB1Protocol

    }
    # Add the properties to the result for each object
    $Results += New-Object psobject -Property $Properties
        
        
        }
        else
        {
        #"machine $_ IS NOT a part of default domain"
        
                    $username = "localadmin01"
$password = Get-Content 'C:\mysecurestring_local.txt' | ConvertTo-SecureString
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
            $SMB = Invoke-Command -ComputerName $computer -Credential $cred -ScriptBlock {Get-SmbServerConfiguration | Select EnableSMB1Protocol }
    
    # Create properties
    $Properties = @{
        # Populate the properties "Computername" and "SMB1Enabled" with variables
        Computername = $Computer
        SMB1Enabled = $SMB.EnableSMB1Protocol

    }
    # Add the properties to the result for each object
    $Results += New-Object psobject -Property $Properties
        
        
        
        }
        
        # Oldest OSes

        if(Get-ADComputer -Filter {Name -eq $computer -and OperatingSystem -notlike '*Windows*Server*2012*' -and OperatingSystem -notlike '*Windows*Server*2016*' -and OperatingSystem -notlike '*Windows*Server*2019*'})
            {
        #"machine $_ is a part of default domain"
            # The command we want to run
          <# HKEY_CLASSES_ROOT (2147483648 (0x80000000))
 HKEY_CURRENT_USER (2147483649 (0x80000001))
 HKEY_LOCAL_MACHINE (2147483650 (0x80000002))
 HKEY_USERS (2147483651 (0x80000003))
 HKEY_CURRENT_CONFIG (2147483653 (0x80000005))
 #>
 
        $basekey  = [uint32]'0x80000002'
$subkey   = 'SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters'
$value    = 'SMB1'

$reg = [wmiclass]"\\$computer\root\default:StdRegProv"
$SMBAudit = $reg.GetStringValue($basekey, $subkey, $value).sValue


        
        
        }
        else
        {
        #"machine $_ IS NOT a part of default domain"

        




}

# Output
$Results | Select-Object Computername, SMB1Enabled | Out-File -Filepath c:\temp\smb1-computers.txt
powershell
asked on Stack Overflow Feb 22, 2021 by Arbelac • edited Mar 2, 2021 by Arbelac

1 Answer

0

I think you are over complicating this and although not tested by me, you could try this:

# Computer List
$allComputers = Get-Content '.\path\to\computers.txt'

# get credentials for domain-joined machines and for local machines
$domainCred = Get-Credential -UserName "domain01\admin01" -Message "Please enter the DOMAIN password"
$localCred  = Get-Credential -UserName "localadmin01" -Message "Please enter the LOCAL password"

# loop through the list of computers and collect output in variable $Results
$Results = foreach($computer in $allComputers) {
    # check if server is pingable before running the query on the server
    if (Test-Connection -ComputerName $computer -Count 1 -Quiet) {  
        Write-Host "$computer is online!" -BackgroundColor Green -ForegroundColor Black

        $server = Get-ADComputer -Filter "Name -eq '$computer'" -Properties OperatingSystem -ErrorAction SilentlyContinue
        # if domain joined, use $domainCred, otherwise $localCred
        if ($server) { 
            $cred    = $domainCred
            $version = ([regex]'Windows Server (\d+)').Match($server.OperatingSystem).Groups[1].Value
        } 
        else { 
            $cred    = $localCred
            $info    = Get-WmiObject -ComputerName $computer -Credential $cred -Class Win32_OperatingSystem
            $version = ([regex]'Windows Server (\d+)').Match($info.Caption).Groups[1].Value
        }
        if ($version -eq '2003') {
            # try reading the registry
            try {
                $RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer)
                $RegKey  = $RegBase.OpenSubKey("SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters")
                $SMB     = $RegKey.GetValue("SMB1")
                [PsCustomObject]@{ ComputerName = $computer; SMB1Enabled = ($null -eq $SMB -or [int]$SMB -eq 1) }
            }
            catch {
                [PsCustomObject]@{ ComputerName = $computer; SMB1Enabled = 'Could not read Remote Registry' }
            }
            finally {
                if ($RegBase) { $RegBase.Close() }
                if ($RegKey)  { $RegKey.Close() }
            }
        }
        elseif ($version -eq '2008') {
            # Older OS
            try {
                # try via WinRM
                $SMB = Invoke-Command -ComputerName $computer -Credential $cred -ScriptBlock {
                            Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters' -Name SMB1
                       } -ErrorAction Stop
                # output an object
                [PsCustomObject]@{ ComputerName = $computer; SMB1Enabled = ($null -eq $SMB -or [int]$SMB -eq 1) }
            }
            catch {
                # try reading the registry
                try {
                    $RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer)
                    $RegKey  = $RegBase.OpenSubKey("SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters")
                    $SMB     = $RegKey.GetValue("SMB1")
                    [PsCustomObject]@{ ComputerName = $computer; SMB1Enabled = ($null -eq $SMB -or [int]$SMB -eq 1) }
                }
                catch {
                    [PsCustomObject]@{ ComputerName = $computer; SMB1Enabled = 'Could not read Remote Registry' }
                }
                finally {
                    if ($RegBase) { $RegBase.Close() }
                    if ($RegKey)  { $RegKey.Close() }
                }
            }
        }
        else {
            # Newer OS
            $SMB = Invoke-Command -ComputerName $computer -Credential $cred -ScriptBlock { Get-SmbServerConfiguration | Select-Object EnableSMB1Protocol }
            # output an object
            [PsCustomObject]@{ ComputerName = $computer; SMB1Enabled = $SMB.EnableSMB1Protocol }
        }
    }
    else {
        Write-Warning "Computer $computer is off-line"
        # output an object anyway, so that in the CSV it is known that the computer didn't ping
        [PsCustomObject]@{ ComputerName = $computer; SMB1Enabled = 'Off-Line' }
    }
}

# Output on screen
$Results | Format-Table -AutoSize

# Output to CSV file
$Results | Export-Csv -Path 'c:\temp\smb1-computers.csv' -NoTypeInformation -UseCulture
answered on Stack Overflow Feb 23, 2021 by Theo • edited Feb 25, 2021 by Theo

User contributions licensed under CC BY-SA 3.0