When connecting to network shares or troubleshooting SMB-related issues, knowing the exact SMB protocol version supported by a remote host is crucial for compatibility and security purposes. Modern Windows systems (Windows 7 and later) provide multiple methods to detect this information programmatically.
The most straightforward approach for Windows 7 SP1 and later (with PowerShell 3.0+):
# First establish a connection to the share (if not already connected) net use \\remotehost\sharename /user:username password # Then check active SMB connections Get-SmbConnection | Where-Object {$_.ServerName -eq "remotehost"} | Select-Object ServerName, Dialect
The Dialect
property will show the negotiated SMB version:
- 2.1 - SMB 2.1 (Windows 7)
- 3.0 - SMB 3.0 (Windows 8/Server 2012)
- 3.1.1 - SMB 3.1.1 (Windows 10/Server 2016+)
For hosts where you can't establish a connection, packet capture reveals SMB negotiation:
# Install Wireshark if needed choco install wireshark -y # Capture traffic to remote host (run as Administrator) & "C:\Program Files\Wireshark\tshark.exe" -i Ethernet -f "host remotehost and port 445" -w smb_capture.pcap
Analyze the capture file and look for SMB2 Negotiate Protocol
in the first few packets.
For advanced discovery across multiple hosts:
# Install Nmap if needed choco install nmap -y # Run SMB version detection scan nmap --script smb-protocols -p445 remotehost
Sample output:
Host script results: | smb-protocols: | dialects: | NT LM 0.12 (SMBv1) [dangerous, should disable] | 2.02 | 2.10 | 3.00 | 3.02 |_ 3.11
For previously established connections, check Event Viewer:
# PowerShell command to check SMB client events Get-WinEvent -LogName "Microsoft-Windows-SMBClient/Operational" | Where-Object {$_.Message -like "*remotehost*"} | Select-Object TimeCreated, Message -First 10
When testing SMB versions:
- Disable SMBv1 if detected (security risk)
- Use encrypted SMB 3.x versions when possible
- Consider network isolation when testing
Here's a PowerShell function for bulk checking:
function Test-SmbVersion { param( [string[]]$ComputerName, [PSCredential]$Credential ) $results = @() foreach ($computer in $ComputerName) { try { $session = New-PSSession -ComputerName $computer -Credential $Credential -ErrorAction Stop $smbInfo = Invoke-Command -Session $session -ScriptBlock { Get-SmbServerConfiguration | Select-Object EnableSMB1Protocol, EnableSMB2Protocol } $results += [PSCustomObject]@{ ComputerName = $computer SMB1Enabled = $smbInfo.EnableSMB1Protocol SMB2Enabled = $smbInfo.EnableSMB2Protocol Status = "Success" } } catch { $results += [PSCustomObject]@{ ComputerName = $computer SMB1Enabled = $false SMB2Enabled = $false Status = "Error: $_" } } } return $results }
When troubleshooting network file sharing or security auditing, identifying the SMB protocol version of a remote host is crucial. Windows provides several built-in tools that can help determine this information without requiring direct access to the target system.
The most reliable way to check SMB versions is through PowerShell's Test-NetConnection
combined with packet analysis:
# First, establish if SMB port is open
$smbPortOpen = Test-NetConnection -ComputerName remotehost -Port 445
if ($smbPortOpen.TcpTestSucceeded) {
# Use .NET sockets to initiate SMB negotiation
$socket = New-Object System.Net.Sockets.TcpClient('remotehost', 445)
$stream = $socket.GetStream()
# Send SMB negotiate protocol request
$negotiatePacket = [byte[]]@(
0x00, 0x00, 0x00, 0x85, 0xFF, 0x53, 0x4D, 0x42,
0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x53, 0xC8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x00, 0x02,
0x50, 0x43, 0x20, 0x4E, 0x45, 0x54, 0x57, 0x4F,
0x52, 0x4B, 0x20, 0x50, 0x52, 0x4F, 0x47, 0x52,
0x41, 0x4D, 0x20, 0x31, 0x2E, 0x30, 0x00, 0x02,
0x4C, 0x41, 0x4E, 0x4D, 0x41, 0x4E, 0x31, 0x2E,
0x30, 0x00, 0x02, 0x57, 0x69, 0x6E, 0x64, 0x6F,
0x77, 0x73, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x57,
0x6F, 0x72, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x70,
0x73, 0x20, 0x33, 0x2E, 0x31, 0x61, 0x00, 0x02,
0x4C, 0x4D, 0x31, 0x2E, 0x32, 0x58, 0x30, 0x30,
0x32, 0x00, 0x02, 0x4C, 0x41, 0x4E, 0x4D, 0x41,
0x4E, 0x32, 0x2E, 0x31, 0x00, 0x02, 0x4E, 0x54,
0x20, 0x4C, 0x4D, 0x20, 0x30, 0x2E, 0x31, 0x32,
0x00
)
$stream.Write($negotiatePacket, 0, $negotiatePacket.Length)
# Read response to determine SMB version
$response = New-Object byte[] 1024
$bytesRead = $stream.Read($response, 0, $response.Length)
$socket.Close()
# Analyze response
if ($response[4] -eq 0xFF -and $response[5] -eq 0x53 -and $response[6] -eq 0x4D -and $response[7] -eq 0x42) {
$smbVersion = "$($response[8]).$($response[9])"
Write-Host "Detected SMB version: $smbVersion"
}
} else {
Write-Warning "Remote host does not have SMB port (445) open"
}
For more comprehensive scanning, you can use Nmap with its SMB scripts:
nmap --script smb-protocols -p 445 remotehost
Sample output would indicate supported versions:
Host script results:
| smb-protocols:
| dialects:
| NT LM 0.12 (SMBv1) [dangerous, but default on some old systems]
| 2.02
| 2.10
| 3.00
| 3.02
|_ 3.1.1
SMB version numbers correspond to:
- 1.0: Original SMB (obsolete and insecure)
- 2.0: Introduced with Windows Vista/Server 2008
- 2.1: Windows 7/Server 2008 R2
- 3.0: Windows 8/Server 2012
- 3.1.1: Windows 10/Server 2016 and later
Remember that SMBv1 is deprecated and dangerous. If you detect it, consider upgrading or disabling it:
# Disable SMBv1 on Windows client
Disable-WindowsOptionalFeature -Online -FeatureName smb1protocol
For servers, use:
Set-SmbServerConfiguration -EnableSMB1Protocol $false
For regular auditing, create a CSV report of multiple hosts:
$hosts = 'server1','server2','fileshare1'
$results = foreach ($host in $hosts) {
try {
$socket = New-Object System.Net.Sockets.TcpClient($host, 445)
$stream = $socket.GetStream()
# ... (same negotiation code as above)
[PSCustomObject]@{
Hostname = $host
SMBVersion = $smbVersion
Timestamp = Get-Date
}
} catch {
[PSCustomObject]@{
Hostname = $host
SMBVersion = 'Unreachable'
Timestamp = Get-Date
}
}
}
$results | Export-Csv -Path 'smb_audit.csv' -NoTypeInformation