Challenge / ICS

Steel Mountain

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

MediumPublished 2024-11-21Sanitized local writeup

Scenario

Steel Mountain attack path

Steel Mountain 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 ICS evidence, validation, and reusable operator lessons.

Steel Mountain sanitized attack graph

Walkthrough flow

01

Extracted instructions and blueprint identified the...

02

Service mapping identified a dashboard on the first...

03

The helper exposed object listing plus read/write...

04

Successful control sequence: raise Level 2 overheat...

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.

  • ICS/Steel-Mountain/writeup.md
  • htb-challenge/ICS/Steel-Mountain/notes.md
  • htb-challenge/ICS/Steel-Mountain/memory-summary.md
  • htb-challenge/ICS/Steel-Mountain/hypothesis-board.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__ICS__Steel-Mountain__memory-summary.md.0e955b0d57.md
  • HTB/_knowledge/exports/ctf-lightrag-latest-203412/documents/challenge__ICS__Steel-Mountain__notes.md.52456aee81.md

Technical Walkthrough

Writeup

Challenge

  • Name: Steel-Mountain
  • Category: ICS
  • Difficulty: Medium
  • Mode: hybrid

Summary

Steel Mountain is a hybrid ICS challenge with a dashboard on <TARGET>:30108

and a planted BACnet helper on <TARGET>:32580. The extracted

instructions say to lock the tape storage room, deny elevators from stopping at

Level 2, and hold the Level 2 temperature at the tape burn point long enough for

the dashboard to reveal the secret.

The successful solve used the helper to control the Level 2 BACnet objects:

raise the Level 2 overheat alarm point, lock the Tape Storage Room door, keep

both elevators away from Level 2, and set the thermostat above the 32 C burn

threshold so the real temperature sensor stayed above 32 during the hold.

Artifact Inventory

The original archive is preserved in files/ and inventoried in

analysis/artifact-inventory.json. It extracted to:

  • analysis/extracted/ics_steel_mountain/Instructions.md
  • analysis/extracted/ics_steel_mountain/Steel Mountain Blueprints.pdf

The blueprint required visual rendering because pdftotext did not expose the

floor labels cleanly. Rendered evidence in analysis/rendered/ showed the Tape

Storage Room on Level 2.

Remote service mapping in analysis/nmap-two-ports.txt identified:

  • 30108/tcp: Werkzeug HTTP dashboard
  • 32580/tcp: interactive helper with objects, bacnet.read, and

bacnet.write

Analysis

Instructions.md gave the mission rules: lock the tape storage room, deny

elevators at Level 2, and hold the level temperature at the burn point for two

minutes. The rendered blueprint confirmed this applies to Level 2.

The BACnet object dump in analysis/nc-objects.txt mapped the relevant objects:

  • <secret redacted> object 102, multiStateOutput, value 2 means locked.
  • ELE-1-CF/ELE-1-TF objects 80/82 and

ELE-2-CF/ELE-2-TF objects 83/85 represent elevator current and target

floors.

  • Therm-L2-21 object 21 controls the Level 2 thermostat.
  • <secret redacted> object 23 controls the Level 2 overheat alarm point.
  • <secret redacted> object 24 reports the alarm state.
  • Message object 500 is rendered by the dashboard when the secret appears.

The first one-shot sequence in analysis/mission-transcript.txt reached the

door and temperature states but failed because elevator values drifted back to

Level 2. The sustained-elevator sequence in

analysis/mission-sustain-transcript.txt kept the elevators away but still

failed because the real temperature sensor dipped below 32 C while the

thermostat was set to 32. The sensor itself was not writable, so the final solve

used a thermostat setpoint of 33 with the alarm point raised to 40.

Solve

The reproducible solver is solve/solve.py.

Read-only validation:

bash
python3 solve/solve.py probe --output analysis/solve-probe.txt

Final solve:

bash
python3 solve/solve.py mission \
  --burn-setpoint 33 \
  --output analysis/mission-hot-transcript.txt \
  --flag-output loot/flag-candidate.txt \
  --hold-seconds 160 \
  --poll-interval 3

