Challenge / Hardware

Secret Treasures

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

MediumPublished 2024-10-21Sanitized local writeup

Scenario

Secret Treasures attack path

Secret Treasures 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 Hardware evidence, validation, and reusable operator lessons.

Secret Treasures sanitized attack graph

Walkthrough flow

01

Extracted the challenge archive and identified an ARM...

02

Reversed the firmware serial path: /dev/ttyS0, 38400...

03

Reversed the firmware PRNG and flash addressing path:

04

Recovered the decimal seed with a local C brute-force...

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.

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.

  • Hardware/Secret-Treasures/writeup.md
  • htb-challenge/Hardware/Secret-Treasures/notes.md
  • htb-challenge/Hardware/Secret-Treasures/memory-summary.md
  • htb-challenge/Hardware/Secret-Treasures/hypothesis-board.md

Technical Walkthrough

Writeup

Challenge

  • Name: Secret-Treasures
  • Category: Hardware
  • Difficulty: Medium
  • Mode: file

Summary

The challenge provides an ARM firmware binary, a W25Q128 flash dump, and a Saleae input trace. The firmware showed that the input channel is an 8-byte decimal passcode used as a PRNG seed. The PRNG output is then converted into flash addresses, one byte at a time, to print the flag.

I validated the firmware logic locally, recovered the decimal seed, and reproduced the 49-byte flag extraction from the flash dump with solve/solve.py. The raw flag is kept only in loot/flag.txt.

Artifact Inventory

  • files/a12c7357-88da-4145-a579-1bb343be1776.zip: original challenge archive.
  • analysis/extracted/hw_secret/embedded_software: 32-bit ARM ELF.
  • analysis/extracted/hw_secret/flash_memory_dump.bin: 16 MiB flash image.
  • analysis/extracted/hw_secret/input_channel_trace.sal: Saleae capture archive; extracted metadata confirms a Logic 8 capture with digital sampling at 50 MHz.
  • Full hashes and file types are in analysis/artifact-inventory.json, analysis/file-types.txt, and analysis/sha256sums.txt.

Analysis

Static analysis was enough to avoid full hardware emulation:

  • analysis/embedded-strings.txt identified wiringPi serial/SPI usage, /dev/ttyS0, serialGetchar, strtoul, W25Q128_init, get_UniqieID, get_secret, and random_generator.
  • analysis/objdump-disasm.txt showed main opening /dev/ttyS0 at 38400 baud, reading 8 serial bytes, echoing them, and parsing the input as a base-10 integer via strtoul.
  • The same disassembly showed the parsed integer is stored as the global PRNG state.
  • random_generator updates the state as state = state * 0x41c64e6d + 0x0008042a modulo 2^32, then returns state % 0x00ffffff.
  • main calls the PRNG three times per output byte. It takes the high byte from the first result, the middle byte from the second result, and the low byte from the third result to build a 24-bit flash address.
  • The output loop runs while the byte counter is less than or equal to 48, so it emits 49 bytes.
  • get_secret sends SPI command 0x03 plus the 24-bit address and copies the returned flash byte.

Public research was used only as a sanity check. Saleae documentation confirmed the <SALEAE> binary header conventions, while sigrok documentation explained why direct .sal import is often unsupported. The HTB forum discussion also matched the observed failure mode: wrong integer/export handling causes random-looking flash output. Those notes are recorded in analysis/research/saleae-and-secret-treasures-research.md.

Solve

