Trace
Trace is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
Trace attack path
Trace 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.
Walkthrough flow
Extract the challenge archive and identify traces.csv...
Render or inspect the Gerbers to identify the board...
Infer the row/column GPIO mapping from Gerber traces...
Split the GPIO CSV into 8-sample frames; each frame...
Reconstruct visible LEDs using selected row high plus...
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.
- Hardware/Trace/writeup.md
- htb-challenge/Hardware/Trace/notes.md
- htb-challenge/Hardware/Trace/memory-summary.md
- htb-challenge/Hardware/Trace/hypothesis-board.md
Technical Walkthrough
Writeup
Challenge
- Name: Trace
- Category: Hardware
- Difficulty: Medium
- Mode: file
Summary
The capture was a multiplexed 8x8 LED matrix trace rather than a normal serial protocol. The Gerber files identified the board as a Raspberry Pi HAT carrying a common-anode matrix, and the CSV recorded the row/column GPIO states over one complete message cycle. Reconstructing each group of eight row scans revealed the displayed HTB flag.
Artifact Inventory
files/a12c7358-7d8b-4b0d-a16c-5a05f7669a6f.zip: original challenge archive.analysis/extracted/traces.csv: GPIO state capture with 336 samples and 16 GPIO signal columns.analysis/extracted/Gerber_module/: PCB fabrication files used to infer the matrix wiring.analysis/render-top-silk.png: rendered silkscreen showing the common-anode matrix and Raspberry Pi HAT context.analysis/netlist-inference.txt: local GPIO row/column mapping inference.
Analysis
The CSV has 336 rows. The timing gaps and one-hot row behavior split naturally into 42 frames of 8 samples each, matching a multiplexed 8x8 LED matrix. The Gerber-derived mapping identified physical rows as GPIO 12, 25, 24, 22, 27, 17, 18, 23 and columns as GPIO 16, 5, 6, 13, 19, 26, 20, 21.
Because the board is common-anode, a visible LED occurs when the selected row is high and the column line is low. After applying that active-low rule and rotating the reconstructed matrix into display orientation, the first four glyphs rendered as HTB{, validating the mapping. The remaining frames decoded as leetspeak dot-matrix glyphs.
Public Trace write-up material was used only as advisory confirmation of the same wiring approach. The actual decoded candidate came from the local CSV and Gerber-derived mapping.
Solve
Run the decoder from the challenge workspace:
cd <local workspace>
./solve/solve.py --output analysis/flag-candidate.txt --dump-glyphs analysis/decoded-glyph-bytes.txtThe script parses traces.csv, groups samples into 8-row frames, reconstructs visible pixels using the common-anode active-low column rule, rotates the matrix, maps each recovered glyph byte pattern to its displayed character, and writes the HTB-format candidate. The harness then captures it into loot/flag.txt.
One important ambiguity was corrected after validation: the glyph byte pattern 00 00 7f 49 49 7f 00 00 is digit 8 in this matrix font, not letter B.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- For LED matrix captures, infer the electrical topology before reading pixels; common-anode/common-cathode changes whether a GPIO high or low means illuminated.
- Gerber files are useful evidence for pin mapping, especially when the trace itself only exposes GPIO names.
- Validate orientation with a known flag prefix before committing to ambiguous glyphs.
- Keep an indexed rendered sheet for dot-matrix challenges so visually similar leetspeak characters can be checked without guessing.
- Cross-check ambiguous LED glyphs against an exact font table;
8andBare easy to confuse in this challenge's rendered style.
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: Trace
- Category: Hardware
- Difficulty: Medium
- Mode: file
- Remote instance: none
- Start time: 2026-06-13T11:38:59Z
- 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/a12c7358-7d8b-4b0d-a16c-5a05f7669a6f.zip | 19303 | <hash redacted> | Zip archive data, at least v2.0 to extract, compression method=store | zip entries: 13 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-13T11:38:59Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-13T11:38:59Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-13T11:57:06Z | hypothesis recorded | hypothesis-board.md | Decode traces.csv as a multiplexed common-anode 8x8 LED matrix using the Gerber-derived Raspberry Pi GPIO row/column mapping. | Medium | Run solve/solve.py to reconstruct active-low visible pixels, rotate into display orientation, map glyph bytes to ASCII, and write analysis/flag-candidate.txt. |
| 2026-06-13T11:57:06Z | instrumentation plan | analysis/instrumentation-plan.md | Reproduce the debug matrix display from the captured GPIO trace. | High | Stop if glyph bytes do not begin with HTB{ or if any recovered glyph is not mapped; do not guess ambiguous characters without a rendered/indexed validation sheet. |
| 2026-06-13T11:57:14Z | research task | analysis/research/task-20260613T115714687382Z-7791a574.md | Research task created for advisory investigation | Medium | Record research output |
| 2026-06-13T11:57:28Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-13T11:57:28Z | checkpoint recorded | analysis/checkpoint-analysis-20260613T115728337980Z-3c9bdaea.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-13T11:57:39Z | evaluator | analysis/evaluator-20260613T115739182240Z-051b391d.md | Proceed | High | Capture flag from analysis/flag-candidate.txt, then complete writeup and final gate. |
| 2026-06-13T11:57:51Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-13T11:59:04Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
| 2026-06-13T12:39:07Z | branch closed | hypothesis-board.md | Glyph was misclassified as B when it is the digit 8 in the matrix font. | High | Rerank hypotheses |
| 2026-06-13T12:39:07Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-13T12:39:42Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- The ZIP contains
traces.csvplus Gerber fabrication files for the debug matrix PCB. traces.csvhas 336 GPIO samples across 16 GPIO columns, which splits cleanly into 42 frames of 8 row scans.- The top silkscreen identifies the board as a Raspberry Pi 3B+ HAT and a common-anode 8x8 LED matrix.
- Gerber/netlist inspection maps rows to GPIO 12, 25, 24, 22, 27, 17, 18, 23 and columns to GPIO 16, 5, 6, 13, 19, 26, 20, 21.
- Visible LED pixels are active-low on the column lines while the selected row is high.
solve/solve.pyreconstructs the frames, rotates them into display orientation, decodes the glyph bytes, and writes an HTB-format flag candidate.- The final flag was captured through the harness into
loot/flag.txt. - Correction after submission feedback: glyph bytes
00 00 7f 49 49 7f 00 00are digit8, not letterB; the visible segment isPC85, notPCB5.
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: Hardware
- Challenge: Trace
- 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.
- Extract the challenge archive and identify
traces.csvplus Gerber fabrication files. - Render or inspect the Gerbers to identify the board as a Raspberry Pi HAT with a common-anode 8x8 LED matrix.
- Infer the row/column GPIO mapping from Gerber traces and Raspberry Pi pin labels.
- Split the GPIO CSV into 8-sample frames; each frame represents one displayed glyph.
- Reconstruct visible LEDs using selected row high plus active-low column lines, then rotate into display orientation.
- Decode the recovered 8x8 glyph byte patterns into the displayed HTB-format message.
- Verify visually similar glyphs against the exact byte table before final capture; in this challenge, the byte pattern for digit 8 can be mistaken for letter B.
Reusable Lessons
- Common-anode LED matrices invert the intuitive column state: selected rows are high, visible columns are low.
- A valid
HTB{prefix is a strong orientation and polarity check before decoding the rest of a dot-matrix message. - Public write-ups can confirm the approach, but the current CSV/Gerber artifacts must remain the source of truth.
- Exact glyph byte matching matters more than semantic reading of the phrase; a visually plausible
Bwas actually digit8.
Dead Ends
- Direct OCR on rendered dot-matrix strips was unreliable for this challenge because the 8x8 glyphs are low-resolution and leetspeak-heavy.
- Treating the electrical high column state as the visible LED state produces the inverse/complement display.
- Misclassifying the digit-8 glyph as letter B produced a rejected candidate.
Tool Quirks
- Tesseract did not read the rendered matrix strip reliably; manual glyph-byte mapping plus indexed render sheets worked better.
- The challenge harness requires a filled writeup and solve script before completion even for file-only challenges.
Evidence Paths
analysis/extracted/traces.csvanalysis/render-top-silk.pnganalysis/netlist-inference.txtanalysis/decoded-glyph-bytes.txtanalysis/decoded-flag-verification.pngsolve/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 | Decode traces.csv as a multiplexed common-anode 8x8 LED matrix using the Gerber-derived Raspberry Pi GPIO row/column mapping. | traces.csv has 336 samples, grouping into 42 frames of 8 row scans; top silkscreen says Common Anode Matrix; netlist inference maps rows/columns; first decoded glyphs render as HTB{ | Run solve/solve.py to reconstruct active-low visible pixels, rotate into display orientation, map glyph bytes to ASCII, and write analysis/flag-candidate.txt. | Medium | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit Condition |
|---|---|---|---|---|
| Frame 23 decoded as letter B, producing PC B5 | analysis/decoded-flag-verification.png and user submission feedback | Rejected candidate used PCB5; exact 8x8 digit table maps 00 00 7f 49 49 7f to digit 8. | Glyph was misclassified as B when it is the digit 8 in the matrix font. | Only revisit if the corrected PC85 candidate is rejected. |
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 Trace, 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.