<# .SYNOPSIS Reports on SMBv1, turns on SMBv1 access auditing, or disables SMBv1 for good. .DESCRIPTION Three modes: Report (default) Shows whether the SMB1 server protocol is enabled, whether the SMB1 feature is installed, whether auditing is on, and which clients have used SMB1 recently according to the audit log. Changes nothing. Audit Turns on SMB1 access auditing (AuditSmb1Access). Windows then logs event 3000 in Microsoft-Windows-SMBServer/Audit every time a client connects with SMB1. Leave it a couple of weeks, then run Report to see who'd break. Disable Turns off the SMB1 server protocol and removes the SMB1Protocol optional feature (client and server). Usually needs a restart to finish. Supports -WhatIf. Needs to run elevated. .PARAMETER Mode Report, Audit or Disable. .PARAMETER AuditDays How far back to look in the audit log in Report mode. Default: 14. .EXAMPLE .\Set-Smb1Protocol.ps1 .EXAMPLE .\Set-Smb1Protocol.ps1 -Mode Audit .EXAMPLE .\Set-Smb1Protocol.ps1 -Mode Disable -WhatIf #> [CmdletBinding(SupportsShouldProcess)] param( [ValidateSet('Report', 'Audit', 'Disable')] [string]$Mode = 'Report', [ValidateRange(1, 365)] [int]$AuditDays = 14 ) $ErrorActionPreference = 'Stop' function Get-Smb1Status { $server = Get-SmbServerConfiguration $feature = Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -ErrorAction SilentlyContinue # Who has actually talked SMB1 to this machine lately? $clients = @() try { $events = Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-SMBServer/Audit' Id = 3000 StartTime = (Get-Date).AddDays(-$AuditDays) } -ErrorAction Stop $clients = @($events | ForEach-Object { if ($_.Message -match 'Client Address:\s*(\S+)') { $Matches[1] } } | Group-Object | Sort-Object Count -Descending | ForEach-Object { '{0} ({1}x)' -f $_.Name, $_.Count }) } catch { Write-Verbose "No SMB1 audit events in the last $AuditDays days (or the log is empty)." } [pscustomobject]@{ ComputerName = $env:COMPUTERNAME Smb1ServerEnabled = $server.EnableSMB1Protocol Smb1FeatureState = if ($feature) { $feature.State.ToString() } else { 'NotPresent' } AuditingEnabled = $server.AuditSmb1Access Smb1ClientsSeen = $clients # A pending state means the change is staged and waiting on a reboot. RestartNeeded = [bool]($feature -and "$($feature.State)" -like '*Pending') } } switch ($Mode) { 'Report' { Get-Smb1Status } 'Audit' { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, 'Enable SMB1 access auditing')) { Set-SmbServerConfiguration -AuditSmb1Access $true -Force -Confirm:$false Write-Verbose 'Auditing on. SMB1 connections will show up as event 3000 in Microsoft-Windows-SMBServer/Audit.' } Get-Smb1Status } 'Disable' { $restart = $false if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, 'Disable SMB1 server protocol')) { Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force -Confirm:$false } $feature = Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -ErrorAction SilentlyContinue if ($feature -and "$($feature.State)" -notin 'Disabled', 'DisabledWithPayloadRemoved', 'DisablePending') { if ($PSCmdlet.ShouldProcess($env:COMPUTERNAME, 'Remove SMB1Protocol optional feature')) { try { $r = Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart $restart = [bool]$r.RestartNeeded } catch { Write-Warning "Couldn't remove the SMB1Protocol feature: $($_.Exception.Message)" } } } else { Write-Verbose 'SMB1Protocol feature is already disabled, pending a restart, or not present.' } $status = Get-Smb1Status $status.RestartNeeded = $status.RestartNeeded -or $restart if ($status.RestartNeeded) { Write-Warning 'Restart required to finish removing SMB1.' } $status } }