Bare Metal
Bare Metal is a sanitized challenge note from the local HTB archive, organized for quick review by category, difficulty, evidence flow, and reusable operator
Scenario
Bare Metal attack path
Bare Metal 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
Parsed the Intel HEX firmware into raw flash bytes.
Identified the main behavior as direct AVR SBI/CBI...
Reconstructed the GPIO timeline for PD5 and PD6.
Treated PD6 as clock and PD5 as data based on the...
Sampled PD5 on rising edges of PD6.
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/Bare-Metal/writeup.md
- htb-challenge/Hardware/Bare-Metal/notes.md
- htb-challenge/Hardware/Bare-Metal/memory-summary.md
- htb-challenge/Hardware/Bare-Metal/hypothesis-board.md
Technical Walkthrough
Writeup
Challenge
- Name: Bare-Metal
- Category: Hardware
- Difficulty: Medium
- Mode: file
Summary
The firmware was an ATmega328p Intel HEX image. Its main routine did not use a standard serial peripheral; it bit-banged a two-wire payload by directly toggling PORTD.
The important pattern was repeated SBI/CBI instructions against PORTD bits 5 and 6. PD5 was the data line and PD6 was the clock line. Sampling PD5 on each rising edge of PD6 produced an MSB-first ASCII command beginning with set_flag:. The value after that prefix was the flag.
Artifact Inventory
files/a12c73a9-a82a-44c2-80e0-3aef51c08e29.zip: original archive.analysis/extracted/extracted_firmware.hex: extracted ATmega328p Intel HEX firmware.analysis/avr-flash.bin: raw flash bytes parsed from the Intel HEX file.analysis/avr-disasm-lite.txt: lightweight decode of relevant AVR instructions.analysis/avr-portd-states.csv: reconstructedPORTDstate changes.
Analysis
The firmware starts with a typical AVR vector table. The reset vector transfers into startup code, which calls a routine at byte address 0x0080; see analysis/avr-disasm-lite.txt.
That routine configures DDRD, then repeatedly uses SBI and CBI instructions:
0x9a5e: setPORTD,60x985e: clearPORTD,60x9a5d: setPORTD,50x985d: clearPORTD,5
This forms a data/clock pattern:
PD5: data bitPD6: clock pulse
analysis/avr-portd-states.csv records each state transition. Sampling the current PD5 value whenever PD6 rises yields 352 bits. Grouping those bits as MSB-first bytes yields a 44-byte ASCII command. analysis/clocked-bit-decode.txt records the manual decode with the raw flag redacted.
Solve
The reproducible solver is solve/solve.py. It:
- Parses
analysis/extracted/extracted_firmware.hex. - Tracks
SBI/CBIwrites toPORTD. - Samples
PD5on rising edges ofPD6. - Groups bits into MSB-first bytes.
- Extracts the HTB-format flag from the decoded
set_flag:command.
Run:
cd <local workspace>
python3 solve/solve.pyThe decoded message is written redacted to analysis/decoded-message.txt; the raw flag candidate is written to loot/flag-candidate.txt and captured by the harness into loot/flag.txt.
Flag
Raw flag is stored in loot/flag.txt and intentionally not reproduced here.
Lessons
- For small AVR firmware, direct opcode decoding can be faster than installing a full decompiler.
- Repeated
SBI/CBIinstructions on GPIO pins often indicate a bit-banged bus. - Reconstructing pin state transitions can reveal what a device sent to a slave even when the hardware is unavailable.
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: Bare-Metal
- Category: Hardware
- Difficulty: Medium
- Mode: file
- Remote instance: none
- Start time: 2026-06-13T13:51:42Z
- 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/a12c73a9-a82a-44c2-80e0-3aef51c08e29.zip | 1115 | <hash redacted> | Zip archive data, at least v2.0 to extract, compression method=deflate | zip entries: 1 shown in artifact inventory JSON |
Evidence Ledger
| Time | Action | Output/File | Finding | Confidence | Next |
|---|---|---|---|---|---|
| 2026-06-13T13:51:42Z | harness init | challenge-state.json | Workspace initialized with deterministic state file | High | Inventory artifacts |
| 2026-06-13T13:52:04Z | artifact inventory | analysis/artifact-inventory.json | 1 artifact(s) inventoried | High | Build or update hypotheses |
| 2026-06-13T13:52:25Z | hypothesis recorded | hypothesis-board.md | Parse the ATmega328p Intel HEX firmware, reverse the UART/SPI/I2C behavior, and derive what command or data was sent to the tapped slave device; the flag is likely encoded in that device action or payload. | Medium | Convert Intel HEX to binary, inspect strings and reset vector, then disassemble enough AVR code around main/peripheral routines to identify protocol bytes. |
| 2026-06-13T13:54:31Z | research task | analysis/research/task-20260613T135431865632Z-c421b6d8.md | Research task created for advisory investigation | Medium | Record research output |
| 2026-06-13T13:54:31Z | research record | analysis/research/research-records.md | Research tagged MATCHED | Medium | Validate against current evidence |
| 2026-06-13T13:54:31Z | checkpoint recorded | analysis/checkpoint-analysis-20260613T135431979107Z-68ae6235.md | Checkpoint for ANALYSIS | High | Use checkpoint to drive next decision |
| 2026-06-13T13:54:32Z | instrumentation plan | analysis/instrumentation-plan.md | Reconstruct the slave-device command bitstream from firmware-level PORTD writes. | High | Stop if no HTB-format value appears after sampling PD5 on PD6 rising edges or if alternative bit ordering contradicts printable ASCII. |
| 2026-06-13T13:54:32Z | evaluator | analysis/evaluator-20260613T135432082468Z-f26ddd95.md | Proceed | High | Run gate, execute solve.py, capture the flag, then complete documentation. |
| 2026-06-13T13:54:47Z | flag capture | loot/flag.txt | HTB-format flag captured; raw value kept in loot only | High | Write solution and run completion gate |
| 2026-06-13T13:55:50Z | completion gate | challenge-state.json | Completion gate passed; state marked COMPLETE | High | Optional sanitized memory summary approval |
Key Findings
- The challenge archive contains one Intel HEX firmware image:
analysis/extracted/extracted_firmware.hex. - The firmware is small, about 2.2 KiB after Intel HEX parsing.
- Reset/startup code calls the routine beginning near byte address
0x0080. - The core routine uses repeated AVR
SBI/CBIoperations against I/O address0x0b, which corresponds toPORTDfor ATmega328p. - The active bit-banged lines are
PD5andPD6;PD5is data andPD6is clock. - Sampling
PD5on each rising edge ofPD6yields 352 bits, or 44 MSB-first ASCII bytes. - The decoded command starts with
set_flag:and contains the challenge flag. solve/avr_trace.pyrecords thePORTDstate timeline;solve/solve.pyreproduces the flag extraction from the original Intel HEX.
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: Bare-Metal
- 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.
- Parsed the Intel HEX firmware into raw flash bytes.
- Identified the main behavior as direct AVR
SBI/CBIwrites to ATmega328pPORTD. - Reconstructed the GPIO timeline for
PD5andPD6. - Treated
PD6as clock andPD5as data based on the repeated set-data then pulse-clock pattern. - Sampled
PD5on rising edges ofPD6. - Decoded the resulting MSB-first bitstream as ASCII.
- Extracted the flag from a decoded
set_flag:command.
Reusable Lessons
- Small AVR firmware can often be solved by decoding a small subset of opcodes rather than using full AVR tooling.
SBI/CBIbursts against one port are strong evidence of GPIO bit-banging.- Reconstructing pin transitions is an effective way to infer what a removed embedded device sent to a slave.
Dead Ends
- Direct string search was not useful; the flag was not stored as text in firmware, it was represented as GPIO operations.
Tool Quirks
avr-objdump,binwalk,ghidra,avrdude, andopenocdwere unavailable locally.- A purpose-built Python parser was sufficient because the relevant instruction set was limited to Intel HEX parsing and AVR
SBI/CBIdecoding.
Evidence Paths
analysis/extracted/extracted_firmware.hexanalysis/avr-disasm-lite.txtanalysis/avr-portd-states.csvanalysis/clocked-bit-decode.txtanalysis/decoded-message.txtsolve/avr_trace.pysolve/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 | Parse the ATmega328p Intel HEX firmware, reverse the UART/SPI/I2C behavior, and derive what command or data was sent to the tapped slave device; the flag is likely encoded in that device action or payload. | Challenge provides only extracted_firmware.hex and states the device was on a serial network, with ATmega328p microcontroller. | Need convert HEX to flash bytes, locate strings/constants/peripheral register accesses, and reconstruct the slave-device interaction. | Convert Intel HEX to binary, inspect strings and reset vector, then disassemble enough AVR code around main/peripheral routines to identify protocol bytes. | Medium | Active |
Closed Branches
| Branch | Evidence Tested | Failure Output | Reason Closed | Revisit 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 Bare Metal, 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.