
SMB, fully explained: from anonymous access to NTLM relay, and how to lock it down
Almost every Windows network runs on SMB, and almost every Windows network compromise touches it. Server Message Block is how Windows machines share files, manage printers, talk to named pipes, and carry a surprising amount of remote administration, which is exactly why it is the first thing an attacker enumerates and one of the last things an organisation manages to lock down. This post explains SMB from the beginning: why it was created, how Microsoft has used and reshaped it across four decades, the exploit history that made an exposed port 445 a standing liability, and then the attack itself, starting from an anonymous connection and ending at NTLM relay and SMB signing. The second half is the larger half, because the point of understanding the attack is to close it.
Scope: everything here assumes an authorised engagement or a lab you own. The enumeration and relay steps are shown against a cooperating target to make the defensive controls legible; the standard tooling is named, not weaponised, and the back half is entirely the controls that break each step.
Why SMB exists
SMB was invented at IBM in the mid 1980s as a way for one computer to use files and printers that physically lived on another, as if they were local. The idea was a client/server request protocol: the client sends a "message block" that says open this file, read these bytes, list this directory, and the server answers. Microsoft adopted it early and made it the native file-sharing protocol of the LAN Manager and Windows for Workgroups era, then of every version of Windows since. For a long stretch Microsoft marketed its SMB implementation as CIFS (Common Internet File System), which is just SMB1 with some additions; the name survives in old documentation and tool flags but the protocol is SMB.
The reason it became load-bearing is that Windows networking grew up around it. SMB does not only move files. It carries the named pipe transport that a large amount of Windows remote administration runs over (the Service Control Manager, the registry, the Security Account Manager, the Server service, the printer spooler, and more all expose RPC interfaces reachable over SMB named pipes). So "SMB" in practice means file shares, printer shares, and a remote-procedure-call bus into the guts of the operating system, all on one port. That breadth is the feature and the problem.
How Windows has carried it for forty years
A short history, because the version matters enormously for security:
- SMB1 / CIFS. The original dialect, carried first over NetBIOS. On a network it appears as TCP 139 (SMB over NetBIOS Session Service) and, from Windows 2000 onward, as TCP 445 (SMB "direct" over TCP, no NetBIOS layer). SMB1 has no meaningful integrity protection by modern standards, supports null/anonymous sessions by design, and is the dialect every catastrophic worm abused. Microsoft began removing it by default in Windows 10 1709 (Fall Creators Update, 2017) and Windows Server 1709, and current Windows ships without the SMB1 client or server installed. If SMB1 is still enabled anywhere in 2026, that is itself a finding.
- SMB2 arrived with Windows Vista / Server 2008 (2006 to 2008). It was a clean redesign: far fewer commands, proper request compounding, larger reads and writes, and, critically, a real message-signing scheme. SMB 2.1 came with Windows 7 / Server 2008 R2.
- SMB3 arrived with Windows 8 / Server 2012 (2012) and is the modern baseline. SMB 3.0, 3.0.2, and 3.1.1 (Windows 10 / Server 2016) added end-to-end encryption, pre-authentication integrity (SMB 3.1.1, which cryptographically protects the dialect negotiation so it cannot be silently downgraded), secure dialect negotiation, and performance features like multichannel and SMB Direct (RDMA).
The through-line is that every serious security property SMB has (signing, encryption, protected negotiation) was bolted on in SMB2 and SMB3, and the dangerous behaviours (anonymous access, downgrade, unsigned traffic) are either SMB1 era or are modern defaults that were chosen for compatibility rather than safety. Understanding the attacks is largely understanding which of those properties is missing on a given host.
Why an exposed port 445 is still treated as dangerous
The structural reasons first. SMB is attractive to an attacker because of what it is, before any specific bug: it exposes file shares (data, and often credentials in scripts and backups), it exposes the Windows RPC administration surface over named pipes, and it is the native lateral movement engine of a Windows estate. A single valid credential plus reachable 445 is remote code execution on every machine that credential is local admin on. And SMB carries NTLM authentication, which is relayable, so SMB is both a target and a transport for attacks on the rest of the domain.
Then the exploit history, which is why "just don't expose 445 to anything you don't have to" became doctrine:
- MS08-067 (2008). A remotely exploitable flaw in the Server service reachable over SMB, wormable, no authentication. It powered Conficker and remained a reliable pre-auth RCE on unpatched hosts for years.
- MS08-068 (2008). The original SMB reflection fix: Windows would relay a machine's own NTLM authentication back to itself over SMB. This is the ancestor of every modern relay attack.
- Null sessions. For a long time Windows allowed an anonymous SMB session that could still enumerate users, groups, shares, and the password policy through the RPC interfaces. This was never a "bug" in the CVE sense; it was default behaviour, and it is still present on misconfigured or legacy hosts.
- MS17-010 / EternalBlue (2017). A pre-authentication remote code execution flaw in SMB1, leaked from the NSA toolkit, exploitable against an unpatched host with nothing but network reach to 445. It is the single most consequential SMB vulnerability in history: it powered WannaCry and NotPetya in 2017, which together caused billions in damage and took down hospitals, ports, and multinationals. EternalBlue is the reason SMB1 is gone and the reason exposing 445 to an untrusted network is treated as negligence.
- SMBGhost / CVE-2020-0796 (2020). A pre-auth, wormable buffer overflow in the SMBv3 compression feature (SMB 3.1.1). It proved that "we are on SMB3, we are fine" is not a safe assumption; the modern dialect had its own critical.
- SMBleed / CVE-2020-1206 (2020). A kernel memory read in the same SMBv3 compression code, chainable with SMBGhost for unauthenticated RCE.
- Badlock / CVE-2016-0128 and friends (2016). A class of SAMR/LSAD man-in-the-middle and downgrade issues that reinforced the need to require signing and sealing on the RPC that rides over SMB.
The pattern across all of them: SMB is reachable, SMB carries powerful functionality, and either a memory-corruption bug or a protocol-downgrade weakness turns that reach into control. Patching closes the memory bugs. The protocol weaknesses (anonymous access, unsigned traffic, relayable NTLM) close with configuration, which is the rest of this post.
Discovery and fingerprinting
The attacker's first question is simply where SMB is and what it will accept. nmap fingerprints the dialect, the signing policy, and the OS:
# hosts with 445/139 open, plus SMB protocol and security details
nmap -p139,445 --open -oA smb-sweep 10.0.0.0/24
nmap -p445 --script smb-protocols,smb-security-mode,smb2-security-mode,smb-os-discovery 10.0.0.10
The modern all-in-one is NetExec (nxc, the maintained successor to CrackMapExec). Pointing it at a range with no credentials prints the hostname, domain, OS build, SMB version, and, in the brackets, the two facts that decide the rest of the engagement: whether signing is required and whether SMBv1 is enabled.
nxc smb 10.0.0.0/24
# 10.0.0.10 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01)
# (domain:corp.local) (signing:True) (SMBv1:False)
signing:False on that line is the single most valuable piece of reconnaissance on a Windows network, because it means that host can be the target of an NTLM relay. Keep the list of unsigned hosts; it is the relay target list.
Detection. A single source touching 139/445 across many hosts in a short window is the classic SMB sweep signature. On the wire it is a burst of SYNs to 445; on Windows it shows as a spray of anonymous or failed sessions. This is high-signal and worth alerting on at the IDS and at the host.
Anonymous access: the null session
A null session is an SMB connection authenticated as nobody: an empty username and empty password. Where it is allowed, it exposes far more than empty shares, because the RPC interfaces behind SMB will answer anonymous queries.
# does the host accept an unauthenticated session at all?
smbclient -L //10.0.0.10 -N
nxc smb 10.0.0.10 -u '' -p '' # null
nxc smb 10.0.0.10 -u 'guest' -p '' # guest, often forgotten and enabled
If it answers, the RPC surface is next. rpcclient with no credential can, on a permissive host, list users, groups, and the domain password policy, and translate RID numbers into account names. RID cycling walks the relative identifiers from 500 upward to recover every account even when direct enumeration is blocked:
rpcclient -U '' -N 10.0.0.10
rpcclient $> enumdomusers
rpcclient $> querydominfo
rpcclient $> queryuser 0x1f4 # RID 500 = built-in Administrator
enum4linux-ng automates the whole anonymous sweep (users, groups, shares, policy, RID cycling) into one run:
enum4linux-ng -A 10.0.0.10
Everything in this step is unauthenticated. The deliverable is a user list and the account-lockout policy, which is precisely what a spray needs.
Detection. Anonymous logons show up as Windows event 4624 with logon type 3 and an anonymous logon account, and a flurry of SAMR/LSARPC calls from one source. A legitimate workstation almost never RID-cycles a domain controller.
Enumerating shares and reading them
With any session (null, guest, or a real credential), the share list is the next target. smbmap and nxc show not just the shares but the attacker's access level on each, and can recurse into them looking for readable files:
smbmap -H 10.0.0.10 -u guest -p ''
nxc smb 10.0.0.10 -u user -p 'Passw0rd!' --shares
nxc smb 10.0.0.10 -u user -p 'Passw0rd!' --spider_plus # crawl readable shares
smbclient //10.0.0.10/Finance -U corp/user
Open or over-shared directories are where engagements are frequently won without any exploit at all: deployment scripts with embedded service-account passwords, web.config and .env files, PowerShell logon scripts, unattended-install XML with local admin credentials, and backups of the very hives (SAM, SYSTEM, NTDS.dit) that hold the keys to the domain. A SYSVOL share on a domain controller is readable by every authenticated user by design and is the classic home of the old Group Policy Preferences password (the famous cpassword, decryptable with a Microsoft-published static key).
Detection. Mass file access across a share from a single account in a short time is the signal. File share auditing (events 5140/5145) on sensitive shares, and treating any read of a hive backup as an incident, catches the data-theft and credential-harvest variants of this step.
Turning enumeration into a credential
The user list plus the lockout policy enables password spraying: one carefully chosen password tried against every account, slowly enough to stay under the lockout threshold. This is the opposite of brute force and is far quieter.
# one password, the whole user list, respecting the policy you enumerated
nxc smb 10.0.0.10 -u users.txt -p 'Autumn2026!' --continue-on-success
Credentials also arrive by other paths that all terminate in SMB access: a hash cracked offline (see Hashcat, end to end), a credential pulled from an open share, or a relayed authentication (below). SMB authentication accepts an NT hash directly, with no need to know the plaintext, which is pass-the-hash:
nxc smb 10.0.0.0/24 -u Administrator -H aad3b4...:31d6cfe0d16ae931b73c59d7e0c089c0
The [+] with (Pwn3d!) in nxc output means that credential is local administrator on that host, which means the next step is available.
Detection. Spraying is a wall of 4625 (failed logon, type 3) across many accounts from one source, then a single 4624 success. A detection on "N distinct target accounts failed from one source inside M minutes" catches it reliably. Pass-the-hash and credential reuse show as the same local account authenticating to many machines, which is why unique local admin passwords (LAPS) collapse the whole technique.
Authenticated access and remote code execution
A credential that is local admin on a host becomes code execution over SMB through a small family of Impacket tools, all of which abuse legitimate Windows remote-administration features rather than any vulnerability:
- psexec.py writes a service binary to the
ADMIN$share and starts it through the Service Control Manager over the\pipe\svcctlnamed pipe. SYSTEM shell, loud, leaves a service artifact. - smbexec.py is similar but avoids dropping a binary, running commands through a temporary service.
- wmiexec.py executes over WMI (DCOM on 135 plus a high port) and uses SMB only to retrieve output, which is quieter.
- secretsdump.py reads the
SAMandLSAsecrets remotely, and against a domain controller performs DCSync to replicate password hashes without ever logging in interactively.
impacket-psexec corp/Administrator@10.0.0.10 # SYSTEM shell
impacket-secretsdump corp/Administrator@10.0.0.10 # local SAM + LSA
nxc smb 10.0.0.10 -u Administrator -H <hash> -x 'whoami' # exec via nxc
Dumped hashes feed the next round of pass-the-hash, and the estate falls one credential at a time. For the detail of where each secret lives and the exact trace each extraction leaves, see Windows credential access.
Detection. This step is the noisiest and the most detectable. psexec writes event 7045 (a new service was installed) and a 4624 type 3 as the admin account, with the well-known PSEXESVC service name and random-named variants. A service whose binary path is in a temp directory, created moments after a remote logon, is a near-certain psexec. Named-pipe creation on svcctl, atsvc, and winreg from a non-admin host is the RPC-level signal.
NTLM relay, and why SMB signing is the whole game
Everything above needed a credential. Relay does not. When a Windows machine authenticates to the attacker over SMB (often provoked, see authentication coercion), it sends an NTLM challenge/response. NTLM has no channel binding to the destination by default, so the attacker can forward that exact authentication to a third machine and be logged in there as the victim, without ever knowing or cracking a password.
The classic setup is Responder to catch authentications (it answers LLMNR, NBT-NS, and mDNS name-resolution requests, so a mistyped share name or a broadcast lookup turns into an authentication aimed at the attacker) and ntlmrelayx to forward them:
# turn OFF Responder's own SMB/HTTP servers so ntlmrelayx can take the auth
responder -I eth0
# relay any captured SMB auth to a host that does NOT require signing, and dump it
impacket-ntlmrelayx -tf unsigned-hosts.txt -smb2support
# or go straight to code execution on the relayed target:
impacket-ntlmrelayx -t smb://10.0.0.20 -smb2support -c 'whoami'
The target list is the signing:False hosts from the very first nxc sweep, because that is the one and only condition that decides whether SMB relay works:
- If the target host requires SMB signing, the relayed session cannot be used, because the attacker does not have the session key needed to sign the messages, and the server drops unsigned traffic. The relay fails cleanly.
- If the target host does not require signing, the relayed session is fully usable and the attacker executes as the victim.
So SMB signing is not a nice-to-have; it is the single control that turns SMB relay from a reliable domain-wide compromise into a non-event. The coercion plus relay chain, taken all the way to domain dominance through LDAP, is covered in coerced NTLM relay to DCSync, and the broader relay surface beyond SMB in application NTLM relay and token theft. This post stays on the SMB leg, where the fix is unusually clean.
Hardening: shutting SMB down, step by step
The attack ladder maps one-to-one onto a list of controls. Work it top to bottom.
1. Remove SMB1 entirely. It should not exist on any machine built this decade. Confirm and remove:
Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol
Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart
# server config switch:
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force
Auditing SMB1 usage before you pull it (Set-SmbServerConfiguration -AuditSmb1Access $true, then watch the SMBServer/Audit log) tells you which legacy device is still asking for it, which is almost always one old NAS or MFP that can be replaced or isolated.
2. Require SMB signing on everything. This is the control that kills relay. Require it on both the server and client side, by GPO, across the estate, not just on domain controllers (which have required it by default for a long time). The policy settings are "Microsoft network server: Digitally sign communications (always)" and the matching client policy, both set to Enabled. On modern Windows 11 24H2 and Server 2025 SMB signing is required by default for outbound connections, but do not rely on the default; set it explicitly so a reimaged or downlevel host cannot drift to optional.
# per-host view and enforcement
Get-SmbServerConfiguration | Select RequireSecuritySignature, EnableSecuritySignature
Set-SmbServerConfiguration -RequireSecuritySignature $true -Force
Set-SmbClientConfiguration -RequireSecuritySignature $true -Force
Verify the result the way an attacker would, by sweeping for signing:False. The goal is an empty result set.
3. Kill anonymous and null-session access. Set "Network access: Restrict anonymous access to Named Pipes and Shares", "Do not allow anonymous enumeration of SAM accounts", and "and shares" to Enabled, and set RestrictNullSessAccess so even a null session that connects can read nothing. Disable the Guest account and make sure no share grants Everyone or Anonymous. This removes the entire enumeration-without-credentials step.
4. Turn off the name-resolution poisoning surface that feeds relay. Disable LLMNR and NBT-NS by GPO (and mDNS where you can), because those broadcast protocols are how Responder harvests authentications in the first place. With them off, a mistyped name fails instead of authenticating to an attacker.
5. Enable SMB encryption for sensitive shares. SMB3 encryption protects data in transit and, as a side effect, also enforces integrity. Require it per share, or globally where performance allows:
Set-SmbShare -Name Finance -EncryptData $true
Set-SmbServerConfiguration -EncryptData $true -Force # whole server
Set-SmbServerConfiguration -RejectUnencryptedAccess $true -Force
6. Collapse credential reuse with LAPS. Pass-the-hash and relayed-admin both depend on one local administrator password working on many machines. Windows LAPS gives every machine a unique, rotated local admin password, so a dumped or relayed local hash unlocks exactly one host. Pair it with the tiered-admin model so domain-admin credentials never log on to workstations where they can be harvested.
7. Restrict NTLM, and prefer Kerberos. Audit NTLM usage first ("Network security: Restrict NTLM: Audit NTLM authentication in this domain"), then move to blocking NTLM where nothing legitimate still needs it. Enforce LDAP signing and channel binding on domain controllers so the relay cannot pivot from SMB to LDAP. Turn off WDigest so plaintext passwords are not cached in LSASS, and run LSASS as a protected process (RunAsPPL) with Credential Guard where available.
8. Patch, always, and fast for SMB. EternalBlue, SMBGhost, and SMBleed were all closed by patches long before they were widely abused. SMB-reachable, pre-auth, wormable bugs are the ones that become the next WannaCry, so SMB components get the shortest patch SLA you have.
Keeping it blocked, and verifying it stays that way
Hardening the protocol is only half of it. The other half is making sure SMB is simply not reachable where it has no business being.
Never expose 445 (or 139) to the internet. There is no legitimate reason for raw SMB to face the public network; file access across the internet goes over a VPN or a purpose-built gateway. Block it at the perimeter firewall inbound and outbound (outbound 445 blocking stops a coerced internal host from authenticating to an attacker on the internet, a real relay vector).
Segment east-west. Most SMB damage is lateral: workstation to workstation and workstation to server. Workstations rarely need to reach each other over 445 at all. A host-based firewall rule that denies inbound 445 between workstations removes a huge amount of lateral movement and self-propagating-malware surface with almost no operational cost:
# example: block inbound SMB from the workstation subnet on a workstation
New-NetFirewallRule -DisplayName "Block inbound SMB (lateral)" -Direction Inbound `
-Protocol TCP -LocalPort 445 -RemoteAddress 10.0.20.0/24 -Action Block
Scope real exceptions (file servers, domain controllers, deployment systems) narrowly to the hosts and subnets that genuinely serve SMB.
Verify continuously, from the attacker's side. The single most useful recurring check is the unauthenticated nxc smb <range> sweep, scripted and diffed over time. Three columns tell you whether the hardening held: any SMBv1:True is a regression, any signing:False is a relay target that should not exist, and any host answering an -u '' -p '' null session with share or user data is an anonymous-access regression. A weekly run that alerts on new rows is a cheap, high-value control.
Watch the host signals. Tie the detection points from each step together into a small set of durable alerts: anonymous/RID-cycling logons against a DC, a spray pattern (many 4625s then a 4624 from one source), service-install events (7045) with temp-path binaries right after a remote logon, and any SMB authentication arriving at a host from the relay-prone name-resolution path. None of these is exotic, and together they cover the whole ladder.
The summary a defender can hold in one sentence: SMB is safe to run and dangerous to expose, so require signing everywhere, forbid SMB1 and anonymous access, keep 445 off the internet and off the paths between workstations, give every machine a unique local admin password, and sweep yourself for the three regressions that undo all of it.