Table of contents
Introduction
I wanted to learn offensive cybersecurity, actual technical skills, hands-on. I had time for it, but not a ton during exams and the semester, so CWES made more sense than jumping straight into CPTS. On top of that, some pentesting internships specifically value Hack The Box experience, which made the decision easy. So I planned it out: complete the path during exam season and find a 4 days timeslot during the semester.
The Exam Experience
I was pretty rusty going in. I had done about 60% of the course during the Christmas break (two months earlier) and barely took any notes. Right before the exam, I set up my environment: I spun up a fresh VM from my golden image, which is a clean base I keep updated with all my tools and only touch for upgrades. From that, I create throwaway VMs for any actual work and can insert VPN at deployment instantly.
Setup Deployment (Fedora SilverBlue)
Requirements: libvirt-client qemu-img virt-install
#!/bin/bash
VM_NAME="ParrotLab"
BASE_IMG="$PATH_TO_BASE_IMAGE"
VM_DIR="$HOME/2_lab/vms/$VM_NAME"
DISK="$VM_DIR/$VM_NAME-disk.qcow2"
CLOUD_ISO="$VM_DIR/config.iso"
SHARED_PATH="/srv/shared_disk"
VPN_FILE="${1:-}"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# 1. Cleanup old attempts
virsh --connect qemu:///session destroy $VM_NAME 2>/dev/null
virsh --connect qemu:///session undefine $VM_NAME --remove-all-storage 2>/dev/null
mkdir -p "$VM_DIR"
# 2. Create the Linked Clone
echo "[+] Creating linked clone..."
qemu-img create -f qcow2 -b "$BASE_IMG" -F qcow2 "$DISK"
# 3. Build user-data (inject VPN config if provided)
USERDATA="$SCRIPT_DIR/user-data"
FINAL_USERDATA="$VM_DIR/user-data"
cp "$USERDATA" "$FINAL_USERDATA"
if [ -n "$VPN_FILE" ]; then
if [ ! -f "$VPN_FILE" ]; then
echo "[!] VPN file not found: $VPN_FILE"
exit 1
fi
VPN_NAME="$(basename "$VPN_FILE" .ovpn)"
echo "[+] Injecting VPN config: $VPN_FILE"
# Write the VPN config block to a temp file
VPN_BLOCK=$(mktemp)
{
echo " - path: /etc/openvpn/client/${VPN_NAME}.conf"
echo " permissions: '0600'"
echo " content: |"
sed 's/^/ /' "$VPN_FILE"
} > "$VPN_BLOCK"
# Replace placeholders in user-data
sed -i -e "/^ #VPN_WRITE_FILES/{r $VPN_BLOCK" -e 'd}' "$FINAL_USERDATA"
sed -i "s| #VPN_RUNCMD| - [ systemctl, enable, --now, openvpn-client@${VPN_NAME} ]|" "$FINAL_USERDATA"
rm -f "$VPN_BLOCK"
else
# No VPN — strip placeholders
sed -i '/^ #VPN_WRITE_FILES/d' "$FINAL_USERDATA"
sed -i '/^ #VPN_RUNCMD/d' "$FINAL_USERDATA"
fi
# 4. Generate Cloud-Init ISO using xorriso
echo "[+] Creating config ISO..."
META_DATA="$VM_DIR/meta-data"
echo "instance-id: $(uuidgen)" > "$META_DATA"
xorriso -as mkisofs \
-R -V cidata \
-o "$CLOUD_ISO" \
"$FINAL_USERDATA" "$META_DATA"
# 5. Deploy
echo "[+] Deploying $VM_NAME..."
virt-install \
--connect qemu:///session \
--name "$VM_NAME" \
--memory 8192 \
--vcpus 8 \
--cpu host-passthrough \
--os-variant debian12 \
--disk path="$DISK",bus=virtio \
--disk path="$CLOUD_ISO",device=cdrom \
--import \
--graphics spice,listen=none \
--video virtio \
--network type=user,model=virtio \
--filesystem "$SHARED_PATH",shared_disk,mode=mapped,type=mount \
--features acpi=on,apic=on \
--boot loader=/usr/share/edk2/ovmf/OVMF_CODE.fd,loader_ro=yes,loader_type=pflash,nvram_template=/usr/share/edk2/ovmf/OVMF_VARS.fd \
--noautoconsole
echo "[!] Success. If it doesn't show up in Virt-Manager immediately, restart it."
Cleanup script (Fedora SilverBlue)
#!/bin/bash
VM_NAME="ParrotLab"
VM_DIR="$HOME/2_lab/vms/$VM_NAME"
echo "[!] Starting cleanup for $VM_NAME..."
# 1. Stop the VM if it is running
if virsh --connect qemu:///session list --all | grep -q "$VM_NAME"; then
echo "[+] Stopping VM..."
virsh --connect qemu:///session destroy "$VM_NAME" 2>/dev/null
echo "[+] Undefining VM and removing NVRAM..."
virsh --connect qemu:///session undefine "$VM_NAME" --nvram
else
echo "[-] VM $VM_NAME not found in Libvirt."
fi
# 2. Delete the associated files
if [ -d "$VM_DIR" ]; then
echo "[+] Deleting disk files in $VM_DIR..."
rm -rf "$VM_DIR"
else
echo "[-] Storage directory already gone."
fi
echo "[✓] Cleanup complete."
| Day | Flags | Notes |
|---|---|---|
| Day 1 | 0 | Rough start : had to accept I needed to revisit the course |
| Day 2 | 2 | First flags came in the afternoon, after 1.5 days of nothing |
| Day 3 | 5 | Breakthrough, started internalizing the methodology |
| Day 4 | 2 | Steady |
| Day 5+ | Report writing |
The biggest lesson: be meticulous. After day one with nothing, I realized the exam wasn’t going to reward speed, it rewarded thoroughness. The path doesn’t train you for actual black box penetration testing, be aware of that ! I went back through the course material during the exam itself, and it paid off.
How I Structured My Notes - After the exam
The most valuable thing I’d recommend is building a solid methodology folder system before you sit the exam. Here’s what mine looks like:
1_Methodology/- Maps real situations to the techniques or tools and order of operations you should follow. Think: login form → try SQL Injection, then LDAP injection, etc.2_Techniques/- Deep dives on each technique referenced in the methodology: SQL Injection, LDAP, XSS, etc.3_Tools/- Usage references for specific tools: Nmap, SQLmap, ffuf, etc.
The key insight is that Methodology and Techniques are separate. Methodology tells you when to use something; Techniques tell you how.
Here’s an example of what a systematic methodology section looks like in practice:
Example of systematic methodology
Port & Service Discovery
- Full port scan → Reference: Nmap
- Identify services, versions, OS → Whatweb
Fingerprinting
- Check HTTP headers (
Server,X-Powered-By,Set-Cookienaming) - Check page source for comments, frameworks, JS libs
- Identify CMS → Reference: CMS Tool
- Check
robots.txt,sitemap.xml,.well-known/ - Check for common files:
crossdomain.xml,security.txt
Etc…