SCRIPT LIBRARY · POWERSHELL
Finding and Disabling SMBv1 Without Breaking the Scanner
Audit who still talks SMBv1 to your machines, then switch it off for good, with one script and three modes.
- What it does
- Reports whether SMBv1 is enabled and installed, turns on SMBv1 access auditing so you can see which clients still use it, or disables the SMB1 server protocol and removes the SMB1Protocol feature.
- Requires
- Windows PowerShell 5.1 (or PowerShell 7 on Windows)
- SmbShare and Dism modules (built in)
- Permissions
- Local admin, elevated.
- Runs on
- Windows 10/11, Windows Server 2016+
- Tested
- Parse-checked and dry-run with mocked cmdlets in PowerShell 7.4
Part 6 of the thread PowerShell craft
SMBv1 is the protocol WannaCry and NotPetya rode in on, and Microsoft has been telling people to get rid of it for about a decade. Newer Windows builds don't even install it any more. But plenty of older machines still have it, usually because nobody wants to be the person who turned it off and broke the copier's scan-to-folder.
That fear is reasonable. The fix is to find out who's actually using SMBv1 before you pull the plug. Windows can log every SMBv1 connection to a server; you just have to turn the auditing on and wait a while.
So this script works in three steps. Report tells you where a machine stands. Audit turns on SMBv1 access logging. After a couple of weeks, Report again lists every client address that connected with SMBv1. When that list is empty (or you've dealt with the stragglers), Disable turns it off and removes the feature. The original post just generated a ConfigMgr package around a single Disable-WindowsOptionalFeature line; this is the part that should have come first.
<#
.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
}
}
Parameters
| Parameter | Type | Default | What it's for |
|---|---|---|---|
-Mode | string | Report | Report shows the current state and recent SMBv1 clients. Audit turns on SMBv1 access logging. Disable turns SMBv1 off and removes the feature. |
-AuditDays | int | 14 | How many days of audit events to look at when reporting SMBv1 clients. |
Run it
Where does this machine stand?
.\Set-Smb1Protocol.ps1Start logging SMBv1 connections on a file server.
.\Set-Smb1Protocol.ps1 -Mode AuditTwo weeks later, see who connected over the last 30 days.
.\Set-Smb1Protocol.ps1 -AuditDays 30 | Select-Object -ExpandProperty Smb1ClientsSeenPreview the shutdown, then do it.
.\Set-Smb1Protocol.ps1 -Mode Disable -WhatIfWhat you'll see
ComputerName : FS-01
Smb1ServerEnabled : True
Smb1FeatureState : Enabled
AuditingEnabled : True
Smb1ClientsSeen : {10.20.1.55 (212x), 10.20.4.12 (3x)}
RestartNeeded : False
How it works
- Report. It reads
EnableSMB1ProtocolandAuditSmb1AccessfromGet-SmbServerConfiguration, and the state of theSMB1Protocoloptional feature fromGet-WindowsOptionalFeature. Then it pulls event ID 3000 from theMicrosoft-Windows-SMBServer/Auditlog for the last-AuditDaysdays, pulls the client address out of each one, and counts connections per client. - Audit.
Set-SmbServerConfiguration -AuditSmb1Access $true. From then on, every SMBv1 connection to this machine leaves an event. It's lightweight enough to leave on for weeks. - Disable.
Set-SmbServerConfiguration -EnableSMB1Protocol $falsestops the server accepting SMBv1 right away. ThenDisable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestartremoves the feature (client and server) the next time the machine restarts. If the feature is already off or pending, that step is skipped. - Always finish with a report, so the output of every mode shows the state it left the machine in.
Rolling it out with ConfigMgr or Intune
The approach I'd use at scale: deploy -Mode Audit to your file servers and anything else that shares folders, wait two weeks, and collect the Report output (a ConfigMgr Script or an Intune remediation's output both work well for this). Chase down every client address that shows up. Then deploy -Mode Disable in rings: a test collection, then a pilot, then everything, with restarts scheduled in your normal maintenance window.
For ongoing enforcement, a ConfigMgr configuration baseline or an Intune remediation that runs Report and flags Smb1ServerEnabled or an enabled feature will catch any machine where somebody turns it back on.
Take it further
- Check the client side too. On a workstation,
Get-SmbConnection | Select-Object ServerName, Dialectshows the SMB dialect of every current connection. Anything showing 1.x is a problem. - Fence off SMB at the network. SMB (TCP 445, plus 139 for the old NetBIOS flavor) has no business crossing between segments that don't need it, whatever the version. It's a good backstop for the old devices you don't know about yet.
Things that'll trip you up
- Auditing only sees the server side. Event 3000 is logged when something connects to this machine with SMBv1. It won't tell you that this machine is using SMBv1 to reach an old NAS. The Disable mode removes the client side too, so test against old appliances before you roll it out.
- It's usually a printer, a NAS, or an old app. Multifunction printers with scan-to-folder, cheap NAS boxes and ancient line-of-business apps are the usual SMBv1 clients. Most can be switched to SMB2 or SMB3 with a firmware update or a setting. A few can't, and those should be replaced or isolated rather than holding the network back.
- The restart matters. Removing the SMB1Protocol feature doesn't finish until the machine restarts. Until then, the feature shows DisablePending and the SMB1 client driver may still be loaded. The script sets RestartNeeded so you can plan for it.
- The feature may already be gone. Windows 10 1709 and later, and Windows Server 2019 and later, don't install SMBv1 by default, and some builds remove it automatically if it goes unused. The script handles "not present" as a perfectly good answer.