RFlag
RFlag is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
RFlag attack path
RFlag 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
Treat .cf32 as little-endian complex float32 IQ...
Compute magnitude squared to distinguish idle noise...
Threshold as OOK/ASK and run-length encode high/low...
Estimate bit-cell timing from short runs, then expand...
Manchester decode with phase 0 and convention 01=0,...
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.
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/RFlag/writeup.md
- htb-challenge/Hardware/RFlag/notes.md
- htb-challenge/Hardware/RFlag/memory-summary.md
- htb-challenge/Hardware/RFlag/hypothesis-board.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Hardware__RFlag__memory-summary.md.e663273744.md
- HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__Hardware__RFlag__notes.md.d110ce8a5f.md
Technical Walkthrough
Writeup
Challenge
- Name: RFlag
- Category: Hardware
- Difficulty: Easy
- Mode: file
Summary
RFlag is a file-only SDR signal-analysis challenge. The provided signal.cf32 capture is an OOK/ASK signal from a garage remote. Decoding required thresholding the IQ magnitude, reducing the waveform to short/long runs, expanding those runs into bit cells, and applying Manchester decoding. The decoded byte stream contains an HTB-format flag after a short preamble.
Artifact Inventory
files/a12c7374-3809-4b8e-8b0a-9bdcf9be63fd.zip: original HTB archive, preserved unmodified.files/extracted/hardware_rflag/signal.cf32: complex-float IQ capture, 3,809,280 bytes, 476,160 complex samples. Evidence:analysis/artifact-inventory.json,analysis/unzip.txt,analysis/sha256-extracted.txt.
Analysis
The file extension and challenge scenario indicated SDR IQ data. The first pass treated it as complex float32 samples. Magnitude statistics showed two strong populations: idle/noise samples near magnitude squared 0.001, and active carrier samples near magnitude squared 2.0. That supports OOK/ASK rather than FSK as the first decode path. Evidence: analysis/signal-basic-stats.txt.
Thresholding at magnitude squared 0.1 produced a clean pulse train. The run lengths clustered around two durations: roughly 900 samples and 1800 samples. Evidence: analysis/ook-runs.txt.
Direct high/low pair PWM was tested and rejected because all four pair classes (SS, SL, LS, LL) appeared frequently. The correct interpretation was run-length expansion: short runs are one bit cell, long runs are two bit cells. Evidence: analysis/ook-symbols.txt, analysis/runlength-decode-attempts.txt.
After run-length expansion, Manchester decoding with phase 0 and convention 01=0, 10=1 produced a byte stream with a preamble and an HTB-format flag beginning at decoded bit offset 48. Including the trailing low run was necessary to recover the final byte; trimming it produced only a partial flag. Evidence: analysis/manchester-full-decode.txt.
Solve
Run:
cd <local workspace>
python3 solve/solve.py --output loot/flag-candidate.txtThe solver:
- Parses the cf32 file as little-endian float32 I/Q pairs.
- Computes magnitude squared and thresholds it as OOK.
- Estimates the bit-cell unit from short pulse lengths.
- Expands each run by
round(length / unit). - Manchester decodes phase 0 using
01=0,10=1. - Searches byte alignments for an HTB-format flag and writes it to
loot/.
The harness captured the generated candidate with:
cd <local workspace>
./scripts/challenge_harness.py capture-flag Hardware/RFlag --from loot/flag-candidate.txtFlag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- For SDR captures, inspect magnitude statistics before assuming a protocol decoder is required.
- OOK remotes may need run-length expansion before Manchester decoding.
- Do not trim trailing idle blindly; the final low run can carry the second half of the last Manchester bit.
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: RFlag
- Category: Hardware
- Difficulty: Easy
- Mode: file
- Remote instance: none
- Start time: 2026-06-09T12:38:54Z
- 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/a12c7374-3809-4b8e-8b0a-9bdcf9be63fd.zip | 370674 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 2 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-09T12:38:54Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-09T12:39:07Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-09T12:39:45Z | hypothesis recorded | hypothesis-board.md | Decode the cf32 RF capture as OOK/ASK remote-key amplitude pulses | Medium | Load complex float32 samples, inspect magnitude envelope, threshold high/low pulses, infer symbol timing, then decode bits/ASCII. |
| 2026-06-09T12:42:34Z | research task | analysis/research/task-20260609T124234161757Z-c7ef9d75.md | Research task created for advisory investigation | Medium | Record research output |
| 2026-06-09T12:42:35Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-09T12:43:32Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-09T12:46:02Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- The ZIP contains a single complex-float IQ capture:
files/extracted/hardware_rflag/signal.cf32; seeanalysis/unzip.txt. - The signal is OOK/ASK-like: low noise has magnitude squared around
0.001, while active carrier samples cluster near2.0; seeanalysis/signal-basic-stats.txt. - Thresholding at magnitude squared
0.1yields short and long runs near900and1800samples; seeanalysis/ook-runs.txt. - Pair-level PWM was not the right decode because
SS,SL,LS, andLLrun pairs all occur; seeanalysis/ook-symbols.txt. - Expanding high/low runs at the 900-sample unit and Manchester decoding with
01=0,10=1, phase 0 reveals an HTB-format flag at decoded bit offset 48. The trailing low run is required to recover the closing byte; see sanitized evidence inanalysis/manchester-full-decode.txt. solve/solve.pyreproduces the full decode and writes the raw flag only toloot/.
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: RFlag
- 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.
- Treat
.cf32as little-endian complex float32 IQ samples. - Compute magnitude squared to distinguish idle noise from active carrier.
- Threshold as OOK/ASK and run-length encode high/low regions.
- Estimate bit-cell timing from short runs, then expand long runs into repeated bit cells.
- Manchester decode with phase 0 and convention
01=0,10=1. - Search decoded byte alignments for the HTB-format flag; include the trailing low run so the final byte is complete.
Reusable Lessons
- Hardware SDR captures can often be solved with simple envelope thresholding before specialized tools like
urhorrtl_433. - If pair-level PWM has all
SS,SL,LS, andLLclasses, try run-length expansion before Manchester decoding. - Avoid trimming all trailing idle; the last low run may contain part of the final Manchester symbol.
Dead Ends
- Direct raw expanded ASCII was noisy and did not produce a clean flag.
- Pair-level PWM classification was not sufficient because all four pair classes appeared.
Tool Quirks
numpy,scipy,matplotlib,rtl_433, andurhwere unavailable locally, but standard-library Python was enough for this capture.
Evidence Paths
analysis/signal-basic-stats.txtanalysis/ook-runs.txtanalysis/ook-symbols.txtanalysis/runlength-decode-attempts.txtanalysis/manchester-full-decode.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 | Decode the cf32 RF capture as OOK/ASK remote-key amplitude pulses | Artifact is named signal.cf32 and the scenario says an SDR captured a garage remote key signal. | Load complex float32 samples, inspect magnitude envelope, threshold high/low pulses, infer symbol timing, then decode bits/ASCII. | Medium | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit Condition |
|---|
Memory Summary
approval_required: true
Sanitized Memory Summary
Metadata
- Platform: HackTheBox Challenges
- Category: Hardware
- Challenge: RFlag
- 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.
- Treat
.cf32as little-endian complex float32 IQ samples. - Compute magnitude squared to distinguish idle noise from active carrier.
- Threshold as OOK/ASK and run-length encode high/low regions.
- Estimate bit-cell timing from short runs, then expand long runs into repeated bit cells.
- Manchester decode with phase 0 and convention
01=0,10=1. - Search decoded byte alignments for the HTB-format flag; include the trailing low run so the final byte is complete.
Reusable Lessons
- Hardware SDR captures can often be solved with simple envelope thresholding before specialized tools like
urhorrtl_433. - If pair-level PWM has all
SS,SL,LS, andLLclasses, try run-length expansion before Manchester decoding. - Avoid trimming all trailing idle; the last low run may contain part of the final Manchester symbol.
Dead Ends
- Direct raw expanded ASCII was noisy and did not produce a clean flag.
- Pair-level PWM classification was not sufficient because all four pair classes appeared.
Tool Quirks
numpy,scipy,matplotlib,rtl_433, andurhwere unavailable locally, but standard-library Python was enough for this capture.
Evidence Paths
analysis/signal-basic-stats.txtanalysis/ook-runs.txtanalysis/ook-symbols.txtanalysis/runlength-decode-attempts.txtanalysis/manchester-full-decode.txtsolve/solve.pyloot/flag.txt
Ingestion Decision
- Proposed for LightRAG: yes
- Requires user approval before ingestion: yes
Notes
Notes
Scope
- Challenge: RFlag
- Category: Hardware
- Difficulty: Easy
- Mode: file
- Remote instance: none
- Start time: 2026-06-09T12:38:54Z
- 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/a12c7374-3809-4b8e-8b0a-9bdcf9be63fd.zip | 370674 | <hash redacted> | Zip archive data, at least v1.0 to extract, compression method=store | zip entries: 2 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-09T12:38:54Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-09T12:39:07Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-09T12:39:45Z | hypothesis recorded | hypothesis-board.md | Decode the cf32 RF capture as OOK/ASK remote-key amplitude pulses | Medium | Load complex float32 samples, inspect magnitude envelope, threshold high/low pulses, infer symbol timing, then decode bits/ASCII. |
| 2026-06-09T12:42:34Z | research task | analysis/research/task-20260609T124234161757Z-c7ef9d75.md | Research task created for advisory investigation | Medium | Record research output |
| 2026-06-09T12:42:35Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-09T12: <REDACTED> | |||||
| 2026-06-09T12:46:02Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- The ZIP contains a single complex-float IQ capture:
files/extracted/hardware_rflag/signal.cf32; seeanalysis/unzip.txt. - The signal is OOK/ASK-like: low noise has magnitude squared around
0.001, while active carrier samples cluster near2.0; seeanalysis/signal-basic-stats.txt. - Thresholding at magnitude squared
0.1yields short and long runs near900and1800samples; seeanalysis/ook-runs.txt. - Pair-level PWM was not the right decode because
SS,SL,LS, andLLrun pairs all occur; seeanalysis/ook-symbols.txt. - Expanding high/low runs at the 900-sample unit and Manchester decoding with
01=0,10=1, phase 0 reveals an HTB-format flag at decoded bit offset 48. The trailing low run is required to recover the closing byte; see sanitized evidence inanalysis/manchester-full-decode.txt. solve/solve.pyreproduces the full decode and writes the raw flag only toloot/.
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.
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 RFlag, 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.