Hell_is_haard
Challenge
Imported from local notes.md.
Solution
Original Notes
Hell_is_haard
Challenge Summary
- Given: a single file,
message.txt, containing 2048 integers. - Goal: recover the hidden flag from the convoluted message.
- Constraints: live CTF challenge, flag accepted by the platform was lowercase
udctf{...}for this challenge.
Initial Recon / Triage
- Observations: the title strongly suggested a Haar transform. The input length was
2048 = 2^11, which fits a recursive wavelet-style encoding. - File identification:
starting_files/message.txtis a Python-style list of signed integers. - Entry points: test inverse Haar layouts first, then inspect whether any residual error is structured rather than random.
Hypotheses & Approach
- Hypothesis 1: the ciphertext was produced by a recursive half-split Haar transform and needed an inverse decode.
- Hypothesis 2: if the decode looked close but not exact, the remaining error would likely live in the low-frequency coefficients and shift whole regions of plaintext at once.
Execution Steps (Reproducible)
Stage 1
Commands:
cd /root/bluehens2026CTF/Hell_is_haard
python3 artifacts/solve.py
Results:
- The best candidate came from the recursive half-split inverse Haar decode.
- The first 512 bytes decoded perfectly into a Longfellow translation of Dante's Inferno, Canto IX.
- The remaining bytes were not random noise. They were the same passage shifted by constant offsets over large blocks, which meant the coarse coefficients were still wrong.
Stage 2
Commands:
cd /root/bluehens2026CTF/Hell_is_haard
python3 artifacts/recover_exact.py
Results:
-
Comparing the decoded text against the normalized Gutenberg source showed exact block deltas of
0,91, and45for the first three 512-byte regions. -
Mapping those region offsets back through the forward Haar transform identified the coarse-coefficient correction.
-
After applying that correction, the text recovered almost exactly and exposed the inserted flag in the final region:
This is udctf{h3lp_1t5_c0ld_d0wn_h3r3}; She who is weeping on the right, Alecto; -
Live validation against the CTFd API confirmed the accepted flag was lowercase.
Stage 3
Commands:
python3 - <<'PY'
import requests
url = 'https://bluehens.ctfd.io/api/v1/challenges/attempt'
headers = {
'Authorization': 'Token ctfd_a8b34b5ad483685d7a9766b48cc00d5912f78707cd241ef656a60b03604b35d8',
'Content-Type': 'application/json',
}
flag = 'udctf{h3lp_1t5_c0ld_d0wn_h3r3}'
print(requests.post(url, headers=headers, json={'challenge_id': 41, 'submission': flag}, timeout=20).json())
PY
Results:
- The platform returned
correctforudctf{h3lp_1t5_c0ld_d0wn_h3r3}.
Artifacts Produced
artifacts/solve.py: inverse-Haar candidate testing.artifacts/probe_rounding.py: showed the main ambiguity was not per-fraction rounding.artifacts/compare_gutenberg.py: aligned the recovered plaintext with Dante Canto IX.artifacts/analyze_blocks.py: showed that later quarters differed by constant offsets.artifacts/recover_exact.py: derived the coarse correction and exposed the flag insertion.artifacts/decoded_best.txt: best initial plaintext candidate.artifacts/gutenberg_source_segment.txt: normalized source segment used for alignment.artifacts/redecoded_exact.txt: corrected plaintext reconstruction containing the flag.
Flag
udctf{h3lp_1t5_c0ld_d0wn_h3r3}