daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

documentation-and-reporting.md (34631B)


      1 ---
      2 title: "Stage 11 — Documentation and Reporting"
      3 description: "CPTS attack-flow reference for stage 11 — documentation and reporting in an authorised engagement."
      4 category: pentest-workflow
      5 subcategory: "CPTS Attack Flow"
      6 order: 15
      7 tags: ["htb", "cpts", "htb-attack-flow", "htb-attack-flow-stage-11", "pentest-workflow"]
      8 tools: ["Markdown", "Obsidian"]
      9 difficulty: intermediate
     10 updated: "2026-08-29"
     11 source: "vault:Pentest Attack Flow/15 - Stage 11 - Documentation and Reporting.md"
     12 ---
     13 > [!dashboard] Attack-flow navigation
     14 > **Dashboard:** [HTB Pentest Attack Flow](/sheets/pentest-workflow/attack-flow-dashboard)
     15 >
     16 > **Section:** 15 of 17 · **Focus:** Stage 11 — Documentation and Reporting
     17 >
     18 > **Previous:** [Domain Trusts and Cross-Forest](/sheets/pentest-workflow/domain-trusts-and-cross-forest) · **Next:** [Appendix — Worked Chains](/sheets/pentest-workflow/worked-chains)
     19 
     20 ---
     21 # 📝 STAGE 11 — Documentation & Reporting
     22 
     23 The exam isn't over at DA. **CPTS is graded on the report, not the shell** — you hand in a commercial-grade pentest report modelled on the AEN sample, and a technically perfect compromise with a sloppy write-up fails. Treat the report as ~50% of the grade and write it *as you go*, not in a panic on day 10. This stage is the wrapper around STAGES 1-10: scaffold + log before first packet, capture an evidence packet per finding, then assemble exec summary → attack chain → findings → appendices. Deep dives: 1 - Introduction to Documentation and Reporting · 10 - Proof of Concept & Post-Engagement.
     24 
     25 > [!note] The snapshot-in-time overview — paste this at the top of every report
     26 > A pentest is a point-in-time snapshot. Open the report with the window + source + disclaimer so scope-creep in either direction can't be pinned on you:
     27 > ```text
     28 > All testing activities were performed between <START> and <END> from source IP(s) <IP/RANGE>,
     29 > [remotely over VPN | onsite | from inside the client's internal network].
     30 > This report represents a snapshot in time during the aforementioned testing period.
     31 > <Firm> cannot attest to the state of any client asset outside of this testing window.
     32 > ```
     33 
     34 ---
     35 
     36 ### 0. SETUP — scaffold evidence dirs + tmux logging BEFORE you touch the box
     37 
     38 **What to look for** → a structured home for evidence *before* anything interesting happens. Skip this and you'll be reconstructing which host a screenshot came from at 2am on submission day. Mirror STAGE 1's "do this first" discipline: run the scaffold, start logging, *then* scan.
     39 
     40 ```bash
     41 export ENG="CPTS-Exam"          # or client codename
     42 mkdir -p "$ENG"/{Admin,Deliverables,Evidence/{Findings,Scans/{Vuln,Service,Web,AD},Notes,OSINT,'Logging output','Misc Files'},Retest}
     43 tree "$ENG"                      # Admin=SoW/RoE/notes · Findings=one subfolder per finding · Retest=post-remediation
     44 ```
     45 
     46 Tmux session logging is the cheapest insurance against lost command evidence — enable it *before* testing, not after something interesting scrolls off:
     47 
     48 ```bash
     49 git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
     50 cat >> ~/.tmux.conf <<'EOF'
     51 set -g @plugin 'tmux-plugins/tpm'
     52 set -g @plugin 'tmux-plugins/tmux-logging'
     53 set -g history-limit 50000        # so retroactive logging still has scrollback
     54 run '~/.tmux/plugins/tpm/tpm'
     55 EOF
     56 tmux source ~/.tmux.conf
     57 tmux new -s exam                  # inside: Ctrl+B then Shift+I to install plugins
     58 ```
     59 
     60 Log-pane keybinds once inside tmux (prefix = `Ctrl+B`):
     61 ```text
     62 prefix + Shift+P        start/stop logging this pane   (file only fills once logging stops / session exits)
     63 prefix + Alt+Shift+P    dump the ENTIRE scrollback retroactively  (needs the raised history-limit above)
     64 prefix + Alt+P          clean screen-capture of ONE pane  (use for split panes: Responder | ntlmrelayx)
     65 ```
     66 
     67 **Session-recording alternatives / complements:**
     68 ```bash
     69 # script — zero-install typescript capture of a whole shell session (timestamped with -T)
     70 script -T timing.log -a "session-$(date -u +%Y%m%dT%H%M%SZ).log"
     71 # asciinema — replayable terminal recording, ideal for review calls / live demos
     72 asciinema rec finding-03-sqli.cast            # asciinema play finding-03-sqli.cast
     73 ```
     74 `script` files are plain text with control codes (`col -b < file.log > clean.txt` strips them); asciinema `.cast` files upload to a local player for the client walkthrough. Both give you **defensible timestamps** for every action — the raw material for the timeline section below.
     75 
     76 > [!warning] Watch out
     77 > The default tmux `history-limit` is tiny — if you enable logging halfway through, everything before it is already gone unless you raised the limit at the start. Also: get **written client approval before creating accounts / changing config**, and log every one live in the Payload + Modifications tables below. Reconstructing "what did I leave on disk" from memory is how you fail the cleanup section. Full setup: 2 - Notetaking and Organisation.
     78 
     79 ---
     80 
     81 ### Capture-as-you-go — the per-finding evidence packet
     82 
     83 **What to look for** → for *every* finding, five things captured the moment you prove it: **the command, its output, a screenshot, a timestamp, and the affected host**. An unattributed screenshot with no host/command context is worthless at report time. Keep three running logs as live notes (never reconstructed afterward):
     84 
     85 ```text
     86 ## Activity / Evidence Log   (chronological, for alert correlation & dispute defence)
     87 | Time (UTC)         | Host / Target        | Action                      | Result / Artefact        |
     88 |--------------------|----------------------|-----------------------------|--------------------------|
     89 | 2026-08-27 14:03Z  | 10.129.x (WEB01)     | Responder -I tun0 -wv       | NTLMv2 bsmith → hashes/  |
     90 
     91 ## Payload Log
     92 | Date | Host | File Path | SHA256 | Cleaned Up |
     93 | ...  | WEB01| C:\Windows\Temp\svc.exe | <hash> | Yes |
     94 
     95 ## System Modifications Log
     96 | Date | Host | Change | Location | Account Created | Password |
     97 | ...  | DC01 | added local admin pentest01 | SAM | pentest01 | <REDACTED> |
     98 ```
     99 
    100 **Evidence discipline rules:**
    101 - **Raw output stays raw.** Tool output files (`nmap` XML, `nxc` logs, BloodHound zips) live untouched in `Evidence/Scans/`; conclusions live in notes. Never edit a raw artefact to "clean it up" — if a client disputes a finding, the pristine raw file is your defence.
    102 - **Timestamp everything** in UTC (`date -u` habit, tmux logging, `script`). Your Activity Log is what answers the client's SOC when they call mid-engagement: "was 14:03Z you, or an incident?"
    103 - **Screenshot hygiene for web surfaces at scale:** instead of 40 manual browser shots, screenshot the whole web scope in one pass with gowitness, then pick the figures you need:
    104   ```bash
    105   gowitness scan file -f web-targets.txt --screenshot-path ./shots/
    106   gowitness scan nmap --file nmap.xml --service-name http --service-name https
    107   gowitness report server                                 # browse the gallery locally
    108   ```
    109 
    110 > [!tools] Stage this
    111 > [gowitness_linux_amd64](/downloads/pentest-workflow/gowitness_linux_amd64) ([SHA-256](/downloads/pentest-workflow/gowitness_linux_amd64.sha256) · [GPG signature](/downloads/pentest-workflow/gowitness_linux_amd64.sha256.asc))
    112 
    113 **Evidence pair standard** — pair every exploit request with a *normal baseline* so the causal change is visible. This is what makes a finding reproducible by the client's team (and what CPTS graders look for):
    114 
    115 ```text
    116 IDOR         baseline: own profile under my session   →  proof: same session, only ID changed, other user's data
    117 Upload       baseline: normal/rejected multipart       →  proof: MIME-only change stores .php, then SEPARATE exec request
    118 SQLi         baseline: normal search + true/false ctrl  →  proof: repeatable UNION/boolean/time result
    119 Cmd inject   baseline: normal ping + blocked probes     →  proof: encoded/quoted input yields appended `id` output
    120 ```
    121 Burp Suite's Repeater history is the natural home for HTTP evidence pairs — save the project file per engagement, and export the specific request/response pairs into the finding folder rather than screenshotting the Burp UI.
    122 
    123 > [!warning] Watch out — redaction must be DESTRUCTIVE
    124 > Never pixelate or blur to redact — tools like **Unredacter** reverse it. Bake a **solid black bar into the image file** (not a shape layered in Word). In terminal text replace secrets with `<REDACTED>`; for hashes keep first/last 3-4 chars only: `5f4dcc3b...ee6c`. Never hide text with black-on-black CSS — highlight or view-source defeats it instantly. Claim only what the evidence proves: `/etc/passwd` read ≠ full FS access; an uploaded file ≠ RCE until the server *executes* it. See Note 5 - Lessons Evidence and Reporting Cheat Sheet.
    125 
    126 ---
    127 
    128 ### Artefact naming + integrity — boring, but it's what survives QA
    129 
    130 ```text
    131 Naming:   <finding#>-<seq>-<host>-<desc>.<ext>
    132           03-02-web01-union-proof.png   07-01-dc01-dcsync-output.txt   01-03-10.129.4.12-ntlmv2-capture.log
    133 Rules:  [ ] finding number matches the report finding ID — renaming later breaks every reference
    134         [ ] SHA256 every artefact at capture:  sha256sum file >> Evidence/hashes.txt
    135         [ ] never rename/move after the finding references it — fix the reference instead
    136         [ ] one folder per finding; nothing loose in Evidence/ root
    137 ```
    138 Hashing at capture gives you chain-of-custody for anything the client later questions ("that screenshot doesn't match our logs"), and it feeds the Payload Log's SHA256 column for free.
    139 
    140 ---
    141 
    142 ### The Obsidian note stack — engagement vault layout
    143 
    144 **What to look for** → notes are written *during* testing, so structure them for retrieval under pressure, not for the report. One vault per engagement (never mix clients), mirroring the evidence scaffold:
    145 
    146 ```text
    147 ENG-Vault/
    148 ├── 00 - Admin/            SoW · RoE · scope list · exclusion list · contacts
    149 ├── 10 - Targets/          one note per host: IP · OS · ports · creds(REDACTED pointer) · flags
    150 ├── 20 - Credentials/      account · source · where valid · notes (passwords in the VAULT, not here)
    151 ├── 30 - Findings/         one note per finding, created from the finding template at discovery
    152 ├── 40 - Attack Chain/     running narrative + mermaid diagram, updated per pivot
    153 ├── 50 - Loot/             hashes, tickets, dumps — filenames + SHA256, content in Evidence/
    154 ├── 60 - Logs/             Activity / Payload / Modifications tables (live, UTC)
    155 └── 70 - Report/           exec summary draft · appendix fodder · QA checklist
    156 ```
    157 Daily habit (15 min at stop-notification time): every interesting shell output got filed, every new host got a note, every new cred got a Credentials entry + vault entry, every modification got a Modifications row. This daily close-out is what makes the final report assembly a *merge*, not an *archaeological dig*.
    158 
    159 > [!tip] Templates do the heavy lifting
    160 > Keep Obsidian templates for: host note, finding write-up (the table above), cred entry. Hotkey a new note from template the moment a shell lands — 30 seconds now saves 30 minutes at report time and guarantees no field (provenance, timestamp, evidence path) is forgotten.
    161 
    162 ---
    163 
    164 ### Common report pitfalls — the grader's red-flag list
    165 
    166 | Pitfall | Why it fails | Fix |
    167 | :-- | :-- | :-- |
    168 | Flags listed, no narrative | proves exploitation skill, not consulting skill | attack-chain chapter tying findings into business risk |
    169 | Screenshots without provenance | can't be attributed to host/time | address bar / hostname / timestamp in every figure |
    170 | "Tool X found Y" language | exec summary must be tool-free | describe the *weakness*, not the scanner |
    171 | Stock remediation text | wrong for the platform observed | platform-specific fix + test-before-deploy note |
    172 | Severity eyeballing | indefensible under client pushback | CVSS vector string on every finding |
    173 | Missing affected-scope list | client can't patch what they can't find | full host list, appendix if long |
    174 | No cleanup appendix | client mistakes your artefacts for an intrusion | every leftover documented with removal instructions |
    175 | Plaintext creds in the report | data-handling violation | truncate/redact; full values only via secure channel |
    176 | Conclusions beyond evidence | "attacker could also…" with no proof | claim only what was demonstrated; label the rest as risk |
    177 | DRAFT watermark at delivery | some auditors reject it outright | FINAL only after review meeting feedback is incorporated |
    178 
    179 ---
    180 
    181 ### The report skeleton — sections in order
    182 
    183 **What to look for** → the standard layout, front-loaded for a non-technical reader. Decide which appendices apply from the engagement *type* at kickoff (VA vs pentest, internal vs external, box colour — see 3 - Types of Reports), don't retrofit them.
    184 
    185 ```text
    186 1. Executive Summary        non-technical, 1.5-2 pages, impact in business terms
    187 2. Summary of Recommendations   near / medium / long-term, environment-specific
    188 3. Attack Chain (narrative)   the story of how DA fell, technical, ties findings together
    189 4. Findings                  one per issue, full detail + reproducible evidence
    190 5. Appendices                Static: Scope · Methodology · Severity Ratings · Biographies (PCI)
    191                              Dynamic: Compromised Creds · Config Changes · Payloads (hash/path) ·
    192                                       Domain Password Analysis (DPAT) · OSINT · Additional Affected Scope
    193 ```
    194 
    195 **Executive summary — do / don't** (the "can your parents follow it" test):
    196 ```text
    197 DO    exact numbers not "several" · impact = what was accessed (HR data, banking) · describe what broke DOWN procedurally
    198 DON'T name commercial vendors · use acronyms (SNMP/MitM/SPN) · use tool names · bury criticals under lows · send reader into Findings
    199 ```
    200 Substitute the jargon: `password spraying → "one guessable password tried against many harvested accounts"`, `hash → "output of an algorithm used to validate file integrity"`, `SQLi/XSS → "unsanitised user input manipulates the app's logic"`.
    201 
    202 **Attack chain skeleton** — write the numbered high-level story first, *then* back each step with one evidence figure. Reference the playbook stages instead of re-explaining the attack:
    203 ```text
    204 1. Captured NTLMv2 for `bsmith` via Responder (LLMNR/NBT-NS poisoning).   → STAGE 3
    205 2. Cracked offline with hashcat → standard-user foothold.                  → STAGE 8
    206 3. BloodHound mapped the domain; Kerberoasted `mssqlsvc` (local admin SQL01). → STAGE 4/5
    207 4. Cracked the TGS, dumped LSA on SQL01 → cleartext `srvadmin` (autologon). → STAGE 8
    208 5. As srvadmin found `pramirez` (DCSync rights) logged in; PtT his TGT.     → STAGE 5/6
    209 6. DCSync as pramirez → Administrator NT hash → domain compromise.          → STAGE 6
    210 ```
    211 
    212 > [!tip] The chain is reusable evidence
    213 > It shows how several *medium* findings combine into *critical* overall risk — and that breaking any one link stops the chain. The same figures paste straight into the individual findings, so format each once. Always name the **root cause not the symptom**: DA with `Password123` is a **password-policy** finding, not "one bad password". Full anatomy: 4 - Components of a Report.
    214 
    215 ---
    216 
    217 ### Writing a single finding — the template
    218 
    219 **What to look for** → every finding needs, at minimum: Description, Impact, Affected systems, Recommendation, References, and reproducible evidence. Missing one weakens its defensibility. Field-by-field:
    220 
    221 | Field | What goes in it | Grader/client trap to avoid |
    222 | :-- | :-- | :-- |
    223 | **Title** | specific + technical root cause: "LLMNR/NBT-NS Poisoning Enables Credential Theft" | vague titles ("Weak Security") or vendor-shaming |
    224 | **Severity** | CVSS score + vector string (below), mapped to Critical/High/Medium/Low | eyeballing the band — score from the vector |
    225 | **CVSS vector** | e.g. `CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/...` | mixing 3.1 and 4.0 conventions in one report — pick one and say which |
    226 | **ATT&CK mapping** | technique IDs per finding (T1110.003 password spray, T1003.001 LSASS, T1558.003 kerberoast) | mapping the *tool* instead of the *behaviour* |
    227 | **Affected assets** | hosts/IPs/URLs/OU scope | long lists inline — use the "Additional Affected Scope" appendix |
    228 | **Evidence refs** | path to each artefact: `Evidence/Findings/03-sqli/02-union-proof.png` | screenshots with no provenance (no host, no timestamp) |
    229 | **Business impact** | what an attacker achieves — concrete: "full domain compromise → access to payroll DB" | generic "could lead to data breach" |
    230 | **Remediation** | specific + actionable; free path alongside any commercial one | "harden the registry" / "buy X" |
    231 | **Retest** | expected verification method + date for the retest window | no retest criteria → client "fixed" it by renaming the page |
    232 
    233 ```markdown
    234 ## <Finding Title> — <Critical/High/Medium/Low/Info>
    235 **CVSS:** <score/vector>   **CWE / OWASP / MITRE ATT&CK:** <IDs>
    236 
    237 ### Description        what the issue is, platform(s) affected, root cause
    238 ### Impact             what an attacker achieves if unresolved — concrete, not generic
    239 ### Affected Systems   hosts/IPs/URLs (long lists → "Additional Affected Scope" appendix)
    240 ### Reproduction       numbered, ONE action per figure, narrative between figures
    241 ### Recommendation     specific + actionable; offer a free path alongside any commercial one
    242 ### References         vendor-agnostic, current, free, no-paywall
    243 ```
    244 
    245 Reproduction & remediation rules that graders actually check:
    246 ```text
    247 [ ] One action per figure — never cram multiple commands/results into one block
    248 [ ] Show full exploit/module CONFIG before execution output (two figures, esp. Metasploit)
    249 [ ] Narrative paragraph between figures — don't let consecutive screenshots carry the story
    250 [ ] Prefer copy/paste terminal TEXT over screenshots of a terminal
    251 [ ] Prove WHERE evidence came from: address bar visible / ifconfig alongside a GUI capture
    252 ```
    253 ```text
    254 Remediation  BAD:  "Reconfigure your registry to harden against X."
    255              GOOD: "Set [full hive path] value X → Y. Test on a small group first."
    256              BAD:  "Buy [commercial tool]."
    257              GOOD: "[Vendor] published a free workaround (ref); commercial tools also exist but may be cost-prohibitive."
    258 ```
    259 
    260 **ATT&CK mapping per finding:** map each finding to technique IDs from [MITRE ATT&CK](https://attack.mitre.org) — it gives the client's blue team a shared vocabulary for detections and turns your report into a detection backlog. Quick mapping examples from this playbook: LLMNR poisoning → T1557.001 · password spraying → T1110.003 · kerberoasting → T1558.003 · LSASS dumping → T1003.001 · DCSync → T1003.006 · golden ticket → T1558.001 · SID history injection → T1134.005. One technique per finding, the *behaviour* not the tool name.
    261 
    262 > [!warning] Watch out
    263 > A findings database of "stock" write-ups saves time, but **never ship a template unedited** — "Default Credentials" means something very different on a DeskJet vs an HVAC controller vs a public web app. Tailor severity, impact language, and scope to what you actually observed. Structure + quality gate: 5 - How to Write Up a Finding.
    264 
    265 ---
    266 
    267 ### CVSS scoring + Domain Password Analysis appendix
    268 
    269 **What to look for** → a defensible severity number. Score it from the vector, don't eyeball the band — it *will* get client pushback. Current default is **CVSS v4.0** ([FIRST calculator](https://www.first.org/cvss/calculator/4.0)); many clients/templates still require v3.1 — support both, but state which standard each score uses.
    270 
    271 ```bash
    272 pip install cvss
    273 python3 -c "from cvss import CVSS4; c=CVSS4('CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N'); print(c.scores(), c.severities())"
    274 python3 -c "from cvss import CVSS3; c=CVSS3('CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H'); print(c.scores(), c.severities())"
    275 # → ((9.8, ...), ('Critical', ...))   # or use the calculator at first.org/cvss/calculator/3.1
    276 ```
    277 v3.1 → v4.0 gotchas: `AC:H` splits into `AC` + **Attack Requirements (`AT`)**; Scope (`S`) is gone, replaced by separate Vulnerable/Subsequent-system impact (`VC/VI/VA` + `SC/SI/SA`); scores shift — re-score old template findings rather than carrying the number across.
    278 
    279 If you cracked NTDS (STAGE 8), generate the **Domain Password Analysis** appendix — cracked %, privileged-account cracks, reuse, top passwords:
    280 ```bash
    281 git clone https://github.com/clr2of8/DPAT && cd DPAT
    282 python3 dpat.py -n ntds.dit -c hashcat.potfile -g "Domain Admins.txt" -o dpat-report   # from the STAGE 8 crack
    283 ```
    284 
    285 > [!note] Severity ≠ foothold value
    286 > Record both dimensions. A *critical* data-exposure finding may yield no internal access; a *lower*-severity command injection on a dual-homed host may be your only route to the internal network. Don't force every result into one ranking — and report the dead ends too (hypothesis, prerequisites checked, mismatch, revisit trigger).
    287 
    288 ---
    289 
    290 ### Timeline building
    291 
    292 **What to look for** → the Activity Log (UTC) + `script`/tmux session logs become the report's **testing timeline**: kickoff → first foothold → lateral movement milestones → DA/EA → exfiltration proof → close-out. It does three jobs: proves coverage of the window, lets the SOC correlate your actions against their alerts (and *excludes* anything that wasn't you — that's an incident, say so), and anchors the attack-chain narrative in real times.
    293 
    294 ```text
    295 | Date/Time (UTC) | Milestone                                   | Evidence ref            |
    296 | 2026-08-27 09:12| Testing commenced (start notification sent) | Admin/comms-01          |
    297 | 2026-08-27 14:03| NTLMv2 captured (bsmith) via LLMNR poisoning| Findings/01/03-...      |
    298 | 2026-08-28 11:40| Domain Admin via DCSync as pramirez         | Findings/09/02-...      |
    299 | 2026-08-29 17:00| Testing concluded (stop notification sent)  | Admin/comms-14          |
    300 ```
    301 
    302 ---
    303 
    304 ### Appendices deep-dive — static vs dynamic
    305 
    306 **Static appendices** (same skeleton every engagement — build them once, reuse):
    307 - **Scope** — the *tested* scope as signed in the SoW/RoE, plus the exclusion list. If you discovered in-scope assets mid-engagement, note when they were added.
    308 - **Methodology** — which standard you followed (PTES / OSSTMM / NIST 800-115 / OWASP WSTG for web) and the phases executed. One page; don't pad.
    309 - **Severity ratings** — your CVSS version + the score→band mapping table, so a "7.4 High" is self-explanatory.
    310 - **Biographies** — required by some compliance regimes (e.g. PCI DSS); tester names, certs, roles.
    311 
    312 **Dynamic appendices** (built per engagement from your logs):
    313 - **Compromised Credentials** — account, privilege level, source, how obtained, disclosure/rotation status. Passwords truncated.
    314 - **Configuration Changes** — every System Modifications Log row, with revert status.
    315 - **Payloads / Artefacts** — Payload Log rows: filename, path, SHA256, cleanup status.
    316 - **Domain Password Analysis** — DPAT output if NTDS was cracked (Stage 08).
    317 - **OSINT findings** — exposed data found pre-engagement (breach corpora, public repos, exposed buckets) with collection dates.
    318 - **Additional Affected Scope** — long host/URL lists pulled out of individual findings.
    319 - **Cleanup exceptions** — anything that could NOT be reverted, with removal instructions for the client.
    320 
    321 > [!warning] Watch out
    322 > The appendices are where disputes get settled. If the client's SOC finds a `pentest01` account or a stray `svc.exe` six months later, the Payload/Changes appendices are the difference between "sanctioned testing artefact, documented" and "undeclared persistence — incident". Every row in those logs must be resolvable to an appendix entry.
    323 
    324 ---
    325 
    326 ### Tooling — where to actually write it
    327 
    328 **What to look for** → a local-first tool for client data (cloud sync may violate the client's data-storage policy). Note-taking during the engagement, then a reporting platform for assembly.
    329 
    330 ```text
    331 Notes (during):   Obsidian (local, Markdown, git-friendly — this vault) · CherryTree (hierarchical, no backlinks)
    332 Report platforms: SysReptor · pwndoc · Ghostwriter · Dradis · WriteHat   (free / self-hostable)
    333                   PlexTrac · AttackForge · VECTR                          (commercial)
    334 Redaction/shots:  Greenshot (solid-shape annotation) · asciinema (full session replay for review calls)
    335 ```
    336 [SysReptor](https://github.com/Syslifters/sysreptor) spins up fast and closes the gap between "Word + macros" and a full platform (findings DB, Markdown findings → PDF/HTML, self-hosted):
    337 ```bash
    338 curl -s https://docs.sysreptor.com/install.sh | bash    # docker-compose stack → https://localhost:8000
    339 ```
    340 [pwndoc](https://github.com/pwndoc/pwndoc) is the other mature self-hosted option: Node + Mongo, customizable DOCX templates, audit/vuln database with per-client reuse — better when the deliverable must be a branded Word document.
    341 
    342 > [!warning] Watch out
    343 > Cloud note tools (Notion, Evernote, hosted Obsidian sync) are fine for labs/CTFs — **check the data-handling terms before using them on live client data**, and the same applies to Grammarly/LanguageTool (they may transmit content to the cloud). For the CPTS exam itself, any tool that produces a clean PDF is fine — content beats platform. Comparison: 6 - Reporting Tips Tricks and Client Communication.
    344 
    345 ---
    346 
    347 ### Client comms during the engagement (real-world, not exam-graded)
    348 
    349 **What to look for** → a start notification at kickoff and a stop notification at the end of each testing day, so the client can correlate their alerts against your activity. Escalate *out of cadence* immediately for: new scope worth adding, a critical/RCE external finding, a host that looks down, or reaching Domain/Enterprise Admin.
    350 
    351 ```text
    352 Subject: [Firm] - <Client> <Type> - Testing Start Notification
    353 Tester(s) · Engagement type · Scope summary (see signed SoW) · Source IP(s) · Dates · Primary+Secondary contact
    354 Testing commences ~<time>. Daily stop notifications will follow. Contact us immediately re: unexpected behaviour.
    355 ```
    356 ```text
    357 Subject: [Firm] - <Client> <Type> - Day <N> Stop Notification
    358 Testing concluded for <date>. Today: <one line per activity area>. No unexpected availability impact observed.
    359 ```
    360 
    361 > [!tip] QA is not optional
    362 > Every report gets ≥1 round of *independent* QA (ideally two: technical accuracy, then cosmetics). Solo? Sleep on it and re-review after stepping away. Pre-delivery scan: acronyms spelled on first use · creds/PII/hashes redacted · screenshots cropped with a **professional hostname** (never `azzkicker@clientsmasher`) · strip tool banners like CrackMapExec's `(Pwn3d!)` · scan hashcat candidate passwords for offensive strings.
    363 
    364 ---
    365 
    366 ### Credential handling policy — the report is not a secrets store
    367 
    368 **What to look for** → every credential recovered in Stage 08 is live client data. Policy, end to end:
    369 
    370 ```text
    371 [ ] During:   creds land in ONE dedicated secrets store (encrypted KeePassXC DB / team vault) —
    372               never in Obsidian notes, chat, screenshots, or the Payload Log (use <REDACTED>)
    373 [ ] Report:   Compromised Credentials appendix lists account + source + how obtained,
    374               passwords TRUNCATED or redacted (e.g. Summer…!); report PDF is encrypted in transit
    375               (client-provided PGP key or a password out-of-band — never same channel)
    376 [ ] DPAT:     statistics only (cracked %, top patterns) — full plaintext passwords never ship
    377 [ ] Close-out: every recovered credential goes on the forced-rotation disclosure list;
    378               client confirms rotation; then the secrets store is wiped per data-retention policy
    379 [ ] Evidence:  raw dumps (NTDS, LSASS, SAM) encrypted at rest; destroyed on schedule after retest
    380 ```
    381 
    382 ---
    383 
    384 ### Cleanup + the retest — closing the engagement out
    385 
    386 **What to look for** → the engagement ends at *close-out*, not at DA. The cleanup register is written *from the Payload + Modifications logs you kept since day one*, not from memory.
    387 
    388 **Artifact cleanup checklist:**
    389 ```text
    390 [ ] Uploaded tools/binaries deleted (Payload Log: every row "Cleaned Up = Yes" + how)
    391 [ ] Webshells removed (every .aspx/.jsp/.php planted — check vhosts + staging dirs)
    392 [ ] SMB/temp shares removed; impacket-smbserver artefacts off target disks
    393 [ ] Scheduled tasks / services created for persistence — deleted
    394 [ ] Added ACEs / group memberships / shadow creds / SPNs — REVERTED (Stage 06: reverse every AD write)
    395 [ ] Test accounts removed — or exact usernames handed to the admin in the report appendix
    396 [ ] Added firewall/EDR exclusions reverted; PSExec-style services (PSEXESVC) gone
    397 [ ] vssadmin shadow copies created for NTDS.dit — deleted
    398 [ ] Listeners, dev servers, port-forwards, ligolo/chisel tunnels — stopped + uninstalled
    399 [ ] Anything that COULDN'T be reverted → documented in an appendix so the client
    400     doesn't mistake it for a real intrusion
    401 ```
    402 
    403 ```text
    404 Report lifecycle:  DRAFT  →  Report Review Meeting (walk findings high-level, gather clarifications)
    405                           →  incorporate feedback  →  FINAL   (some auditors reject a "DRAFT"-labelled report)
    406 
    407 Post-remediation retest — retest ONLY the original findings/hosts, with a time limit. Before/after table:
    408 | # | Severity | Finding                | Status        |
    409 | 1 | High     | SQL Injection          | Remediated    |
    410 | 4 | High     | Inadequate Egress Filt | Not Remediated|
    411 ```
    412 
    413 **Retest guidance:**
    414 - Retest **only** the original findings, on the originally affected hosts, with the same PoC steps — a finding is "Remediated" only if the *exact* original exploit path now fails.
    415 - Time-box it (typically 1-2 days) and state the retest window in the report.
    416 - Statuses: `Remediated` / `Partially Remediated` (root cause fixed, variant still works — explain) / `Not Remediated` / `Risk Accepted` (client signs off in writing — that's their call to make, not yours).
    417 - Update severity only on the retest report, never silently edit the original finding — the original report is the point-in-time record.
    418 
    419 > [!warning] Watch out
    420 > Don't let a retest become a new assessment — no fresh large-scale scans, no auditing the whole environment for new hosts hit by an old finding. If the environment changed significantly, *say so explicitly* rather than quietly rescoping. Stay an **impartial third party**: you *advise* remediation ("parameterise queries"), you never implement fixes or hand over rewritten code — that's a conflict-of-interest and an independence problem. Wipe the tester VM at close-out; encrypt retained evidence at rest. Pointers: 10 - Proof of Concept & Post-Engagement.
    421 
    422 > [!note] The paperwork that made it legal (pre-flight bookend)
    423 > Reporting is the back half of the engagement wrapper; the front half is signed contracts. Nothing proceeds before the **NDA** (bilateral is standard). Confirm the requester actually has signatory authority (CEO/CTO/CISO tier), then the doc set: NDA → Scoping Questionnaire → Scoping Document → Proposal/SoW → **Rules of Engagement** → Contractors Agreement (physical only) → Reports. Get a written **exclusion list** at kickoff even inside a confirmed scope. Detail: 5 - Pre-Engagement.
    424 
    425 ---
    426 
    427 ### 🔬 PoC, Cleanup & the Post-Engagement Lifecycle
    428 
    429 The report is graded on more than findings — the assessor wants proof, a clean environment, and a closed loop. This is methodology, not tooling.
    430 
    431 - **Proof of Concept** — reproducible evidence *per finding*, scaled to risk: documented step-by-step at minimum, an automated exploit script for the serious ones. Admins won't remediate a business-critical system on your word alone — the PoC is what forces the fix.
    432 - **Cleanup log** — keep a running list as you go: every uploaded tool/webshell/binary removed, every config change reverted. Anything you **can't** revert (a created local-admin account, an added ACL, a planted SPN) goes in a report appendix so the client can tell sanctioned testing from a real intrusion. This is also why [STAGE 6](/sheets/pentest-workflow/acl-and-object-abuse) says *reverse every AD write*.
    433 - **Lifecycle** — draft report → deliverable-acceptance/review with the client → final report → **post-remediation retest** with a before/after status table per finding (Open → Remediated / Risk Accepted).
    434 - **Stay in your lane** — you *advise* the fix ("parameterise the query", "enforce SMB signing") but never implement it — independence / conflict-of-interest.
    435 
    436 > [!tip] Capture the cleanup evidence *as you plant it*, not from memory at the end — a screenshot of the added account plus the exact removal command in one note. Deep dive: 10 - Proof of Concept & Post-Engagement.
    437 
    438 ---
    439 
    440 ### 🎓 CPTS exam reporting tips
    441 
    442 - **Flags ≠ report.** Every flag captured is one line of the attack chain; the grade comes from a commercial-grade report: exec summary, attack path narrative, findings with reproduction steps, appendices. A candidate with 12/14 flags and a strong report passes; 14/14 flags with a thin report fails.
    443 - **Reproduce yourself:** write every finding's steps so a stranger could redo them from the report alone — exact commands, full config, expected output. The grader *will* replay steps.
    444 - **Write as you go:** fill each finding template the day you prove it. Day-10 report-writing from memory is where evidence gaps appear.
    445 - **Standard domain-attack findings to expect:** LLMNR poisoning, password spraying hits, kerberoastable accounts, GPP cpassword, ASREProastable users, unconstrained delegation, weak ACL chains — pre-draft template skeletons for all of them before the exam and tailor on the day.
    446 - **Include a Domain Password Analysis** if you DCSync — graders expect the DPAT-style appendix and it's nearly free once you have the potfile.
    447 - **Deliverable hygiene:** exact filename per the exam briefing, PDF format, submitted before the deadline — late or misnamed submissions fail regardless of technical content.
    448 - **Report format:** clean PDF from any toolchain (Word, SysReptor, Obsidian export). Label the deliverable exactly as instructed in the exam briefing and respect the deadline — late = fail, regardless of content.
    449 
    450 ---
    451 
    452 > [!navigation] Continue the attack flow
    453 > **Previous:** [Domain Trusts and Cross-Forest](/sheets/pentest-workflow/domain-trusts-and-cross-forest)
    454 >
    455 > **Dashboard:** [HTB Pentest Attack Flow](/sheets/pentest-workflow/attack-flow-dashboard)
    456 >
    457 > **Next:** [Appendix — Worked Chains](/sheets/pentest-workflow/worked-chains)