The solver redacts dashboard flags from analysis transcripts and writes the raw

candidate only to loot/flag-candidate.txt. The harness then validated and

stored the final value in loot/flag.txt.

Flag

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

Lessons

For this challenge, the intended path was not raw BACnet tooling; the provided

netcat helper was enough. The important trick was not just setting the visible

thermostat to 32. The real temperature sensor could drift below the burn point,

so the thermostat needed to be above the threshold while the overheat alarm point

was raised to avoid a reset. Elevator values also required sustained control

rather than a single write.

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: Steel-Mountain
  • Category: ICS
  • Difficulty: Medium
  • Mode: hybrid
  • Remote instance: <TARGET>:30108,<TARGET>:32580
  • Start time: 2026-06-11T06:08:20Z
  • 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/a12c735e-5f7c-429e-812d-0933ec081f76.zip83527<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 3 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-11T06:08:20Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-11T06:08:20Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-11T06:08:20Zsession bootstrapnotes.mdChallenge metadata, scenario, and prior context seeded into workspaceHighRecord initial hypothesis and research
2026-06-11T06:08:20Zhypothesis recordedhypothesis-board.mdinitial triage from supplied challenge metadataMediuminventory files / inspect app surface / map routes depending on category
2026-06-11T06:08:20Zresearch taskanalysis/research/task-20260611T060820936111Z-1880d6b4.mdResearch task created for advisory investigationMediumRecord research output
2026-06-11T06:09:14Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T060914414768Z-8bb49e8a.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06:10:31Zhypothesis recordedhypothesis-board.mdInteract with the planted BACnet tool/menu over netcat to sequence Level Two controls, then read the dashboard for the flag.MediumNmap/service-identify both ports, then connect read-only with nc to identify which port is the dashboard and which is the tool before any mutation.
2026-06-11T06:10:31Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-11T06:10:52ZRAG queryanalysis/rag/rag-query-20260611T061033283496Z-3d12691d.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-11T06:11:40ZRAG recordanalysis/rag-records.mdRetrieved memory tagged GENERICMediumValidate or reject with live evidence
2026-06-11T06:11:55Zinstrumentation plananalysis/instrumentation-plan.mdIdentify the dashboard and planted BACnet/netcat tool ports, map the command protocol, then perform the exact Level Two mission sequence without triggering alarm resets.HighStop if the service shows an alarm/reset, if prompts are ambiguous, or after two failed command sequences without a new state fact; record failure and refresh hypothesis instead of blind probing.
2026-06-11T06:12:54Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-11T06:13:08Zevaluatoranalysis/evaluator-20260611T061308235567Z-eda10063.mdProceedHighUse challenge_exec for nmap/curl/nc read-only probes and save transcripts before any state-changing sequence.
2026-06-11T06:14:01Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T061401525835Z-6ed79ce2.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06:19:01Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T061901215883Z-99dcc057.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06:19:01Zevaluatoranalysis/evaluator-20260611T061901316859Z-393b14d6.mdProceedHighRun solve/solve.py mission through challenge_exec and save transcript/flag candidate.
2026-06-11T06:22:33Zbranch closedhypothesis-board.mdDoor lock and Level 2 temperature reached the intended state without alarm, but the dashboard Message stayed empty; final transcript shows both elevators drifted/stopped at Level 2, so one-shot ELE target writes do not satisfy the elevator denial condition.HighRerank hypotheses
2026-06-11T06:26:42Zbranch closedhypothesis-board.mdDoor lock, elevator current/target floors, alarm threshold, and thermostat setpoint were sustained without alarm, but dashboard Message stayed empty. Transcript shows actual Temp-L2-20 dipped below 32 during the hold, so thermostat-only control likely does not satisfy the two-minute burn condition.HighRerank hypotheses
2026-06-11T06:26:42Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T062642616755Z-f70428fe.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06:26:42Zevaluatoranalysis/evaluator-20260611T062642667155Z-378fac53.mdProceedHighPatch solver to sustain Temp-L2-20 and run one bounded mission attempt through challenge_exec.
2026-06-11T06:30:48Zbranch closedhypothesis-board.mdTemp-L2-20 analogInput is not writable, and with Therm-L2 set to 32 the actual sensor still dipped below 32 during the hold. Door/elevator/alarm controls remained valid but no dashboard Message appeared.HighRerank hypotheses
2026-06-11T06:30:48Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T063048840886Z-62025272.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06:30:48Zevaluatoranalysis/evaluator-20260611T063048891384Z-ac9286af.mdProceedHighRun high-setpoint mission attempt through challenge_exec.
2026-06-11T06:32:55Zflag captureloot/flag.txtHTB-format flag captured; raw value kept in loot onlyHighWrite solution and run completion gate
2026-06-11T06:36:35Zcompletion 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.