The solve has two parts:

  1. solve/bruteforce_seed.c searches the 8-digit decimal seed space using the exact firmware PRNG/address logic and validates candidates against the HTB{ prefix.
  2. solve/solve.py uses the recovered seed 73261522 to reproduce the final extraction from analysis/extracted/hw_secret/flash_memory_dump.bin.

Re-run:

bash
cd <local workspace>
./solve/solve.py --output loot/flag-candidate.txt

The harness capture step copied the validated flag to loot/flag.txt.

Flag

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

Lessons

  • In hardware challenges with firmware plus flash, reverse the device-side address generation before trying broad carving.
  • .sal files may require vendor tooling or custom parsing; firmware-derived validation can be cheaper when the passcode is only a PRNG seed.
  • Preserve C helpers for expensive seed searches, but keep a clean Python script for final reproducibility.

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: Secret-Treasures
  • Category: Hardware
  • Difficulty: Medium
  • Mode: file
  • Remote instance: none
  • Start time: 2026-06-13T12:45:03Z
  • 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/a12c7357-88da-4145-a579-1bb343be1776.zip16815481<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 4 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-13T12:45:03Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-13T12:45:03Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-13T12:45:55Zhypothesis recordedhypothesis-board.mdReverse the ARM embedded_software to identify the passcode verification and flash lookup logic, decode input_channel_trace.sal to recover the entered passcode, then use the passcode against flash_memory_dump.bin to extract the HTB flag.MediumExtract the .sal capture into CSV/metadata, inspect ELF strings/disassembly for protocol constants and flash offsets, then write solve/solve.py to reproduce passcode decoding and flash extraction.
2026-06-13T12:51:47Zresearch taskanalysis/research/task-20260613T125147012693Z-206f638b.mdResearch task created for advisory investigationMediumRecord research output
2026-06-13T12:52:33Zresearch recordanalysis/research/research-records.mdResearch tagged MATCHEDMediumValidate against current evidence
2026-06-13T12:52:54Zcheckpoint recordedanalysis/checkpoint-analysis-20260613T125253998893Z-5f455c77.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-13T12:52:54Zinstrumentation plananalysis/instrumentation-plan.mdProve the offline flag extraction path from firmware PRNG to W25Q128 flash bytes.HighStop if no HTB{ prefix appears under the exact firmware PRNG logic, or if solve.py output fails HTB flag format validation.
2026-06-13T12:52:54Zevaluatoranalysis/evaluator-20260613T125254120114Z-dbd337d3.mdProceedHighRun gate before exploit, execute solve.py to loot/flag-candidate.txt, then capture-flag.
2026-06-13T12:53:00Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-13T12:54:05Zcompletion gatechallenge-state.jsonCompletion gate passed; state marked COMPLETEHighOptional sanitized memory summary approval

Key Findings

  • Archive extracted with the standard HTB archive password into analysis/extracted/.
  • embedded_software is a 32-bit ARM ELF using wiringPi serial and SPI functions.
  • The firmware opens /dev/ttyS0 at 38400 baud, reads exactly 8 bytes, and parses them with strtoul(..., base=10).
  • The firmware checks a W25Q128 unique ID against the .rodata bytes at 0x10f40.
  • The PRNG is an LCG: state = state * 0x41c64e6d + 0x0008042a modulo 2^32, returning state % 0x00ffffff.
  • Each emitted byte is read from the flash dump at an address built from three PRNG calls.
  • The firmware emits 49 bytes after successful identification.
  • Local seed search recovered decimal seed 73261522, and solve/solve.py reproduces the flag extraction from the flash dump.

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: Hardware
  • Challenge: Secret-Treasures
  • 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.

  1. Extracted the challenge archive and identified an ARM ELF, a W25Q128 flash dump, and a Saleae input trace.
  2. Reversed the firmware serial path: /dev/ttyS0, 38400 baud, 8 bytes, strtoul(..., base=10).
  3. Reversed the firmware PRNG and flash addressing path:

- LCG state update with multiplier 0x41c64e6d and increment 0x0008042a.

- PRNG return value is modulo 0x00ffffff.

- Three PRNG calls build each 24-bit flash address.

  1. Recovered the decimal seed with a local C brute-force helper and reproduced the final extraction with Python.

Reusable Lessons

  • For firmware plus flash challenges, recover the firmware's exact integer semantics before reading flash bytes; minor type/modulo mistakes produce plausible but wrong random output.
  • Use C for bounded high-volume seed search and Python for the final clean solve artifact.
  • Treat .sal parsing as optional when the firmware model provides a deterministic extraction route.

Dead Ends

  • Direct sigrok-cli import of the .sal archive was not viable in this local environment.
  • Direct string search of the flash dump did not reveal the flag.

Tool Quirks

  • binwalk, ghidra, openocd, avrdude, minipro, rtl_433, and urh were missing locally, but were not blockers.
  • objdump was sufficient for the ARM ELF even though readelf was unavailable.
  • Saleae .sal containers can hold internal binary data that does not import cleanly through sigrok.

Evidence Paths

  • analysis/objdump-disasm.txt
  • analysis/objdump-symbols.txt
  • analysis/objdump-rodata.txt
  • analysis/research/saleae-and-secret-treasures-research.md
  • analysis/seed-candidates-7.txt
  • solve/bruteforce_seed.c
  • solve/solve.py
  • loot/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.

RankPathEvidenceMissing ProofCheapest ValidationConfidenceStatus
1Reverse the ARM embedded_software to identify the passcode verification and flash lookup logic, decode input_channel_trace.sal to recover the entered passcode, then use the passcode against flash_memory_dump.bin to extract the HTB flag.Artifacts include embedded_software ARM ELF, flash_memory_dump.bin, and input_channel_trace.sal matching the scenario's embedded software, flash dump, and passcode input channel capture.Extract the .sal capture into CSV/metadata, inspect ELF strings/disassembly for protocol constants and flash offsets, then write solve/solve.py to reproduce passcode decoding and flash extraction.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition

Technical analogy

How to remember this solve

Think of the hardware challenge like following copper tracks on a circuit board. The useful clue is usually where signals enter, where they are transformed, and which debug or storage path exposes hidden state.

For Secret Treasures, 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.