back to log

My pentest notes template

How I structure offensive-security notes, drilled for the HTB CPTS exam.

I'm working through the HTB CPTS path right now. The exam is 7 days against an Active-Directory-heavy environment, then 4 days to write the report. Most people who fail it don't fail because they couldn't pop the box. They fail because they can't find the screenshot, the credential, or the command they ran on day two when they need it on day six.

So before I touch a single module, I drill the note-taking pipeline. Below is the setup I'm using now. I'll iterate as I go.

The shape

Plain Markdown in Obsidian. Not because Obsidian is magical, but because I want a folder of .md files I can also grep from a terminal. Vendor lock-in on notes is its own kind of problem.

~/notes/
├─ 00-templates/
│   ├─ engagement.md
│   ├─ host.md
│   └─ vulnerability.md
├─ 10-cpts/                      # one folder per HTB Academy module
│   ├─ pivoting-tunneling-and-port-forwarding/
│   ├─ active-directory-enumeration-and-attacks/
│   └─ ...
├─ 20-htb-boxes/                 # retired boxes I work through
│   └─ <box-name>/
└─ 30-engagements/               # exam + real engagements (separate vaults in real life)
    └─ cpts-exam-2026-XX/
        ├─ README.md             # scope, target IPs, rules, timezone
        ├─ findings/
        ├─ hosts/
        ├─ creds.md
        └─ report-draft.md

The numeric prefixes aren't OCD — they keep the sidebar sorted so the folders I actually touch are always at the top.

The host file (where I live for hours)

Every reachable host gets its own file. Same skeleton, fill it in as enumeration progresses. The key rule: commands always go in fenced code blocks with the language tag, so I can later regex out everything I ran without hand-cleaning.

# 10.10.11.42 — `prod-fs01`
 
- Role: file server (suspected)
- First seen: 2026-04-24 14:02 UTC
- Reached via: foothold on 10.10.11.13 (kerberoast → svc_backup)
 
## Recon
 
```bash
nmap -sC -sV -p- -oA scans/prod-fs01-full 10.10.11.42
nmap --script "smb-vuln*" -p139,445 10.10.11.42

Open: 139/smb, 445/smb, 5985/winrm

Enumeration

crackmapexec smb 10.10.11.42 -u svc_backup -p 'P@ssw0rd!' --shares
crackmapexec winrm 10.10.11.42 -u svc_backup -p 'P@ssw0rd!'

Backups$ share is readable. Pulled Settings.xml → cpassword present.

Foothold

Loot: creds.md updated with j.smith / Summer2025! (decrypted from cpassword).

Lateral / Privesc

(empty until something lands)

Artifacts

  • loot/prod-fs01/Settings.xml
  • screenshots/prod-fs01-shares.png
 
The blockquote callouts mark anything that affected another host's notes. They become my cross-reference bread crumbs when writing the report.
 
## The credential ledger
 
Single file, append-only, no exceptions.
 
```md
| date       | host           | user          | secret              | source           |
|------------|----------------|---------------|---------------------|------------------|
| 2026-04-24 | prod-fs01      | svc_backup    | P@ssw0rd!           | foothold-svc     |
| 2026-04-24 | prod-fs01      | j.smith       | Summer2025!         | gpp-decrypt      |
| 2026-04-24 | DC01           | (kerb-tgt)    | <hash>              | rubeus asktgt    |

If I touched a credential it goes here, with the time and where it came from. This is the single thing I most wish I had built a habit of earlier.

The vulnerability template (report-ready)

The exam wants a real report at the end. Pre-shaping each finding while the context is fresh saves a brutal 12-hour crunch on day 7.

# Finding: Group Policy Preferences cpassword on `prod-fs01`
 
**Severity:** High
**CWE:** [CWE-321: Use of Hard-coded Cryptographic Key](https://cwe.mitre.org/data/definitions/321.html)
 
## Description
The accessible SMB share `\\prod-fs01\Backups$` contains a `Settings.xml`
with a `cpassword` attribute, which is encrypted with a key Microsoft
publicly disclosed in 2014. Any authenticated user can decrypt it.
 
## Reproduction
```bash
smbclient //prod-fs01/Backups$ -U svc_backup
get Settings.xml
gpp-decrypt <cpassword>

Impact

Recovered local administrator credentials for j.smith, used to pivot to ...

Remediation

  1. Remove all GPP files referencing cpassword (KB2962486).
  2. Rotate any credentials previously stored in GPP files.
  3. Audit GPO XML files in SYSVOL for the cpassword attribute pattern.
 
A finding that already has Description/Reproduction/Impact/Remediation is 80% of a report paragraph by the time I write it down.
 
## What this actually gets me
 
**Searchability.** `rg "cpassword" ~/notes/30-engagements/cpts-exam-2026-XX` finds every host where I touched the GPP issue, instantly.
 
**No retracing.** Every command is in a fenced block. I never have to re-derive syntax I already worked out.
 
**Cross-host chain.** The blockquote callouts surface the path: foothold → creds → lateral → loot.
 
**Report skeleton, free.** By exam day 7, the report is half-written before I open the doc.
 
## What's coming
 
Once I clear the modules I'll publish per-module notes here. Most of the public CPTS notes I've found are either way too thin or too specific to the author's own habits. I'd rather put out the version that actually worked for me.
 
If you've got a setup that handles the "I'm enumerating" to "I'm writing" transition better than this, I'd genuinely like to hear it. There's a [terminal](/contact) on the contact page.