Impacket Deep Dive Part 5: ntlmrelayx and the Passwordless Hijack
The brief that started this series called out ntlmrelayx.py as “the ultimate passwordless hijack,” and it earns that description more than any other tool in the toolkit. Every technique in Parts 3 and 4 ends with an offline cracking step — a hash you take away and attack at leisure. NTLM relay skips cracking entirely. The authentication attempt itself, mid-flight, becomes the access.
What’s actually being relayed
NTLM authentication is a three-message challenge-response handshake: the client sends a NEGOTIATE, the server replies with a CHALLENGE (a random nonce), and the client proves it knows the password by sending a RESPONSE — a hash of the password combined with that specific challenge. Critically, NTLM was never designed to guarantee where that response gets used, only that it corresponds to that one challenge. If an attacker sits between the client and the server it thinks it’s talking to, forwards the challenge unmodified, and forwards the response back to a different server that also trusts the same domain, that second server has no way to know the authentication didn’t originate from a direct, legitimate connection. The victim authenticated once. The attacker used that authentication twice — once, from the victim’s perspective, and once, from the second target’s.
Nothing here requires the victim’s password, their hash, or any cracking. It requires only a network position and a target that will accept an incoming NTLM authentication without something extra tying the session to its original endpoint.
What defeats it, and the gap that’s left
SMB signing — a cryptographic signature over every SMB message, tied to the session key derived during that specific authentication — is what stops the classic version of this attack cold: a relayed session’s signature won’t validate against the target that’s meant to receive it, so the relay fails outright. Since Windows 11 24H2 and Windows Server 2025, SMB signing is required by default for all outbound and inbound SMB connections, which is the single biggest reason this technique has become harder to pull off against fully modern estates than it was five years ago.
The gap that’s left is everything SMB signing doesn’t cover: LDAP and LDAPS, which historically didn’t enforce signing or channel binding by default either (Microsoft has been tightening this since 2020’s LDAP hardening advisories, but plenty of domains still run permissive settings); cross-protocol relays, where an SMB authentication gets relayed to an HTTP-based service like Active Directory Certificate Services’ web enrollment endpoint instead of back to another SMB target; and any host anywhere in the estate — printers, older Linux/Samba shares, legacy line-of-business appliances — that simply never had signing enforced in the first place. ntlmrelayx.py’s entire feature set is organized around exploiting exactly those gaps.
Setting up the relay
Verified --help, current v0.13.1 — the tool has grown considerably since its early “relay to a second SMB share” reputation and now covers relay targets across SMB, HTTP, LDAP, MSSQL, IMAP, and RPC:
usage: ntlmrelayx.py [-h] [-ts] [-debug] [-t TARGET] [-tf TARGETSFILE] [-w]
[-i] [-ip INTERFACE_IP] [--no-smb-server]
... (dozens of protocol-specific option groups) ...
For every connection received, this module will try to relay that connection
to specified target(s) system or the original client
Against WKS01 — where svc-backup’s credentials from Part 4 are useful for a different reason entirely: confirming which hosts on the segment still accept unsigned SMB, rather than cracking anything further —a basic relay-to-command run:
$ ntlmrelayx.py -smb2support -t 10.10.30.20 -c 'whoami /all'
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies
[*] Servers started, waiting for connections
[*] SMBD-Thread-4: Connection from CONTOSO/A.OYELARAN@10.10.30.55 controlled, attacking target smb://10.10.30.20
[*] Authenticating against smb://10.10.30.20 as CONTOSO/A.OYELARAN SUCCEED
[*] SMBD-Thread-4: Executing command via wmiexec
CONTOSO\a.oyelaran
USER INFORMATION
----------------
User Name SID
=============== ===============================================
contoso\a.oyelaran S-1-5-21-1957667318-3765306688-1889875232-1122
GROUP INFORMATION
-----------------
Group Name Type SID
==================================== ================ =========
BUILTIN\Administrators Alias S-1-5-32-544
The client here — a.oyelaran, a workstation-support technician whose credentials were never cracked or phished — authenticated to what it believed was a normal SMB share, most likely because something forced that authentication attempt to fire in the first place. That’s the missing half of every relay attack: coercion. ntlmrelayx.py is a relay engine, not a trigger; something has to make a target authenticate to the attacker’s listener on demand. In practice that’s tools like PetitPotam, PrinterBug (SpoolSample), or coercer, all abusing MS-RPC methods that force a machine to authenticate outward — genuinely out of scope for a strictly-Impacket series, but the honest missing link in the chain above, and worth knowing by name even where it isn’t covered in depth here.
Where the real damage lives: LDAP relay
--no-da, --no-acl, --dump-laps, --dump-gmsa, --dump-adcs, and --add-computer in the --help output above all point at the same target: relaying to LDAP instead of SMB. Relay a machine account’s authentication (coerced the same way) to LDAP, and by default ntlmrelayx.py will attempt to add a new Domain Admin account outright — the --no-da flag exists specifically to turn that automatic behavior off when a quieter ACL-based privilege escalation is preferred instead. --dump-laps pulls any LAPS-managed local administrator passwords the relayed account’s permissions allow reading. --dump-adcs enumerates AD Certificate Services templates reachable from that identity — the entry point into the ESC8 relay-to-certificate-enrollment attack chain, where a relayed machine account authentication against ADCS’s HTTP enrollment endpoint can mint a certificate usable for full domain-controller-equivalent authentication, one of the more consequential AD attack paths disclosed in the last several years and a large part of why ntlmrelayx.py grew an entire --adcs/--template/--altname option group.
Defensive notes
Enforce SMB signing everywhere, not just where it’s now default. Server 2025 and Windows 11 24H2 default to required signing, but most real estates are running a mix of OS versions for years yet. Set Microsoft network server: Digitally sign communications (always) via GPO domain-wide rather than relying on a rolling OS upgrade to get there — this is the single control that stops the classic SMB-to-SMB relay outright.
LDAP signing and channel binding are not the same setting, and both matter. LDAP server signing requirements set to Require signing, plus LDAP server channel binding token requirements set to Always (the setting Microsoft’s 2020 advisory, ADV190023, specifically hardened) — channel binding is what stops LDAPS relay even when the relayed session is itself individually authenticated correctly, because it ties the TLS channel to the authentication in a way signing alone doesn’t.
Extended Protection for Authentication (EPA) on ADCS web enrollment. The specific defense against the ESC8 relay-to-certificate path — binds the HTTP authentication to the underlying TLS channel so a relayed NTLM session can’t be replayed against the enrollment endpoint from elsewhere. Microsoft has pushed this as a default in newer ADCS deployments; older, upgraded-in-place CA installs are the ones actually at risk and worth an explicit audit.
Kill the coercion primitives, not just the relay. PetitPotam and PrinterBug both abuse legitimate RPC methods (EFSRPC, MS-RPRN) that most domains have no operational reason to leave reachable from arbitrary workstations. Disabling the Print Spooler service on domain controllers (it should never have been running there) and restricting EFSRPC reachability closes the trigger half of this attack even where relay itself can’t be fully eliminated.
Detect the pattern: one client, many destinations, same session key. Because a relayed authentication reuses the victim’s actual NTLM challenge-response rather than generating a fresh one per destination, correlating NTLM authentication events (4624 logon type 3) by session characteristics across multiple destination hosts in a short window — something Microsoft Defender for Identity’s relay detection specifically watches for — catches the technique independent of which specific target or payload was used.
Next: Part 6, where a foothold — cracked, relayed, or otherwise obtained — turns into an actual remote shell, and why wmiexec.py barely shows up in EDR telemetry while its siblings do.