Challenge / Quantum

Noisy Vault

Noisy Vault is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator

EasyPublished 2025-05-16Sanitized local writeup

Scenario

Noisy Vault attack path

Noisy Vault 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 Quantum evidence, validation, and reusable operator lessons.

Noisy Vault sanitized attack graph

Walkthrough flow

01

Circuit constraints

02

State manipulation

03

Measurement strategy

04

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.

100% coverage
Evidence verdict

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.

  • Quantum/Noisy-Vault/writeup.md
  • htb-challenge/Quantum/Noisy-Vault/notes.md
  • htb-challenge/Quantum/Noisy-Vault/memory-summary.md
  • htb-challenge/Quantum/Noisy-Vault/hypothesis-board.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Quantum__Noisy-Vault__memory-summary.md.b28150c63c.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Quantum__Noisy-Vault__notes.md.bb3ac55d53.md

Technical Walkthrough

Writeup

Challenge

  • Name: Noisy-Vault
  • Category: Quantum
  • Difficulty: Easy
  • Mode: hybrid

Summary

This challenge is a source-led hybrid oracle solve, not a complicated quantum-correction problem. The provided server.py contradicts the scenario blurb and shows the real service: 64 data qubits, 16 ancillas, a single oracle query, and one exact 64-bit unlock attempt. The solve is to submit a validator-safe layer of 16 data-controlled CNOTs into the ancillas, collect the noisy measurement counts, reverse each Qiskit count key to align it with the server's stored 64-bit access code, majority-vote each bit, and submit the recovered code once.

Artifact Inventory

Relevant artifacts and surfaces:

  • files/extracted/quantum_noisy_vault/server.py: authoritative challenge logic
  • analysis/source-audit.md: condensed source-derived behavior summary
  • analysis/local-validation.txt: local Qiskit proof that the returned count string must be reversed
  • analysis/oracle-counts.json: sanitized live oracle counts from the single remote query
  • analysis/remote-session.txt: sanitized remote interaction transcript with the flag redacted
  • Remote target: <TARGET>:31538

Analysis

The key correction is that the scenario text is wrong for this artifact set. server.py defines visible_bits = 64 and ancilla_qubits = 16, prepares a 64-bit computational-basis access code on data qubits 0..63, and allows exactly one oracle call plus one exact unlock attempt. Those facts come directly from files/extracted/quantum_noisy_vault/server.py and are summarized in analysis/source-audit.md.

The validator does not care about quantum usefulness; it checks structural activity after transpilation. A candidate circuit must preserve at least 16 data-ancilla links and at least 4 active ancillas in the compiled circuit. A simple layer of CX:0,64; ... ; CX:15,79 satisfies both requirements while keeping the data register unchanged in the ideal circuit, because the data qubits are controls and the ancillas are targets.

The only subtlety that can burn the one unlock attempt is Qiskit bit ordering. The server measures qubit i into classical bit i, but Qiskit displays count strings with the highest classical bit on the left. analysis/local-validation.txt proves this locally with a seeded 64-bit bitstring: the noiseless count string matches that seeded value only after reversing the returned bitstring.

With that bit-order proof in hand, the live path is straightforward. The oracle returns a large counts dictionary over 4096 shots. Reversing each count key before tallying per-qubit votes yields the 64-bit access code. The sanitized remote evidence is stored in analysis/oracle-counts.json and analysis/remote-session.txt.

Solve

The full solve lives in solve/solve.py.

It performs these steps:

  1. Connect to the remote service.
  2. Send menu option 1.
  3. Submit the fixed 16-gate CNOT layer from data qubits 0..15 into ancillas 64..79.
  4. Parse the returned counts JSON.
  5. Reverse each count key, majority-vote each bit position, and reconstruct the 64-bit access code.
  6. Send menu option 2.
  7. Submit the recovered code once and write the returned flag to analysis/flag-candidate.txt for harness capture.

After capture, transient artifacts were sanitized so the raw flag remains only in loot/flag.txt.

Flag

Raw flag is stored in loot/flag.txt and intentionally not reproduced here.

Lessons

  • For HTB source-backed hybrid challenges, treat the provided source as the authority when it conflicts with the scenario text.
  • When a quantum service returns Qiskit counts, validate classical-bit ordering before using a one-shot decoded answer.
  • Structural validator challenges can often be solved by the cheapest circuit that satisfies the policy while preserving the measured register in the ideal case.

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: Noisy-Vault
  • Category: Quantum
  • Difficulty: Easy
  • Mode: hybrid
  • Remote instance: <TARGET>:31538
  • Start time: 2026-06-07T16:45:31Z
  • 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

