Birds Of Randomness
Birds Of Randomness is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
Birds Of Randomness attack path
Birds Of Randomness 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
Audit the source before touching the remote service.
Identify that each station point is d * G, where d is...
Use small prime-power factors of the EC order to...
Factor the recovered scalar into the three current...
Generate destination candidates by advancing every...
Source coverage
High source coverage
Status: complete. This article is generated from 4 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/Birds-of-Randomness/writeup.md
- htb-challenge/Crypto/Birds-of-Randomness/notes.md
- htb-challenge/Crypto/Birds-of-Randomness/memory-summary.md
- htb-challenge/Crypto/Birds-of-Randomness/hypothesis-board.md
Technical Walkthrough
Writeup
Challenge
- Name: Birds-of-Randomness
- Category: Crypto
- Difficulty: Medium
- Mode: hybrid
Summary
The service exposes a departing station as an elliptic-curve point. The source
shows each station is d G, where d = x y * z and the three PRNG state
components are small prime values. The EC group order has enough small factors
to recover this bounded scalar with Pohlig-Hellman plus CRT. Factoring the
scalar gives the current state values; the assignment to (x, y, z) is
ambiguous, but there are at most six permutations and the service gives six
guesses.
Artifact Inventory
The archive contains:
source.py: challenge service implementation and route generator.love_letter.txt: story hint and an explicit warning not to pursue image stego.forologia.jpg: story image, not needed for the solve.
The live service was available at <TARGET>:32403.
Analysis
source.py defines a route state (x, y, z) modulo 30269, 30307, and
30323. Each rotation multiplies the components by fixed constants. A station
is emitted only when all three components are prime, and the station coordinate
is the elliptic-curve point:
d * G where d = x * y * zThe largest possible station scalar is:
30269 * 30307 * 30323 = 27817185604309The supplied EC order includes small prime-power factors:
[2, 3, 49, 1487, 3761, 176489, 439693]Their product is greater than the maximum possible station scalar. That means
we can recover the departing scalar uniquely by solving the discrete log modulo
each small factor and combining the residues with CRT.
After recovering d, factoring it gives the three prime state values. Because
the published EC point only reveals the product, not which factor belongs to
which state component, the solve tries every unique permutation. This is still
bounded by six candidates, which matches the six mechapegion guesses offered by
the service.
Solve
Run:
python3 Crypto/Birds-of-Randomness/solve/solve.py --host <TARGET> --port 32403The solver:
- Parses the departing station coordinates from the service.
- Implements the curve arithmetic locally.
- Recovers the departing scalar using PH/CRT over the small order factors.
- Factors the scalar into the three current prime state components.
- Advances each possible state permutation to the next all-prime station.
- Submits the unique destination candidates until the service returns the flag.
The redacted live transcript is stored at
analysis/remote/solve-transcript-redacted.txt.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- Bounded EC scalars can make partial Pohlig-Hellman enough even when the full
group order has a large unfactored component.
- When a point reveals only a product of state components, preserve assignment
ambiguity and use the protocol's allowed guesses if the search space is small.
- Follow explicit challenge hints: the letter states the image is story-only, so
the source and live transcript are the correct evidence path.
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: Birds-of-Randomness
- Category: Crypto
- Difficulty: Medium
- Mode: hybrid
- Remote instance: none
- Start time: 2026-06-13T09:38: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
| File | Size | SHA256 | Type | Notes |
|---|---|---|---|---|
files/a12c738d-f603-4273-8c57-a8bbf7eec7ac.zip | 5263424 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 4 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-13T09:38:31Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-13T09:38:46Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-13T09:38:46Z | hypothesis recorded | hypothesis-board.md | Analyze the provided crypto source and remote transcript to identify weak randomness or coordinate-derived seed recovery, then reproduce the ticket/flag derivation. | Medium | Extract source, identify PRNG/seed/key schedule, and compare one local transcript with the remote prompt format. |
| 2026-06-13T09:38:46Z | research task | analysis/research/task-20260613T093846334465Z-3c583fdb.md | Research task created for advisory investigation | Medium | Record research output |
| 2026-06-13T09:40:01Z | source audit | analysis/source-audit.md | Source audit recorded | High | Gate before exploit |
| 2026-06-13T09:40:01Z | instrumentation plan | analysis/instrumentation-plan.md | Recover the next destination coordinates from one departing EC point. | High | Stop after two remote sessions fail with predicted coordinates; record transcript and reassess scalar recovery/state ambiguity before trying more guesses. |
| 2026-06-13T09:40:11Z | checkpoint recorded | analysis/checkpoint-hypothesis_ready-20260613T094011399920Z-29b537a6.md | Checkpoint for <secret redacted> | High | Use checkpoint to drive next decision |
| 2026-06-13T09:40:41Z | RAG query | analysis/rag/rag-query-20260613T094031344513Z-73b06268.txt | RAG helper exited 0; output saved | Medium | Record retrieval tag and validation |
| 2026-06-13T09:40:51Z | RAG record | analysis/rag-records.md | Retrieved memory tagged GENERIC | Medium | Validate or reject with live evidence |
| 2026-06-13T09:41:03Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-13T09:41:35Z | local memory record | analysis/local-memory-records.md | Prior local notes reviewed as fallback/advisory context | Medium | Validate against current evidence |
| 2026-06-13T09:41:35Z | evaluator | analysis/evaluator-20260613T094135484508Z-1f51436f.md | Proceed | High | Implement solve.py and submit predicted destination coordinates to the live service once. |
| 2026-06-13T09:43:06Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-13T09:44:04Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- Source audit confirms the route state is three small modular components:
x mod 30269, y mod 30307, and z mod 30323.
- Each station is emitted only after a rotation where all three components are
prime, and the published station coordinate is the elliptic-curve point
d G for d = x y * z.
- The maximum possible station scalar is `30269 30307 30323 =
27817185604309`.
- The supplied EC order has small prime-power factors
[2, 3, 49, 1487, 3761, 176489, 439693]; their product is
127593580992036069666, which is greater than the maximum station scalar.
- That means Pohlig-Hellman over only those small factors plus CRT uniquely
recovers d from the departing station point.
- Factoring
dgives the three current prime state values, but the assignment
to (x, y, z) is ambiguous. There are at most six permutations, matching the
six available mechapegion guesses.
solve/solve.pyimplements standalone curve arithmetic, PH/CRT scalar
recovery, state factoring, candidate generation, and socket submission.
- The live service accepted the third submitted destination candidate in the
captured run; the transcript is stored redacted under
analysis/remote/solve-transcript-redacted.txt.
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.
Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category: Crypto
- Challenge: Birds-of-Randomness
- Difficulty: Medium
- Source workspace:
<local workspace>
Validated Solve Chain
Concepts only. Do not include raw flags, reusable credentials, tokens, cookies, private keys, or live secrets.
- Audit the source before touching the remote service.
- Identify that each station point is
d * G, wheredis the product of
three small prime PRNG state components.
- Use small prime-power factors of the EC order to recover the bounded scalar
with Pohlig-Hellman plus CRT.
- Factor the recovered scalar into the three current prime state values.
- Generate destination candidates by advancing every possible assignment of
the three factors to (x, y, z).
- Submit the unique next-station candidates to the remote service; the six
allowed guesses cover the assignment ambiguity.
Reusable Lessons
- A full discrete log is not always needed when the scalar has a strict small
bound and enough small subgroup residues can exceed that bound under CRT.
- Protocol-provided retry limits can be a hint about a small ambiguity class.
- Source comments/story hints should be used to avoid low-value artifact rabbit
holes when the source already exposes the cryptographic primitive.
Dead Ends
- Image steganography was not pursued because
love_letter.txtexplicitly says
the image is only story material.
- The private CTF RAG query returned no challenge-specific shortcut; the solve
came from local source and math validation.
Tool Quirks
- Local Python did not have the challenge's
ecdsadependency, so the final
solve script implements the required elliptic-curve arithmetic directly.
- Sage/Z3 were missing, but they were not required for the PH/CRT approach.
Evidence Paths
files/extracted/birds_of_randomness/source.pyfiles/extracted/birds_of_randomness/love_letter.txtanalysis/math-notes.txtanalysis/source-audit.mdanalysis/instrumentation-plan.mdanalysis/evaluator-20260613T094135484508Z-1f51436f.mdanalysis/remote/solve-transcript-redacted.txtsolve/solve.pyloot/flag.txt
Ingestion Decision
- Proposed for LightRAG: yes
- 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 | Analyze the provided crypto source and remote transcript to identify weak randomness or coordinate-derived seed recovery, then reproduce the ticket/flag derivation. | Scenario references coordinates, a train ticket, and randomness; challenge has both source ZIP and remote service. | Extract source, identify PRNG/seed/key schedule, and compare one local transcript with the remote prompt format. | Medium | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit Condition |
|---|
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 Birds Of Randomness, 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.