Scenario

Challenge: Steel Mountain. Steel Mountain is a secure facility serving major corporations like E-Corp. We've infiltrated their network and planted our tool. Final step: Burn the tapes to destroy the data. All necessary info is in the files.

Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: ICS
  • Challenge: Steel-Mountain
  • 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 instructions and blueprint identified the Tape Storage Room on

Level 2.

  1. Service mapping identified a dashboard on the first remote port and a custom

BACnet helper on the second remote port.

  1. The helper exposed object listing plus read/write commands for BACnet object

type, object ID, property, and value.

  1. Successful control sequence: raise Level 2 overheat alarm point, lock

<secret redacted>, sustain both elevator current/target floors away from Level 2,

and set Therm-L2 above the 32 C burn threshold so actual Temp-L2 remains

above 32 during the hold.

Reusable Lessons

  • In simulator-style ICS challenges, distinguish a thermostat/setpoint from the

actual sensor value the validator may check.

  • If a control value drifts back due to the simulator loop, solve by sustaining

the control during the validation window rather than writing it once.

  • Raising the overheat alarm threshold can be required before deliberately

heating a level above the default alarm point.

Dead Ends

  • One-shot elevator target writes failed because elevators drifted back to

Level 2.

  • Sustained elevator denial with thermostat 32 failed because actual

temperature dipped below the burn threshold.

  • Direct Temp-L2 sensor write failed because the analog input was not

writable.

Tool Quirks

  • A simple Python socket client was more reliable than batch nc for the custom

prompt timing.

  • External BACnet packages were not needed because the challenge supplied a

custom helper menu.

Evidence Paths

  • analysis/nc-objects.txt
  • analysis/solve-probe.txt
  • analysis/mission-transcript.txt
  • analysis/mission-sustain-transcript.txt
  • analysis/mission-sensor-transcript.txt
  • analysis/mission-hot-transcript.txt
  • solve/solve.py

Ingestion Decision

  • Proposed for LightRAG: yes, after user approval.
  • 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
1initial triage from supplied challenge metadatachallenge name, category, difficulty, scenario, and remote target were provided by operatorinventory files / inspect app surface / map routes depending on categoryMediumActive
1Interact with the planted BACnet tool/menu over netcat to sequence Level Two controls, then read the dashboard for the flag.Instructions.md says a tool is implanted in the BACnet network and reachable with netcat; blueprint places Tape Storage Room on Level Two; two remote ports are provided.Nmap/service-identify both ports, then connect read-only with nc to identify which port is the dashboard and which is the tool before any mutation.MediumActive

Closed Branches