FileSizeSHA256TypeNotes
files/a160415e-eefd-4508-86a0-e2322131b4c9.zip2849<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 2 shown in artifact inventory JSON
files/extracted/quantum_noisy_vault/server.py9239<hash redacted>Python script text executable, Unicode text, UTF-8 text

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-07T16:45:31Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-07T16:45:54Zartifact inventoryanalysis/artifact-inventory.json2 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T16:45:54Zhypothesis recordedhypothesis-board.mdAnalyze server.py to understand the 13-qubit noisy process, then construct a 13-bit/9-bit answer strategy that mitigates or decodes the noise before making the one-shot remote submission.MediumRead server.py, identify exact input/output protocol, qubit roles, noise model, scoring condition, and local simulation requirements.
2026-06-07T16:46:25Zcheckpoint recordedanalysis/checkpoint-hypothesis_ready-20260607T164625723210Z-5c67def4.mdCheckpoint for <secret redacted>HighUse checkpoint to drive next decision
2026-06-07T16:46:25Zresearch taskanalysis/research/task-20260607T164625725654Z-c674d622.mdResearch task created for advisory investigationMediumRecord research output
2026-06-07T16:47:00Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-07T16:49:56ZRAG queryanalysis/rag/rag-query-20260607T164948196417Z-7db78a4e.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-07T16:53:56Zbranch closedhypothesis-board.mdSource code disproves the scenario text: the real service uses 64 data qubits, 16 ancillas, and one exact 64-bit unlock attempt.HighRerank hypotheses
2026-06-07T16:53:57Zhypothesis recordedhypothesis-board.mdUse 16 data-controlled CNOTs into ancillas to satisfy structural validation while preserving the 64 data bits, then reverse each returned Qiskit count key and majority-vote the remote oracle output to recover the exact 64-bit access code.HighRun the single oracle query with the 16 CX layer, parse counts, reverse each bitstring, and compute per-qubit majority before the one unlock attempt.
2026-06-07T16:54:07Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-07T16:54:08ZRAG recordanalysis/rag-records.mdRetrieved memory tagged GENERICMediumValidate or reject with live evidence
2026-06-07T16:54:14Zevaluatoranalysis/evaluator-20260607T165414554775Z-05d22d98.mdProceedHighImplement solve/solve.py, run the exploit gate, query the remote oracle once, decode the key, and submit it immediately.
2026-06-07T17:00:24Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-07T17:02:08Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • server.py is the authority, not the scenario text: the service uses 64 data qubits, 16 ancillas, one oracle call, 4096 shots, and one exact 64-bit unlock submission.
  • A layer of 16 CX:data,ancilla gates satisfies the validator because it creates 16 data-ancilla links and touches all 16 ancillas while leaving the data qubits unchanged in the ideal circuit.
  • analysis/local-validation.txt proves the Qiskit count strings must be reversed before reconstructing the access code: the noiseless measurement key matches the seeded local bitstring only after reversing the returned bitstring.
  • The live oracle output was captured in analysis/oracle-counts.json; reversing each count key and majority-voting across the 4096-shot distribution recovered the correct access code.
  • solve/solve.py reproduced the full hybrid path against the live target and the validated flag was captured into loot/flag.txt.

RAG / Advisory Memory

RAG output is advisory only. Record evaluated retrievals with:

bash
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.

Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: Quantum
  • Challenge: Noisy-Vault
  • Difficulty: 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.

RankPathEvidenceMissing ProofCheapest ValidationConfidenceStatus
1Analyze server.py to understand the 13-qubit noisy process, then construct a 13-bit/9-bit answer strategy that mitigates or decodes the noise before making the one-shot remote submission.Challenge provides source code and a live target; scenario describes 13 qubits, 9-bit access code, and ancilla-based noise mitigation.Read server.py, identify exact input/output protocol, qubit roles, noise model, scoring condition, and local simulation requirements.MediumActive
1Use 16 data-controlled CNOTs into ancillas to satisfy structural validation while preserving the 64 data bits, then reverse each returned Qiskit count key and majority-vote the remote oracle output to recover the exact 64-bit access code.files/extracted/quantum_noisy_vault/server.py,analysis/local-validation.txtRemote oracle must return counts consistent with the locally validated bit ordering and majority-vote assumption.Run the single oracle query with the 16 CX layer, parse counts, reverse each bitstring, and compute per-qubit majority before the one unlock attempt.HighActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition
Analyze server.py to understand the 13-qubit noisy process, then construct a 13-bit/9-bit answer strategy that mitigates or decodes the noise before making the one-shot remote submission.files/extracted/quantum_noisy_vault/server.pySource code disproves the scenario text: the real service uses 64 data qubits, 16 ancillas, and one exact 64-bit unlock attempt.Only if the deployed remote behavior contradicts the provided source.

