The Last Dance
The Last Dance is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
The Last Dance attack path
The Last Dance is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Objective
Challenge walkthrough focused on Crypto evidence, validation, and reusable operator lessons.
Walkthrough flow
Challenge parameters
Weak assumption
Recovered secret state
Proof captured
Source coverage
High source coverage
Status: complete. This article is generated from 6 sanitized Markdown sources and keeps raw flags, credentials, keys, cookies, and reusable secrets out of the rendered blog.
High confidence: the page is reconstructed from a primary walkthrough plus multiple supporting notes or evidence sources. Treat the chain as source-backed, while still checking the listed source files for sensitive values.
- Crypto/The-Last-Dance/writeup.md
- htb-challenge/Crypto/The-Last-Dance/notes.md
- htb-challenge/Crypto/The-Last-Dance/memory-summary.md
- htb-challenge/Crypto/The-Last-Dance/hypothesis-board.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Crypto__The-Last-Dance__memory-summary.md.2de2a2b240.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Crypto__The-Last-Dance__notes.md.abaaec9a96.md
Technical Walkthrough
Writeup
Challenge
- Name: The-Last-Dance
- Category: Crypto
- Difficulty: Very Easy
- Mode: file
Summary
The challenge source uses ChaCha20 twice with the same random key and nonce: once on a fully known plaintext message and once on the secret flag. Because ChaCha20 is a stream cipher, reusing the same keystream lets us recover the keystream from the known plaintext/ciphertext pair and decrypt the flag ciphertext directly.
Artifact Inventory
files/a12c73a6-d316-4483-a59b-9874ca90e0f3.zip— original encrypted challenge archive.analysis/<password redacted>— successful archive decryption validation.analysis/extracted/crypto_the_last_dance/source.py— vulnerable source code.analysis/extracted/crypto_the_last_dance/out.txt— nonce, known-message ciphertext, and flag ciphertext.analysis/solve-result.txt— recovered flag before harness capture.solve/solve.py— deterministic decryptor.
Reference analysis/artifact-inventory.json and summarize the relevant files or remote surface.
Analysis
source.py generates one random key and one random nonce, then encrypts both a fully known plaintext message and the secret flag with ChaCha20 using the same (key, nonce) pair. For a stream cipher this is catastrophic: ciphertext = plaintext XOR keystream. Since the long plaintext message is known, XORing it with its ciphertext reveals the keystream bytes. The same keystream bytes then decrypt the flag ciphertext.
Solve
The solver parses out.txt, converts the two ciphertexts from hex, XORs the known plaintext with its ciphertext to recover the keystream, then XORs that keystream prefix with the encrypted flag to recover the plaintext flag.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
When a stream cipher reuses the same key and nonce across two messages, the problem often collapses into simple XOR algebra. If one plaintext is known, recover the keystream from it first before trying anything more complicated.
Source-Backed Dossier
The sections below are merged from companion Markdown notes for the same case. They are rendered after sanitization so the article stays precise without publishing raw flags, credentials, or target-specific secrets.
Notes
Scope
- Challenge: The-Last-Dance
- Category: Crypto
- Difficulty: Very Easy
- Mode: file
- Remote instance: none
- Start time: 2026-06-07T09:21:26Z
- Operator: harness
- State file:
challenge-state.json
Harness Status
- Current phase: see
challenge-state.json - Next allowed actions: see
next-action.json - Raw flags and sensitive material stay in
loot/only. Do not paste them here.
Artifact Inventory
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
files/a12c73a6-d316-4483-a59b-9874ca90e0f3.zip | 1260 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 3 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-07T09:21:26Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-07T09:21:26Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T09:21:26Z | session bootstrap | notes.md | Challenge metadata, scenario, and prior context seeded into workspace | High | Record initial hypothesis and research |
| 2026-06-07T09:21:26Z | hypothesis recorded | hypothesis-board.md | initial triage from supplied challenge metadata | Medium | inventory files / inspect app surface / map routes depending on category |
| 2026-06-07T09:21:26Z | research task | analysis/research/task-20260607T092126176454Z-6b4a1068.md | Research task created for advisory investigation | Medium | Record research output |
| 2026-06-07T09:23:10Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-07T09:23:29Z | research skip | analysis/research/research-skip.md | Research intentionally skipped with recorded reason | Medium | Gate before exploit |
| 2026-06-07T09:24:33Z | checkpoint recorded | analysis/checkpoint-analysis-20260607T092433754665Z-2f1000d9.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-07T09:24:34Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-07T09:24:34Z | Decrypted flag via ChaCha20 keystream reuse | analysis/extracted/crypto_the_last_dance/source.py, analysis/extracted/crypto_the_last_dance/out.txt, analysis/solve-result.txt | The source reused the same key and nonce for a known plaintext message and the flag. XORing the known plaintext with its ciphertext recovered the keystream, which directly decrypted the flag ciphertext. | High | Capture the flag through the harness and complete the workspace. |
| 2026-06-07T09:24:34Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
-
RAG / Advisory Memory
RAG output is advisory only. Record evaluated retrievals with:
scripts/challenge_harness.py rag-record <workspace> --query "..." --tag MATCHED|PARTIAL|MISSING|<secret redacted>|GENERIC --validation "..."Secrets/Flags
Raw flags and sensitive material stay in loot/ only. Use scripts/challenge_harness.py capture-flag to validate and record flag capture without printing the value.
Scenario
To be accepted into the upper class of the Berford Empire, you had to attend the annual Cha-Cha Ball at the High Court. Little did you know that among the many aristocrats invited, you would find a burned enemy spy. Your goal quickly became to capture him, which you succeeded in doing after putting something in his drink. Many hours passed in your agency interrogation room, and you eventually learned important information about the enemy agency secret communications. Can you use what you learned to decrypt the rest of the messages?
Operator Question
Analyze the provided Crypto challenge artifact, identify the cipher or cryptographic weakness, decrypt the messages reproducibly, and capture the HTB flag.
Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category: Crypto
- Challenge: The-Last-Dance
- Difficulty: Very Easy
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
1.
Reusable Lessons
-
Dead Ends
-
Tool Quirks
-
Evidence Paths
-
Ingestion Decision
- Proposed for LightRAG: yes/no
- Requires user approval before ingestion: yes
Hypothesis Board
Keep no more than 3 active hypotheses on Easy/Medium and 5 on Hard unless the user explicitly asks for breadth.
| Rank | Path | Evidence | Missing Proof | Cheapest Validation | Confidence | Status |
|---|---|---|---|---|---|---|
| 1 | initial triage from supplied challenge metadata | challenge name, category, difficulty, scenario, and remote target were provided by operator | inventory files / inspect app surface / map routes depending on category | Medium | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit Condition |
|---|
Memory Summary
approval_required: true
Sanitized Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category: Crypto
- Challenge: The-Last-Dance
- Difficulty: Very Easy
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
1.
Reusable Lessons
-
Dead Ends
-
Tool Quirks
-
Evidence Paths
-
Ingestion Decision
- Proposed for LightRAG: yes/no
- Requires user approval before ingestion: yes
Notes
Notes
Scope
- Challenge: The-Last-Dance
- Category: Crypto
- Difficulty: Very Easy
- Mode: file
- Remote instance: none
- Start time: 2026-06-07T09:21:26Z
- Operator: harness
- State file:
challenge-state.json
Harness Status
- Current phase: see
challenge-state.json - Next allowed actions: see
next-action.json - Raw flags and sensitive material stay in
loot/only. Do not paste them here.
Artifact Inventory
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
files/a12c73a6-d316-4483-a59b-9874ca90e0f3.zip | 1260 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 3 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-07T09:21:26Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-07T09:21:26Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-07T09:21:26Z | session bootstrap | notes.md | Challenge metadata, scenario, and prior context seeded into workspace | High | Record initial hypothesis and research |
| 2026-06-07T09:21:26Z | hypothesis recorded | hypothesis-board.md | initial triage from supplied challenge metadata | Medium | inventory files / inspect app surface / map routes depending on category |
| 2026-06-07T09:21:26Z | research task | analysis/research/task-20260607T092126176454Z-6b4a1068.md | Research task created for advisory investigation | Medium | Record research output |
| 2026-06-07T09:23:10Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-07T09:23:29Z | research skip | analysis/research/research-skip.md | Research intentionally skipped with recorded reason | Medium | Gate before exploit |
| 2026-06-07T09:24:33Z | checkpoint recorded | analysis/checkpoint-analysis-20260607T092433754665Z-2f1000d9.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-07T09: <REDACTED> | |||||
2026-06-07T09: <REDACTED>, analysis/extracted/crypto_the_last_dance/out.txt, analysis/solve-result.txt | The source reused the same key and nonce for a known plaintext message and the flag. XORing the known plaintext with its ciphertext recovered the keystream, which directly decrypted the flag ciphertext. | High | Capture the flag through the harness and complete the workspace. | ||
| 2026-06-07T09:24:34Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
-
RAG / Advisory Memory
RAG output is advisory only. Record evaluated retrievals with:
scripts/challenge_harness.py rag-record <workspace> --query "..." --tag MATCHED|PARTIAL|MISSING|<secret redacted>|GENERIC --validation "..."Secrets/Flags
Raw flags and sensitive material stay in loot/ only. Use scripts/challenge_harness.py capture-flag to validate and record flag capture without printing the value.
Scenario
To be accepted into the upper class of the Berford Empire, you had to attend the annual Cha-Cha Ball at the High Court. Little did you know that among the many aristocrats invited, you would find a burned enemy spy. Your goal quickly became to capture him, which you succeeded in doing after putting something in his drink. Many hours passed in your agency interrogation room, and you eventually learned important information about the enemy agency secret communications. Can you use what you learned to decrypt the rest of the messages?
Operator Question
Analyze the provided Crypto challenge artifact, identify the cipher or cryptographic weakness, decrypt the messages reproducibly, and capture the HTB flag.
Technical analogy
How to remember this solve
Think of the challenge like a locked box where the lock is mathematical but slightly flawed. The goal is not to smash the box; it is to notice which part of the lock repeats, leaks, or trusts the wrong assumption.
For The Last Dance, keep the mental model simple: identify the trusted assumption, prove it with the smallest safe test, then automate or repeat only the part that directly leads to the flag.