BranchEvidence TestedFailure OutputReason ClosedRevisit Condition
one-shot mission write sequenceanalysis/mission-transcript.txtanalysis/mission-transcript.txtDoor lock and Level 2 temperature reached the intended state without alarm, but the dashboard Message stayed empty; final transcript shows both elevators drifted/stopped at Level 2, so one-shot ELE target writes do not satisfy the elevator denial condition.Use sustained elevator denial during the two-minute burn window, reasserting target/current floors away from Level 2 while keeping door locked, Level 2 at 32 C, and alarm threshold safely above burn temperature.
sustained elevator denial with thermostat-only temperature controlanalysis/mission-sustain-transcript.txtanalysis/mission-sustain-transcript.txtDoor lock, elevator current/target floors, alarm threshold, and thermostat setpoint were sustained without alarm, but dashboard Message stayed empty. Transcript shows actual Temp-L2-20 dipped below 32 during the hold, so thermostat-only control likely does not satisfy the two-minute burn condition.Sustain actual Temp-L2-20 at 32 alongside Therm-L2-21, while continuing sustained elevator denial and door lock.
sustained thermostat 32 with attempted sensor writeanalysis/mission-sensor-transcript.txtanalysis/mission-sensor-transcript.txtTemp-L2-20 analogInput is not writable, and with Therm-L2 set to 32 the actual sensor still dipped below 32 during the hold. Door/elevator/alarm controls remained valid but no dashboard Message appeared.Use a thermostat setpoint above the burn threshold, with OHAP-L2 raised, so actual Temp-L2 remains continuously >=32 for the two-minute burn window.

Memory Summary

approval_required: true

Sanitized Memory Summary

Metadata

  • Platform: HackTheBox Challenges
  • Category: ICS
  • Challenge: Steel-Mountain
  • 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 instructions and blueprint identified the Tape Storage Room on

Level 2.

  1. Service mapping identified a dashboard on the first remote port and a custom

BACnet helper on the second remote port.

  1. The helper exposed object listing plus read/write commands for BACnet object

type, object ID, property, and value.

  1. Successful control sequence: raise Level 2 overheat alarm point, lock

<secret redacted>, sustain both elevator current/target floors away from Level 2,

and set Therm-L2 above the 32 C burn threshold so actual Temp-L2 remains

above 32 during the hold.

Reusable Lessons

  • In simulator-style ICS challenges, distinguish a thermostat/setpoint from the

actual sensor value the validator may check.

  • If a control value drifts back due to the simulator loop, solve by sustaining

the control during the validation window rather than writing it once.

  • Raising the overheat alarm threshold can be required before deliberately

heating a level above the default alarm point.

Dead Ends

  • One-shot elevator target writes failed because elevators drifted back to

Level 2.

  • Sustained elevator denial with thermostat 32 failed because actual

temperature dipped below the burn threshold.

  • Direct Temp-L2 sensor write failed because the analog input was not

writable.

Tool Quirks

  • A simple Python socket client was more reliable than batch nc for the custom

prompt timing.

  • External BACnet packages were not needed because the challenge supplied a

custom helper menu.

Evidence Paths

  • analysis/nc-objects.txt
  • analysis/solve-probe.txt
  • analysis/mission-transcript.txt
  • analysis/mission-sustain-transcript.txt
  • analysis/mission-sensor-transcript.txt
  • analysis/mission-hot-transcript.txt
  • solve/solve.py

Ingestion Decision

  • Proposed for LightRAG: yes, after user approval.
  • Requires user approval before ingestion: yes

Notes

Notes

Scope

  • Challenge: Steel-Mountain
  • Category: ICS
  • Difficulty: Medium
  • Mode: hybrid
  • Remote instance: <TARGET>:30108,<TARGET>:32580
  • Start time: 2026-06-11T06:08:20Z
  • 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/a12c735e-5f7c-429e-812d-0933ec081f76.zip83527<hash redacted>Zip archive data, at least v1.0 to extract, compression method=storezip entries: 3 shown in artifact inventory JSON

Evidence Ledger