Memory Summary

approval_required: true

Sanitized Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: Quantum
  • Challenge: Noisy-Vault
  • Difficulty: 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: Noisy-Vault
  • Category: Quantum
  • Difficulty: Easy
  • Mode: hybrid
  • Remote instance: <TARGET>:31538
  • Start time: 2026-06-07T16:45:31Z
  • 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

FileSizeSHA256TypeNotes
files/a160415e-eefd-4508-86a0-e2322131b4c9.zip2849<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 2 shown in artifact inventory JSON
files/extracted/quantum_noisy_vault/server.py9239<hash redacted>Python script text executable, Unicode text, UTF-8 text

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-07T16:45:31Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-07T16:45:54Zartifact inventoryanalysis/artifact-inventory.json2 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-07T16:45:54Zhypothesis recordedhypothesis-board.mdAnalyze server.py to understand the 13-qubit noisy process, then construct a 13-bit/9-bit answer strategy that mitigates or decodes the noise before making the one-shot remote submission.MediumRead server.py, identify exact input/output protocol, qubit roles, noise model, scoring condition, and local simulation requirements.
2026-06-07T16:46:25Zcheckpoint recordedanalysis/checkpoint-hypothesis_ready-20260607T164625723210Z-5c67def4.mdCheckpoint for <secret redacted>HighUse checkpoint to drive next decision
2026-06-07T16:46:25Zresearch taskanalysis/research/task-20260607T164625725654Z-c674d622.mdResearch task created for advisory investigationMediumRecord research output
2026-06-07T16:47:00Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-07T16:49:56ZRAG queryanalysis/rag/rag-query-20260607T164948196417Z-7db78a4e.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-07T16:53:56Zbranch closedhypothesis-board.mdSource code disproves the scenario text: the real service uses 64 data qubits, 16 ancillas, and one exact 64-bit unlock attempt.HighRerank hypotheses
2026-06-07T16:53:57Zhypothesis recordedhypothesis-board.mdUse 16 data-controlled CNOTs into ancillas to satisfy structural validation while preserving the 64 data bits, then reverse each returned Qiskit count key and majority-vote the remote oracle output to recover the exact 64-bit access code.HighRun the single oracle query with the 16 CX layer, parse counts, reverse each bitstring, and compute per-qubit majority before the one unlock attempt.
2026-06-07T16:54:07Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-07T16:54:08ZRAG recordanalysis/rag-records.mdRetrieved memory tagged GENERICMediumValidate or reject with live evidence
2026-06-07T16:54:14Zevaluatoranalysis/evaluator-20260607T165414554775Z-05d22d98.mdProceedHighImplement solve/solve.py, run the exploit gate, query the remote oracle once, decode the key, and submit it immediately.
2026-06-07T17: <REDACTED>
2026-06-07T17:02:08Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • server.py is the authority, not the scenario text: the service uses 64 data qubits, 16 ancillas, one oracle call, 4096 shots, and one exact 64-bit unlock submission.
  • A layer of 16 CX:data,ancilla gates satisfies the validator because it creates 16 data-ancilla links and touches all 16 ancillas while leaving the data qubits unchanged in the ideal circuit.
  • analysis/local-validation.txt proves the Qiskit count strings must be reversed before reconstructing the access code: the noiseless measurement key matches the seeded local bitstring only after reversing the returned bitstring.
  • The live oracle output was captured in analysis/oracle-counts.json; reversing each count key and majority-voting across the 4096-shot distribution recovered the correct access code.
  • solve/solve.py reproduced the full hybrid path against the live target and the validated flag was captured into loot/flag.txt.

RAG / Advisory Memory

RAG output is advisory only. Record evaluated retrievals with:

bash
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.

Technical analogy

How to remember this solve

Think of the quantum circuit like a fragile sequence of switches. The solve is about arranging the switches so the final measurement lands in the one state that unlocks the flag.

For Noisy Vault, 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.