Challenge / Misc

ShinyHunter

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

EasyPublished 2024-12-23Sanitized local writeup

Scenario

ShinyHunter attack path

ShinyHunter 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 Misc evidence, validation, and reusable operator lessons.

ShinyHunter sanitized attack graph

Walkthrough flow

01

Artifact review

02

Hypothesis

03

Validated solve path

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.

  • Misc/ShinyHunter/writeup.md
  • htb-challenge/Misc/ShinyHunter/notes.md
  • htb-challenge/Misc/ShinyHunter/memory-summary.md
  • htb-challenge/Misc/ShinyHunter/hypothesis-board.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Misc__ShinyHunter__memory-summary.md.2d6dccf4c8.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Misc__ShinyHunter__notes.md.4a793affee.md

Technical Walkthrough

Writeup

Challenge

  • Name: ShinyHunter
  • Category: Misc
  • Difficulty: Easy
  • Mode: hybrid

Summary

The challenge is a Python game service where a shiny starter unlocks the flag. The service prints a random device MAC address before asking for input. Source review showed the shiny outcome is deterministic from that MAC address and the integer elapsed boot second when the player name is submitted. The solve reconnects until a MAC has a near-term shiny second, waits for that second, submits the name and predicted starter choice, and captures the reward.

Artifact Inventory

  • files/a12c7342-e7bf-44f3-9315-d4c039f10769.zip: original challenge archive.
  • files/extracted/challenge/chall.py: Python service source.
  • files/extracted/Dockerfile: service runs chall.py through socat.
  • analysis/artifact-inventory.json: archive hash and extracted file listing.
  • loot/remote-transcript.txt: successful remote interaction transcript, kept in loot/ because it contains the raw flag.

Analysis

chall.py generates and prints a device MAC immediately. Later, after the intro dialog and player-name input, it computes an integer elapsed time from time.time() - boot_time. The initial seed is:

text
int(elapsed_time) + int(device_mac_without_colons, 16)

That value is passed through the service LCG. Python random then generates the trainer IDs and each starter's PID. The shiny condition is:

text
((tid ^ sid) ^ (pid & 0xffff) ^ (pid >> 16)) < 8

Since the MAC is printed and the elapsed second can be controlled by delaying input, the solve can predict which future second and starter choice will produce a shiny. A first live attempt confirmed the RNG formula but showed the timing base was about two seconds early, so the final solver uses a calibrated send offset.

Solve

Run:

bash
cd <local workspace>
python3 -u Misc/ShinyHunter/solve/solve.py --host <TARGET> --port 32211 --send-offset 2.35
python3 scripts/challenge_harness.py capture-flag Misc/ShinyHunter --from loot/flag-candidate.txt

The solver parses the MAC banner, screens future elapsed seconds for a shiny starter, reconnects on bad MACs, waits for a predicted second, submits a normal player name and starter choice, and writes the captured flag candidate under loot/.

Flag

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

Lessons

For timing-based RNG services, the visible seed material is only half the problem. The client-side timing base must be calibrated against the service clock. Here, transcript comparison against the predicted stats showed the first input was two seconds early, and a calibrated send offset made the exploit reliable.

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: ShinyHunter
  • Category: Misc
  • Difficulty: Easy
  • Mode: hybrid
  • Remote instance: <TARGET>:32211
  • Start time: 2026-06-09T08:41:13Z
  • 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/a12c7342-e7bf-44f3-9315-d4c039f10769.zip5219<hash redacted>Zip archive data, at least v2.0 to extract, compression method=deflatezip entries: 4 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-09T08:41:13Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-09T08:41:13Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-09T08:43:37Zhypothesis recordedhypothesis-board.mdUse the printed MAC address and controllable elapsed time before name submission to predict a seed where one starter Poketmon is shiny, then submit the matching starter choice to the live service.MediumWrite a local predictor for MAC plus target elapsed second, test source logic locally, then run against the remote with bounded reconnects until a near-term shiny second appears.
2026-06-09T08:43:37Zcheckpoint recordedanalysis/checkpoint-analysis-20260609T084337513193Z-b746a743.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-09T08:44:17ZRAG queryanalysis/rag/rag-query-20260609T084403639093Z-ffe42d9d.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-09T08:45:04ZRAG recordanalysis/rag-records.mdRetrieved memory tagged GENERICMediumValidate or reject with live evidence
2026-06-09T08:45:04Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-09T08:45:04Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-09T08:45:05Zevaluatoranalysis/evaluator-20260609T084505037810Z-5a453b70.mdProceedHighImplement solve/solve.py and run it against <TARGET>:32211.
2026-06-09T09:15:13Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-09T09:15:51Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

-

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: Misc
  • Challenge: ShinyHunter
  • 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
1Use the printed MAC address and controllable elapsed time before name submission to predict a seed where one starter Poketmon is shiny, then submit the matching starter choice to the live service.chall.py derives initial_seed from int(elapsed_time + mac_int), generates TID/SID and starter PIDs with Python random, and prints the flag only when chosen_poketmon['is_shiny'] is true.Write a local predictor for MAC plus target elapsed second, test source logic locally, then run against the remote with bounded reconnects until a near-term shiny second appears.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition

Memory Summary

approval_required: true

Sanitized Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: Misc
  • Challenge: ShinyHunter
  • 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: ShinyHunter
  • Category: Misc
  • Difficulty: Easy
  • Mode: hybrid
  • Remote instance: <TARGET>:32211
  • Start time: 2026-06-09T08:41:13Z
  • 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/a12c7342-e7bf-44f3-9315-d4c039f10769.zip5219<hash redacted>Zip archive data, at least v2.0 to extract, compression method=deflatezip entries: 4 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-09T08:41:13Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-09T08:41:13Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-09T08:43:37Zhypothesis recordedhypothesis-board.mdUse the printed MAC address and controllable elapsed time before name submission to predict a seed where one starter Poketmon is shiny, then submit the matching starter choice to the live service.MediumWrite a local predictor for MAC plus target elapsed second, test source logic locally, then run against the remote with bounded reconnects until a near-term shiny second appears.
2026-06-09T08:43:37Zcheckpoint recordedanalysis/checkpoint-analysis-20260609T084337513193Z-b746a743.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-09T08:44:17ZRAG queryanalysis/rag/rag-query-20260609T084403639093Z-ffe42d9d.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-09T08:45:04ZRAG recordanalysis/rag-records.mdRetrieved memory tagged GENERICMediumValidate or reject with live evidence
2026-06-09T08:45:04Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-09T08:45:04Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-09T08:45:05Zevaluatoranalysis/evaluator-20260609T084505037810Z-5a453b70.mdProceedHighImplement solve/solve.py and run it against <TARGET>:32211.
2026-06-09T09: <REDACTED>
2026-06-09T09:15:51Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

-

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 challenge like a timed puzzle booth. If the task is too fast or repetitive for a person, the intended move is usually to write a small helper that performs the simple action perfectly.

For ShinyHunter, 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.