TimeActionOutput/FileFindingConfidenceNext
2026-06-11T06:08:20Zharness initchallenge-state.jsonWorkspace initialized with deterministic state fileHighInventory artifacts
2026-06-11T06:08:20Zartifact inventoryanalysis/artifact-inventory.json1 artifact(s) inventoriedHighBuild or update hypotheses
2026-06-11T06:08:20Zsession bootstrapnotes.mdChallenge metadata, scenario, and prior context seeded into workspaceHighRecord initial hypothesis and research
2026-06-11T06:08:20Zhypothesis recordedhypothesis-board.mdinitial triage from supplied challenge metadataMediuminventory files / inspect app surface / map routes depending on category
2026-06-11T06:08:20Zresearch taskanalysis/research/task-20260611T060820936111Z-1880d6b4.mdResearch task created for advisory investigationMediumRecord research output
2026-06-11T06:09:14Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T060914414768Z-8bb49e8a.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06: <REDACTED>, then read the dashboard for the flag.MediumNmap/service-identify both ports, then connect read-only with nc to identify which port is the dashboard and which is the tool before any mutation.
2026-06-11T06:10:31Zsource auditanalysis/source-audit.mdSource audit recordedHighGate before exploit
2026-06-11T06:10:52ZRAG queryanalysis/rag/rag-query-20260611T061033283496Z-3d12691d.txtRAG helper exited 0; output savedMediumRecord retrieval tag and validation
2026-06-11T06:11:40ZRAG recordanalysis/rag-records.mdRetrieved memory tagged GENERICMediumValidate or reject with live evidence
2026-06-11T06:11:55Zinstrumentation plananalysis/instrumentation-plan.mdIdentify the dashboard and planted BACnet/netcat tool ports, map the command protocol, then perform the exact Level Two mission sequence without triggering alarm resets.HighStop if the service shows an alarm/reset, if prompts are ambiguous, or after two failed command sequences without a new state fact; record failure and refresh hypothesis instead of blind probing.
2026-06-11T06:12:54Zlocal memory recordanalysis/local-memory-records.mdPrior local notes reviewed as fallback/advisory contextMediumValidate against current evidence
2026-06-11T06:13:08Zevaluatoranalysis/evaluator-20260611T061308235567Z-eda10063.mdProceedHighUse challenge_exec for nmap/curl/nc read-only probes and save transcripts before any state-changing sequence.
2026-06-11T06:14:01Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T061401525835Z-6ed79ce2.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06:19:01Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T061901215883Z-99dcc057.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06: <REDACTED>
2026-06-11T06:22:33Zbranch closedhypothesis-board.mdDoor lock and Level 2 temperature reached the intended state without alarm, but the dashboard Message stayed empty; final transcript shows both elevators drifted/stopped at Level 2, so one-shot ELE target writes do not satisfy the elevator denial condition.HighRerank hypotheses
2026-06-11T06:26:42Zbranch closedhypothesis-board.mdDoor lock, elevator current/target floors, alarm threshold, and thermostat setpoint were sustained without alarm, but dashboard Message stayed empty. Transcript shows actual Temp-L2-20 dipped below 32 during the hold, so thermostat-only control likely does not satisfy the two-minute burn condition.HighRerank hypotheses
2026-06-11T06:26:42Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T062642616755Z-f70428fe.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06:26:42Zevaluatoranalysis/evaluator-20260611T062642667155Z-378fac53.mdProceedHighPatch solver to sustain Temp-L2-20 and run one bounded mission attempt through challenge_exec.
2026-06-11T06:30:48Zbranch closedhypothesis-board.mdTemp-L2-20 analogInput is not writable, and with Therm-L2 set to 32 the actual sensor still dipped below 32 during the hold. Door/elevator/alarm controls remained valid but no dashboard Message appeared.HighRerank hypotheses
2026-06-11T06:30:48Zcheckpoint recordedanalysis/checkpoint-analysis-20260611T063048840886Z-62025272.mdCheckpoint for ANALYSISHighUse checkpoint to drive next decision
2026-06-11T06:30:48Zevaluatoranalysis/evaluator-20260611T063048891384Z-ac9286af.mdProceedHighRun high-setpoint mission attempt through challenge_exec.
2026-06-11T06: <REDACTED>
2026-06-11T06:36:35Zcompletion 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.

Scenario

Challenge: Steel Mountain. Steel Mountain is a secure facility serving major corporations like E-Corp. We've infiltrated their network and planted our tool. Final step: Burn the tapes to destroy the data. All necessary info is in the files.

Technical analogy

How to remember this solve

Think of the industrial system like a control-room checklist. You map the inputs, outputs, and assumptions, then find the one control path that accepts a state it should have rejected.

For Steel Mountain, 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.