mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-09-09 19:38:55 +02:00
Add 0x0001b_ctf challenge with companion PDFs
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,387 @@
|
||||
# CTF Challenge - Operation Black Start
|
||||
|
||||
## ⚠ WORLDGRID EMERGENCY INCIDENT ⚠
|
||||
|
||||
```
|
||||
+----------------------------------------------------------------------------------------+
|
||||
| |
|
||||
| ██████╗ ██╗ █████╗ ██████╗██╗ ██╗███████╗████████╗ █████╗ ██████╗ ████████╗ |
|
||||
| ██╔══██╗██║ ██╔══██╗██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝██╔══██╗██╔══██╗╚══██╔══╝ |
|
||||
| ██████╔╝██║ ███████║██║ █████╔╝ ███████╗ ██║ ███████║██████╔╝ ██║ |
|
||||
| ██╔══██╗██║ ██╔══██║██║ ██╔═██╗ ╚════██║ ██║ ██╔══██║██╔══██╗ ██║ |
|
||||
| ██████╔╝███████╗██║ ██║╚██████╗██║ ██╗███████╗ ██║ ██║ ██║██║ ██║ ██║ |
|
||||
| ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝██║ ██║╚══════╝ ╚═╝ ╚═╝ ╚═╝██║ ██║ ██║ |
|
||||
| |
|
||||
| |
|
||||
| O P E R A T I O N B L A C K S T A R T |
|
||||
| |
|
||||
| *** PRIORITY RED *** |
|
||||
| |
|
||||
+----------------------------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## INCIDENT BRIEFING
|
||||
|
||||
### Background
|
||||
|
||||
**WorldGrid Compact** is the emergency interconnection standard shared by
|
||||
three allied national grid operators. When any member's primary SCADA
|
||||
network goes dark, a fleet of small embedded relay nodes — call sign
|
||||
**GRID-7** — is the only thing standing between an orderly recovery and an
|
||||
uncontrolled cascade. Each relay node watches the last known grid frequency
|
||||
deviation, decides whether conditions are safe, and either **holds** the
|
||||
automatic black-start dispatch or **authorizes** it.
|
||||
|
||||
At 03:11 UTC, a coordinated cyberattack severed the primary SCADA uplink
|
||||
across the GRID-7 corridor and the WATER-3 aqueduct pumping stations that
|
||||
depend on it. With the network coordination center offline and three
|
||||
continents' worth of hospitals, rail systems, and water treatment plants
|
||||
running on backup power, WorldGrid's engineering team did the only thing
|
||||
they could: they rushed an emergency firmware build for the relay fleet and
|
||||
pushed it within **eleven minutes** of the attack being detected.
|
||||
|
||||
### The Disaster
|
||||
|
||||
The engineer who built that emergency image, **Dr. Elias Renner**, has not
|
||||
slept in thirty-one hours. He compiled the fix, ran a five-second bench
|
||||
test, and shipped it — because the alternative was leaving the relay fleet
|
||||
completely blind. It appears to work. The relay boots. It prints a status
|
||||
report. It reports **GRID STATUS: STABLE** and **DISPATCH PATH:
|
||||
AUTHORIZED**.
|
||||
|
||||
There is a problem: the frozen frequency reading latched at the moment
|
||||
communications were cut shows a deviation of **0.87 Hz** — nearly *50%
|
||||
beyond* WorldGrid's hard engineering limit of **0.60 Hz**. A deviation this
|
||||
large, if trusted, means the grid is nowhere near stable enough for an
|
||||
automatic black-start dispatch. If the fleet authorizes dispatch on a false
|
||||
"STABLE" reading, cascading generator trips will follow within minutes,
|
||||
and GRID-7 and WATER-3 will go dark for the second time — this time with no
|
||||
backup plan.
|
||||
|
||||
**Dr. Renner's rushed build has a bug. Multiple relay nodes are already
|
||||
reporting the same false-safe status. Nobody has found where in the
|
||||
compiled firmware the error lives, because the source code used for that
|
||||
emergency compile was overwritten by the next build fifteen minutes later
|
||||
and cannot be recovered.**
|
||||
|
||||
### The Only Surviving Evidence
|
||||
|
||||
One relay node — the training/verification unit — still holds the exact
|
||||
miscompiled image that shipped to the fleet. This binary, and this binary
|
||||
alone, is the only remaining copy of the emergency build. There is no
|
||||
source code. There is no build log. There is only the compiled image, a
|
||||
UART cable, and whatever a skilled embedded reverse engineer can prove by
|
||||
reading machine code.
|
||||
|
||||
### The Human Stakes
|
||||
|
||||
| Consequence if the false "STABLE" reading is trusted | Scale |
|
||||
|---|---|
|
||||
| Hospitals on generator backup past their fuel reserve | 214 facilities |
|
||||
| Water treatment and pumping stations losing pressure | 3 aqueduct systems |
|
||||
| Rail corridors stranded mid-route | 6 national rail networks |
|
||||
| Estimated population affected by cascading failure | 40+ million people |
|
||||
|
||||
**The options are:**
|
||||
|
||||
1. ❌ **Trust the fleet's reported status** — dispatch fires on a false
|
||||
reading, cascading failure follows within the hour.
|
||||
2. ❌ **Shut the entire relay fleet down** — buys time, but leaves 40
|
||||
million people with no automated recovery path at all.
|
||||
3. **REVERSE ENGINEER THE EMERGENCY BUILD** — find the exact
|
||||
miscompiled bytes, patch them, verify the corrected image on real
|
||||
hardware, and hand the fix to the field team so the *rest of the fleet*
|
||||
can be safely repatched before the next attempt.
|
||||
|
||||
### THE SHORTAGE
|
||||
|
||||
For years, the world treated embedded systems as invisible infrastructure.
|
||||
The engineers who could read a vector table, decode a Thumb branch, or
|
||||
patch a miscompiled constant directly in a stripped binary were never
|
||||
numerous enough. Tonight almost all of them are already in the field
|
||||
chasing other failures. **You are the reserve team.**
|
||||
|
||||
You were called in because you can do something Dr. Renner's exhausted
|
||||
team cannot do right now: read what the processor is actually doing, with
|
||||
no source code, no time for a rewrite, and no room for a guess.
|
||||
|
||||
> **⏰ TIME PRESSURE:** The field team is standing by to push your verified
|
||||
> patch to the rest of the GRID-7 fleet. Every relay node still reporting
|
||||
> a false "STABLE" status is one dispatch cycle away from disaster.
|
||||
|
||||
> **AUTHORIZED LAB ONLY:** This challenge uses a supplied Pico 2 training
|
||||
> relay and its exact miscompiled firmware image. Do not connect this
|
||||
> exercise to a public network, an operational grid, a water utility, or
|
||||
> any device you do not own or have explicit written authorization to test.
|
||||
|
||||
---
|
||||
|
||||
## What This CTF Tests
|
||||
|
||||
| Week | Concepts Tested |
|
||||
|------|-----------------|
|
||||
| 1 | RP2350 architecture, ARM Cortex-M33 registers, stack, flash/RAM, Thumb assembly, Ghidra static analysis |
|
||||
| 2 | GDB connection, breakpoints, disassembly, register and memory inspection, UART observation |
|
||||
| 3 | Bootrom handoff, vector table, reset handler, startup code, XIP, Thumb-bit addressing |
|
||||
|
||||
---
|
||||
|
||||
## Part 1: Understanding the Relay Node
|
||||
|
||||
### GRID-7 Relay Hardware
|
||||
|
||||
| Component | Connection | Purpose |
|
||||
|-----------|------------|---------|
|
||||
| Raspberry Pi Pico 2 | RP2350 | Runs the miscompiled emergency firmware |
|
||||
| UART TX | GPIO 0 | Relay telemetry output |
|
||||
| UART RX | GPIO 1 | Reserved (no command parser is implemented) |
|
||||
| SWD debug interface | Supplied probe | Authorized GDB inspection |
|
||||
|
||||
No LED, relay output, sensor, display, or other peripheral is part of this
|
||||
CTF. Every graded finding lives in flash (`.rodata`/`.text`) or SRAM, and is
|
||||
reachable with only the Weeks 1-3 toolset: Ghidra, GDB, and a UART monitor.
|
||||
|
||||
### UART Configuration
|
||||
|
||||
- Baud: `115200`
|
||||
- Data: `8 bits`
|
||||
- Parity: `none`
|
||||
- Stop: `1`
|
||||
- Logic: `3.3 V`
|
||||
|
||||
### Normal (Intended) Behavior
|
||||
|
||||
The relay should latch the frozen deviation reading, compare it against the
|
||||
**real** WorldGrid safety limit of **60** (0.60 Hz, encoded as an integer
|
||||
`x100`), and report honestly:
|
||||
|
||||
```
|
||||
+-----------------------------------------------------------------+
|
||||
| Intended Relay Behavior |
|
||||
| |
|
||||
| 1. Boot and initialize UART |
|
||||
| 2. Print the boot identity and a signal-quality banner |
|
||||
| 3. Compare the frozen 87 (0.87 Hz) reading against the 60 |
|
||||
| (0.60 Hz) safety limit |
|
||||
| 4. 87 exceeds 60, so the grid is NOT stable |
|
||||
| 5. Report GRID STATUS: CRITICAL and DISPATCH PATH: HELD |
|
||||
| 6. Repeat the report once per second until conditions change |
|
||||
+-----------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### Observed (Buggy) Behavior — What You Will See When You First Flash `CTF-01.uf2`
|
||||
|
||||
```text
|
||||
GLOBAL EMBEDDED RESPONSE NETWORK
|
||||
BLACK START WINDOW: 27 MINUTES
|
||||
UART0 115200 8N1 | AUTHORIZED LAB CONSOLE
|
||||
SIGNAL: NORMAL
|
||||
RESPONSE> GRID STATUS: STABLE
|
||||
DISPATCH PATH: AUTHORIZED
|
||||
LAST FRAME: QUARANTINED
|
||||
RESPONSE>
|
||||
```
|
||||
|
||||
This is exactly what Dr. Renner's team is seeing on the deployed fleet. It
|
||||
is wrong, and it is wrong in **two independent ways** inside the compiled
|
||||
binary. Do not assume the first readable sentence is the full truth —
|
||||
treat every printed line as evidence to be checked against the machine
|
||||
code, not as a fact on its own.
|
||||
|
||||
---
|
||||
|
||||
## How To Connect the Training Relay
|
||||
|
||||
- Pico 2 **GPIO 0 / UART TX** -> USB-UART adapter **RX**
|
||||
- Pico 2 **GPIO 1 / UART RX** -> USB-UART adapter **TX**
|
||||
- Pico 2 **GND** -> USB-UART adapter **GND**
|
||||
- Use **3.3 V logic only**. Never connect a 5 V line to a Pico GPIO.
|
||||
- Connect the supplied SWD probe according to its documented pinout.
|
||||
|
||||
The supplied image is `CTF-01.bin` (for Ghidra analysis) and `CTF-01.uf2`
|
||||
(for flashing). If your instructor supplies different filenames, record the
|
||||
actual filenames in your report.
|
||||
|
||||
---
|
||||
|
||||
## Part 2: The Miscompiled Firmware
|
||||
|
||||
You do not have the source code. It was overwritten fifteen minutes after
|
||||
the emergency build shipped. You have only the compiled image. Your job is
|
||||
to reverse engineer it with Ghidra, locate the defects, and patch the
|
||||
binary directly — exactly the way Dr. Renner's field team will need to
|
||||
patch the rest of the deployed fleet.
|
||||
|
||||
### What The Firmware Does
|
||||
|
||||
1. Initializes UART0 and stdio.
|
||||
2. Reads a frozen grid-frequency-deviation reading that was latched in
|
||||
memory before communications were severed.
|
||||
3. Compares that reading against a compiled-in safety threshold — **twice**,
|
||||
once for each independent status line it reports.
|
||||
4. Prints a boot banner containing an unconditional signal-quality line.
|
||||
5. Enters an infinite loop printing the grid classification and dispatch
|
||||
decision once per second.
|
||||
|
||||
### Bug Summary — What You Are Graded On
|
||||
|
||||
| Bug # | Category | Severity | Description | Hint |
|
||||
|-------|----------|----------|--------------|------|
|
||||
| **Bug #1** | Miscompiled safety constant | **CRITICAL** | The safety threshold used to classify the frozen reading was compiled far too permissive. It is used **twice** — once for the operator-facing status and once for the automated dispatch decision — and **both** copies must be corrected. | The real WorldGrid safety limit is 60 (0.60 Hz). Search for the wrong immediate value used in the comparison. |
|
||||
| **Bug #2** | Hardcoded string literal | **HIGH** | The boot banner unconditionally prints a signal-quality word that does not reflect the actual reading, regardless of what the relay later reports. | The correct word describes the true state of a 0.87 Hz deviation against a 0.60 Hz limit — not "NORMAL". |
|
||||
|
||||
**Important:** The replacement text for Bug #2 **must be the same length**
|
||||
as the original — patching a shorter or longer string will corrupt
|
||||
adjacent flash data.
|
||||
|
||||
### A Third Finding — Not a Bug, a Recovery Task
|
||||
|
||||
Somewhere in this image is the **quarantined black-start authorization
|
||||
frame** — the exact frame the relay is supposed to transmit to the
|
||||
regional dispatcher once a human operator confirms it is safe to proceed.
|
||||
It is never printed by the firmware. Recovering it (without patching
|
||||
anything) is required evidence for your final report.
|
||||
|
||||
---
|
||||
|
||||
## Part 3: Your Assignment
|
||||
|
||||
### Submission Document
|
||||
|
||||
Whenever a task asks you to **Document** or **answer**, write your answers
|
||||
in a single file named `CTF-01-Answers.md` (or `.txt`).
|
||||
|
||||
### Task 1: Setup and Initial Analysis
|
||||
|
||||
1. Create a new Ghidra project named `Black_Start_Investigation`.
|
||||
2. Import `CTF-01.bin`.
|
||||
3. Configure the language as **ARM Cortex 32-bit, little endian**.
|
||||
4. Set the base address to `0x10000000`.
|
||||
5. Run auto-analysis.
|
||||
|
||||
**Document:**
|
||||
- A screenshot of the Ghidra **Import Results** or **Program Information**
|
||||
window showing the project name, processor settings, and base address.
|
||||
- The address of `main()`.
|
||||
- The address of the recurring status loop (the branch target that repeats
|
||||
once per second).
|
||||
- The vector-table base, the initial stack pointer, and the reset-handler
|
||||
pointer as stored (note its Thumb bit) versus the actual instruction
|
||||
address.
|
||||
|
||||
### Task 2: Find and Patch Bug #1 — The Miscalibrated Safety Threshold
|
||||
|
||||
1. Find **both** locations where the frozen reading is compared against
|
||||
the miscompiled safety constant.
|
||||
2. Document the exact address, the original instruction, and the original
|
||||
immediate value at each location.
|
||||
3. Determine the correct immediate value. **Caution:** the compiler may
|
||||
not have encoded the raw threshold you expect — a strict "less than"
|
||||
comparison against an unsigned value is often optimized into a
|
||||
"less-or-equal" comparison against one less than the threshold. Show
|
||||
your reasoning.
|
||||
4. Patch **both** locations in Ghidra.
|
||||
|
||||
**Questions to answer:**
|
||||
- Why must both locations be patched? What happens if you only patch one?
|
||||
- Why is a false "STABLE" classification on an 0.87 Hz reading dangerous
|
||||
for an automated black-start dispatch?
|
||||
|
||||
### Task 3: Find and Patch Bug #2 — The False Signal Banner
|
||||
|
||||
1. Find the boot-banner string that unconditionally reports the wrong
|
||||
signal quality.
|
||||
2. Document its address and the exact bytes that must change.
|
||||
3. Patch the string, preserving its exact length.
|
||||
|
||||
**Questions to answer:**
|
||||
- Document the original vs. patched bytes, character by character.
|
||||
- Why is a hardcoded, unconditional status word more dangerous than one
|
||||
that is at least computed from a (miscalibrated) reading?
|
||||
|
||||
### Task 4: Recover the Quarantined Dispatch Frame
|
||||
|
||||
1. Use Ghidra's Defined Strings (or a raw string search) to locate the
|
||||
hidden black-start authorization frame.
|
||||
2. Document its address and explain why it is never transmitted by the
|
||||
current firmware.
|
||||
3. Do **not** attempt to patch this value — it is evidence, not a bug.
|
||||
|
||||
### Task 5: Export and Verify
|
||||
|
||||
1. Export your patched binary as `CTF-01_fixed.bin`.
|
||||
2. Convert it to UF2 format for the RP2350:
|
||||
```bash
|
||||
python uf2conv.py CTF-01_fixed.bin --base 0x10000000 --family 0xe48bff59 --output CTF-01_fixed.uf2
|
||||
```
|
||||
3. Flash `CTF-01_fixed.uf2` to your Pico 2 and capture the corrected UART
|
||||
output.
|
||||
4. Confirm that the corrected image now reports **GRID STATUS: CRITICAL**,
|
||||
**DISPATCH PATH: HELD**, and the corrected signal-quality word — an
|
||||
honest, safe report instead of a false "all clear."
|
||||
5. Build a summary table of every patch: address, original bytes, patched
|
||||
bytes, and a one-line description.
|
||||
|
||||
### Task 6: Written Reflection (short answers, 150 words or less each)
|
||||
|
||||
1. Why is "the build was rushed under emergency pressure" not an
|
||||
acceptable excuse for shipping a firmware defect that could trigger a
|
||||
cascading grid failure?
|
||||
2. Name one concrete engineering practice (code review, static analysis,
|
||||
hardware-in-the-loop test, etc.) that would have caught **each** of the
|
||||
two graded bugs before this image ever reached the fleet.
|
||||
|
||||
---
|
||||
|
||||
## Submission Format
|
||||
|
||||
Submit a folder containing:
|
||||
|
||||
- `CTF-01-Answers.md`;
|
||||
- screenshots or terminal transcripts;
|
||||
- `CTF-01_fixed.bin` and `CTF-01_fixed.uf2`;
|
||||
- the original image hash.
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
You complete the challenge when you can prove all of the following:
|
||||
|
||||
- You can explain how the RP2350 reaches the relay's code from reset.
|
||||
- You can locate and patch both copies of the miscalibrated threshold.
|
||||
- You can locate and patch the false signal-quality string without
|
||||
corrupting adjacent data.
|
||||
- You can export, convert, and flash a corrected image.
|
||||
- You can prove on real hardware that the corrected image reports the
|
||||
true, dangerous state instead of the false "all clear."
|
||||
- You can recover the quarantined dispatch frame as evidence.
|
||||
|
||||
---
|
||||
|
||||
## Academic Integrity and Safety
|
||||
|
||||
By submitting this CTF work, you certify that:
|
||||
|
||||
1. You used only the supplied training relay, image, and lab interface.
|
||||
2. You did not connect the challenge to a public network, an operational
|
||||
grid, a water utility, or any third-party device.
|
||||
3. You understand that embedded reverse engineering and binary patching
|
||||
require explicit authorization in any real-world context.
|
||||
4. You will report any discovered weakness responsibly to the course
|
||||
instructor.
|
||||
|
||||
The world is short on people who can do this work. Treat that
|
||||
responsibility seriously: verify before you patch, patch before you trust,
|
||||
and never confuse a clean-looking status line with a safe system.
|
||||
|
||||
---
|
||||
|
||||
## Reference Material
|
||||
|
||||
- ARM Cortex-M33 Technical Reference Manual
|
||||
- RP2350 datasheet
|
||||
- GDB documentation
|
||||
- Ghidra documentation: [https://ghidra-sre.org/](https://ghidra-sre.org/)
|
||||
Binary file not shown.
@@ -0,0 +1,216 @@
|
||||
# CTF Challenge: Operation Black Start
|
||||
|
||||
## Project Requirements & Grading Criteria
|
||||
|
||||
```
|
||||
+----------------------------------------------------------------------------------------+
|
||||
| |
|
||||
| ██████╗ ██╗ █████╗ ██████╗██╗ ██╗███████╗████████╗ █████╗ ██████╗ ████████╗ |
|
||||
| ██╔══██╗██║ ██╔══██╗██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝██╔══██╗██╔══██╗╚══██╔══╝ |
|
||||
| ██████╔╝██║ ███████║██║ █████╔╝ ███████╗ ██║ ███████║██████╔╝ ██║ |
|
||||
| ██╔══██╗██║ ██╔══██║██║ ██╔═██╗ ╚════██║ ██║ ██╔══██║██╔══██╗ ██║ |
|
||||
| ██████╔╝███████╗██║ ██║╚██████╗██║ ██╗███████╗ ██║ ██║ ██║██║ ██║ ██║ |
|
||||
| ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝██║ ██║╚══════╝ ╚═╝ ╚═╝ ╚═╝██║ ██║ ██║ |
|
||||
| |
|
||||
| |
|
||||
| O P E R A T I O N B L A C K S T A R T |
|
||||
| |
|
||||
| REQUIREMENTS & GRADING CRITERIA |
|
||||
| |
|
||||
+----------------------------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Project Overview
|
||||
|
||||
Students are the reverse-engineering reserve team called in after WorldGrid
|
||||
Compact's emergency firmware build shipped a miscompiled safety threshold and
|
||||
a false status string to its GRID-7 relay fleet. Students reverse engineer
|
||||
the supplied RP2350 image with Ghidra, locate two real defects, patch them
|
||||
directly in the binary, export a corrected image, flash it to real hardware,
|
||||
and verify the corrected behavior on a physical Pico 2 — the same workflow
|
||||
used in the FINAL projects.
|
||||
|
||||
Students must use only Weeks 1-3 concepts: ARM registers and stack behavior,
|
||||
UART output, GDB, Ghidra static analysis and binary patching, vector tables,
|
||||
reset startup, XIP, and Thumb addressing. No LED, relay, sensor, display, or
|
||||
later-week peripheral-control task is part of this CTF.
|
||||
|
||||
The challenge is separate from all FINAL projects and contains no FINAL-project
|
||||
answer, constant, address, bug, or patch.
|
||||
|
||||
---
|
||||
|
||||
## Learning Objectives
|
||||
|
||||
Students will demonstrate the ability to:
|
||||
|
||||
1. Capture a clean UART baseline before modifying the binary.
|
||||
2. Decode an RP2350 vector table and initial stack pointer.
|
||||
3. Explain the Thumb bit in a reset-handler pointer.
|
||||
4. Trace a flash string into the UART output call and argument register.
|
||||
5. Locate a miscompiled immediate value used in **multiple** locations and
|
||||
understand why every occurrence must be patched.
|
||||
6. Correctly compute a patched immediate value even when the compiler has
|
||||
transformed the original comparison (e.g., `<` optimized to `<=`).
|
||||
7. Patch a string literal in flash without corrupting adjacent data.
|
||||
8. Export a patched binary, convert it to UF2, and verify the fix on real
|
||||
hardware.
|
||||
9. Recover a quarantined data frame from flash as static evidence.
|
||||
|
||||
---
|
||||
|
||||
## Deliverables Checklist
|
||||
|
||||
| # | Deliverable | Format | Task |
|
||||
|---|-------------|--------|------|
|
||||
| 1 | Ghidra project screenshot (project name, processor, base address) | PNG/JPG | Task 1 |
|
||||
| 2 | `main()`, status-loop, and vector-table address table | Inside `CTF-01-Answers.md` | Task 1 |
|
||||
| 3 | Bug #1 analysis: both addresses, original/patched bytes, immediate-value reasoning | Inside `CTF-01-Answers.md` | Task 2 |
|
||||
| 4 | Bug #2 analysis: string address, original/patched bytes, character-by-character mapping | Inside `CTF-01-Answers.md` | Task 3 |
|
||||
| 5 | Recovered dispatch frame and its address | Inside `CTF-01-Answers.md` | Task 4 |
|
||||
| 6 | `CTF-01_fixed.bin` — exported patched binary | BIN file | Task 5 |
|
||||
| 7 | `CTF-01_fixed.uf2` — UF2-converted binary | UF2 file | Task 5 |
|
||||
| 8 | Verification transcript: corrected UART output on real hardware | Inside `CTF-01-Answers.md` | Task 5 |
|
||||
| 9 | Summary table of all patches (address, original bytes, patched bytes) | Inside `CTF-01-Answers.md` | Task 5 |
|
||||
| 10 | Written reflection (two short answers) | Inside `CTF-01-Answers.md` | Task 6 |
|
||||
|
||||
---
|
||||
|
||||
## Required Tools and Equipment
|
||||
|
||||
| Tool | Purpose | Required For |
|
||||
|------|---------|-------------|
|
||||
| Raspberry Pi Pico 2 | Isolated target | All tasks |
|
||||
| 3.3 V USB-UART adapter | UART capture | Tasks 1, 5 |
|
||||
| Serial monitor | Observe output | Tasks 1, 5 |
|
||||
| Ghidra | Static analysis and binary patching | Tasks 1-4 |
|
||||
| Python (`uf2conv.py`) | UF2 conversion | Task 5 |
|
||||
| `CTF-01.bin` and `CTF-01.uf2` | Supplied artifacts | All tasks |
|
||||
|
||||
UART settings: **115200 baud, 8 data bits, no parity, 1 stop bit**.
|
||||
|
||||
The instructor-issued artifact hashes are:
|
||||
|
||||
```text
|
||||
CTF-01.bin 6FD296F7A85F243FB26BF6BFFCBEAB26815FD8915101A81F72069063A5635E5A
|
||||
CTF-01.uf2 980F04369C23AD32A063DFE18DE5AF08DF3830138FC7E7898B1F011B4F5E1D9D
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Setup and Initial Analysis — 15 points
|
||||
|
||||
| Criterion | Points | Full Credit | Partial Credit | No Credit |
|
||||
|-----------|--------|-------------|----------------|-----------|
|
||||
| Ghidra project setup | 3 | Screenshot shows correct project name, ARM Cortex 32-bit little endian, base `0x10000000` | One item off | Not set up |
|
||||
| `main()` and status-loop addresses | 4 | Both addresses correctly documented | One correct | Neither found |
|
||||
| Vector table | 4 | Correct base, initial SP, reset pointer | One missing | Not found |
|
||||
| Thumb addressing | 4 | Correctly clears bit 0 to identify the real instruction address | General explanation | Incorrect |
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Find and Patch Bug #1 — Miscalibrated Safety Threshold — 30 points
|
||||
|
||||
**What to find:** the frozen reading is compared against a miscompiled
|
||||
safety constant at **two separate addresses** — once for the operator-facing
|
||||
status and once for the automated dispatch decision.
|
||||
|
||||
| Criterion | Points | Full Credit | Partial Credit | No Credit |
|
||||
|-----------|--------|-------------|----------------|-----------|
|
||||
| Found location A | 5 | Correct address and original instruction/bytes documented | Address off | Not found |
|
||||
| Found location B | 5 | Correct address and original instruction/bytes documented | Address off | Not found |
|
||||
| Correct immediate-value reasoning | 8 | Explains the `<` vs `<=` compiler transform and derives the correct patched immediate | Correct value, no reasoning | Wrong value |
|
||||
| Patched location A | 4 | Grader verifies the byte change | Wrong byte | Not patched |
|
||||
| Patched location B | 4 | Grader verifies the byte change | Wrong byte | Not patched |
|
||||
| Explained why both must be patched | 4 | Clear explanation of duplicated/independent comparisons | Vague | Missing |
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Find and Patch Bug #2 — The False Signal Banner — 20 points
|
||||
|
||||
| Criterion | Points | Full Credit | Partial Credit | No Credit |
|
||||
|-----------|--------|-------------|----------------|-----------|
|
||||
| Found the string | 5 | Correct address, found via Ghidra Defined Strings or hex inspection | Approximate | Not found |
|
||||
| Patched correctly | 8 | All required bytes changed, string length preserved, grader verifies boot output | Correct text but wrong bytes documented | Wrong length or corrupted data |
|
||||
| Character-by-character documentation | 4 | Original vs. patched bytes for every changed character | Partial | Missing |
|
||||
| Explained the danger of a hardcoded status word | 3 | Clear, specific reasoning | Generic | Missing |
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Recover the Quarantined Dispatch Frame — 10 points
|
||||
|
||||
| Criterion | Points | Full Credit | Partial Credit | No Credit |
|
||||
|-----------|--------|-------------|----------------|-----------|
|
||||
| Found the hidden frame | 6 | Correct address and full recovered text | Partial text | Not found |
|
||||
| Explained why it is not transmitted | 4 | Clear static-analysis explanation | Vague | Missing |
|
||||
|
||||
Students must **not** patch this value; it is evidence only.
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Export and Verify — 20 points
|
||||
|
||||
| Criterion | Points | Full Credit | Partial Credit | No Credit |
|
||||
|-----------|--------|-------------|----------------|-----------|
|
||||
| Exported patched binary | 4 | Valid `CTF-01_fixed.bin` submitted | Corrupted | Not submitted |
|
||||
| Converted to UF2 correctly | 4 | Valid `CTF-01_fixed.uf2`, correct base/family flags | Wrong flags | Not submitted |
|
||||
| Hardware verification | 8 | Grader confirms corrected UART output: `GRID STATUS: CRITICAL`, `DISPATCH PATH: HELD`, corrected signal word | Only some lines corrected | No verification |
|
||||
| Summary table of all patches | 4 | Complete table with addresses and before/after bytes | Missing entries | No table |
|
||||
|
||||
---
|
||||
|
||||
## Task 6: Written Reflection — 5 points
|
||||
|
||||
| Criterion | Points | Full Credit | Partial Credit | No Credit |
|
||||
|-----------|--------|-------------|----------------|-----------|
|
||||
| "Rushed build" is not an excuse | 2 | Specific, grounded reasoning | Generic | Missing |
|
||||
| Engineering practice per bug | 3 | Names one concrete, relevant practice for **each** bug | Names one for only one bug | Missing |
|
||||
|
||||
---
|
||||
|
||||
## Recommended Answer File Structure
|
||||
|
||||
```text
|
||||
# Operation Black Start - Incident Report
|
||||
## 1. Scope and Artifact Integrity
|
||||
## 2. Ghidra Setup and Boot/Vector Table
|
||||
## 3. Bug #1 - Miscalibrated Safety Threshold
|
||||
## 4. Bug #2 - False Signal Banner
|
||||
## 5. Recovered Dispatch Frame
|
||||
## 6. Export and Hardware Verification
|
||||
## 7. Patch Summary Table
|
||||
## 8. Written Reflection
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠ Common Pitfalls
|
||||
|
||||
| Pitfall | Consequence | Avoidance |
|
||||
|---------|-------------|-----------|
|
||||
| Patching only one of the two threshold locations | Half the fleet's telemetry still lies | Search for **every** occurrence of the wrong immediate |
|
||||
| Assuming the threshold immediate equals the safety limit directly | Off-by-one patch, wrong behavior | Check whether the compiler used `<` or `<=` semantics |
|
||||
| Replacing a string with a different length | Corrupts adjacent flash data | Count bytes before patching |
|
||||
| Treating an odd vector address as invalid | Thumb analysis fails | Explain bit 0 |
|
||||
| Skipping hardware verification | Patch is unproven | Flash and capture real UART output |
|
||||
| Modifying the quarantined dispatch frame | Destroys required evidence | Recover it, do not patch it |
|
||||
|
||||
---
|
||||
|
||||
## Reference Memory Map
|
||||
|
||||
| Region | Address | Purpose |
|
||||
|--------|---------|---------|
|
||||
| Bootrom | `0x00000000` | Immutable boot code |
|
||||
| Flash/XIP | `0x10000000` | Vector table, code, constant strings |
|
||||
| SRAM | `0x20000000` | Stack and writable state |
|
||||
|
||||
---
|
||||
|
||||
## Safety and Academic Integrity
|
||||
|
||||
Use only the supplied Pico 2 and firmware. Do not connect the exercise to an
|
||||
operational grid, water plant, public network, military system, or third-party
|
||||
device. This is a controlled, isolated educational exercise.
|
||||
Binary file not shown.
@@ -0,0 +1,311 @@
|
||||
# CTF Challenge - Operation Black Start
|
||||
|
||||
## Instructor Solution Key
|
||||
|
||||
```
|
||||
+----------------------------------------------------------------------------------------+
|
||||
| |
|
||||
| ██████╗ ██╗ █████╗ ██████╗██╗ ██╗███████╗████████╗ █████╗ ██████╗ ████████╗ |
|
||||
| ██╔══██╗██║ ██╔══██╗██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝██╔══██╗██╔══██╗╚══██╔══╝ |
|
||||
| ██████╔╝██║ ███████║██║ █████╔╝ ███████╗ ██║ ███████║██████╔╝ ██║ |
|
||||
| ██╔══██╗██║ ██╔══██║██║ ██╔═██╗ ╚════██║ ██║ ██╔══██║██╔══██╗ ██║ |
|
||||
| ██████╔╝███████╗██║ ██║╚██████╗██║ ██╗███████╗ ██║ ██║ ██║██║ ██║ ██║ |
|
||||
| ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝██║ ██║╚══════╝ ╚═╝ ╚═╝ ╚═╝██║ ██║ ██║ |
|
||||
| |
|
||||
| |
|
||||
| O P E R A T I O N B L A C K S T A R T |
|
||||
| |
|
||||
| *** INSTRUCTOR SOLUTION KEY - RESTRICTED *** |
|
||||
| |
|
||||
+----------------------------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
> This key is for Operation Black Start only. It contains no FINAL-project
|
||||
> answers, constants, addresses, bugs, or patches.
|
||||
|
||||
---
|
||||
|
||||
## Artifact Identity
|
||||
|
||||
| Artifact | Value |
|
||||
|----------|-------|
|
||||
| Student image | `CTF-01.bin` |
|
||||
| Flash image | `CTF-01.uf2` |
|
||||
| Target | Raspberry Pi Pico 2 / RP2350 ARM |
|
||||
| Image base | `0x10000000` |
|
||||
| UART | UART0, GPIO 0 TX / GPIO 1 RX, 115200 8N1 |
|
||||
|
||||
```text
|
||||
CTF-01.bin 6FD296F7A85F243FB26BF6BFFCBEAB26815FD8915101A81F72069063A5635E5A
|
||||
CTF-01.uf2 980F04369C23AD32A063DFE18DE5AF08DF3830138FC7E7898B1F011B4F5E1D9D
|
||||
```
|
||||
|
||||
Every address and byte value below was independently verified against the
|
||||
compiled ELF (`arm-none-eabi-nm`, `arm-none-eabi-objdump`) and the raw bytes
|
||||
of the delivered `CTF-01.bin` (direct hex read at each file offset). This
|
||||
image contains **no** LED, relay, sensor, display, or GPIO-control logic.
|
||||
|
||||
---
|
||||
|
||||
## Instructor Scenario
|
||||
|
||||
WorldGrid Compact's emergency firmware build for the GRID-7 relay fleet was
|
||||
compiled and shipped eleven minutes after a cyberattack severed the primary
|
||||
SCADA uplink. The engineer (Dr. Elias Renner) had no time to review the
|
||||
build; the source used for that compile no longer exists. The training
|
||||
relay supplied to students holds the exact miscompiled image that shipped
|
||||
to the fleet, containing two real, independently patchable defects.
|
||||
|
||||
Students must reconstruct the boot path, locate both defects with Ghidra,
|
||||
patch the binary directly, export and convert it, and prove the corrected
|
||||
behavior on real hardware — the same workflow used in the FINAL projects.
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Setup and Initial Analysis Solution
|
||||
|
||||
### Vector Table (first 32 bytes of `CTF-01.bin`)
|
||||
|
||||
```text
|
||||
00 20 08 20 5B 01 00 10 1B 01 00 10 1D 01 00 10
|
||||
11 01 00 10 11 01 00 10 11 01 00 10 11 01 00 10
|
||||
```
|
||||
|
||||
| Evidence | Answer |
|
||||
|----------|--------|
|
||||
| Vector table base | `0x10000000` |
|
||||
| Initial SP | `0x20082000` |
|
||||
| Reset pointer (as stored) | `0x1000015b` |
|
||||
| Reset instruction address (bit 0 cleared) | `0x1000015a` |
|
||||
| `main()` | `0x100001e0` |
|
||||
| Recurring status loop start | `0x10000234` |
|
||||
| Loop branch (`b.n` back to loop start) | `0x10000246` |
|
||||
|
||||
### Data Symbols
|
||||
|
||||
| Symbol | Address | Notes |
|
||||
|--------|---------|-------|
|
||||
| `grid_deviation` | `0x200005d8` | Initialized to `87` (0.87 Hz x100), lives in `.data` |
|
||||
| `operator_state` | `0x20000844` | Zero-initialized, `.bss` |
|
||||
| `dispatch_state` | `0x20000834` | Zero-initialized, `.bss` |
|
||||
| `dispatch_frame` | `0x100037a0` | Hidden black-start frame, `.rodata` |
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Bug #1 Solution — Miscalibrated Safety Threshold
|
||||
|
||||
`grid_deviation` is declared `volatile`, so the compiler cannot reuse one
|
||||
comparison for both output paths — it emits **two independent** compare
|
||||
instructions, one for `operator_state` and one for `dispatch_state`:
|
||||
|
||||
```text
|
||||
100001f8: 6813 ldr r3, [r2, #0] ; r3 = grid_deviation
|
||||
100001fc: 2b5e cmp r3, #94 @ 0x5e ; <-- PATCH LOCATION A
|
||||
100001fe: bf8c ite hi
|
||||
10000200: 2300 movhi r3, #0 ; operator_state = 0 (CRITICAL)
|
||||
10000202: 2301 movls r3, #1 ; operator_state = 1 (STABLE)
|
||||
10000204: 6033 str r3, [r6, #0]
|
||||
|
||||
10000206: 6813 ldr r3, [r2, #0] ; r3 = grid_deviation (2nd read)
|
||||
1000020a: 2b5e cmp r3, #94 @ 0x5e ; <-- PATCH LOCATION B
|
||||
1000020c: bf8c ite hi
|
||||
1000020e: 2300 movhi r3, #0 ; dispatch_state = 0 (HELD)
|
||||
10000210: 2301 movls r3, #1 ; dispatch_state = 1 (AUTHORIZED)
|
||||
10000212: 602b str r3, [r5, #0]
|
||||
```
|
||||
|
||||
### Why the immediate is 94, not 95
|
||||
|
||||
The source-level constant is `SAFE_THRESHOLD = 95`, and the intended test is
|
||||
`grid_deviation < 95`. For an **unsigned** comparison, GCC legally rewrites
|
||||
`x < 95` as `x <= 94` (`ite hi`/`movhi`/`movls` on the `hi`/`ls` unsigned
|
||||
condition codes), which lets it use a single `cmp` + `ite` sequence instead
|
||||
of a separate branch. The compiled immediate is therefore **one less** than
|
||||
the source constant.
|
||||
|
||||
The correct engineering limit is **60**. Applying the same compiler
|
||||
transform, `x < 60` becomes `x <= 59`, so the **correct patched immediate is
|
||||
`0x3B` (59), not `0x3C` (60)**. A student who patches to `0x3C` without
|
||||
understanding this transform will get a binary that misclassifies a
|
||||
`grid_deviation` of exactly 60.
|
||||
|
||||
### Exact Byte Patch (both locations, identical change)
|
||||
|
||||
| Location | File Offset | Address | Original Bytes | Patched Bytes | Instruction Before | Instruction After |
|
||||
|----------|-------------|---------|-----------------|----------------|---------------------|---------------------|
|
||||
| A | `0x1FC` | `0x100001fc` | `5E 2B` | `3B 2B` | `cmp r3, #0x5e` | `cmp r3, #0x3b` |
|
||||
| B | `0x20A` | `0x1000020a` | `5E 2B` | `3B 2B` | `cmp r3, #0x5e` | `cmp r3, #0x3b` |
|
||||
|
||||
Both changes independently verified against the raw bytes of `CTF-01.bin`.
|
||||
|
||||
### Why both must be patched
|
||||
|
||||
`operator_state` (GRID STATUS line) and `dispatch_state` (DISPATCH PATH
|
||||
line) are each computed from their **own** re-read of `grid_deviation`
|
||||
against their **own** copy of the compiled threshold. Patching only
|
||||
location A fixes what is *displayed* to a human operator while leaving the
|
||||
*automated dispatch decision* (location B) still authorizing a black start
|
||||
on a dangerous reading — the worst possible partial fix, because it makes
|
||||
the display look trustworthy while the machine still does the wrong thing.
|
||||
|
||||
### Grid math with the frozen reading (87)
|
||||
|
||||
| Threshold used | Comparison | Result |
|
||||
|---|---|---|
|
||||
| Miscompiled: `<= 94` | `87 <= 94` -> true | `STABLE` / `AUTHORIZED` (false-safe) |
|
||||
| Corrected: `<= 59` | `87 <= 59` -> false | `CRITICAL` / `HELD` (true, safe) |
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Bug #2 Solution — The False Signal Banner
|
||||
|
||||
The unconditional boot-banner string lives in `.rodata`:
|
||||
|
||||
| String | Address |
|
||||
|--------|---------|
|
||||
| `"SIGNAL: NORMAL\r"` (printed via `puts`, which appends `\n`) | `0x10003678` |
|
||||
| `"NORMAL"` substring to patch | `0x10003680` |
|
||||
|
||||
Call site: `0x10000224` loads `r0 = 0x10003678`; `0x10000226` calls
|
||||
`__wrap_puts`. This line prints once, at boot, and is never re-evaluated —
|
||||
it does not depend on `grid_deviation` at all.
|
||||
|
||||
### Exact Byte Patch (6 bytes, same length: `NORMAL` -> `DANGER`)
|
||||
|
||||
| Address | Original Char | Original Byte | Patched Char | Patched Byte |
|
||||
|---------|----------------|----------------|----------------|----------------|
|
||||
| `0x10003680` | N | `4E` | D | `44` |
|
||||
| `0x10003681` | O | `4F` | A | `41` |
|
||||
| `0x10003682` | R | `52` | N | `4E` |
|
||||
| `0x10003683` | M | `4D` | G | `47` |
|
||||
| `0x10003684` | A | `41` | E | `45` |
|
||||
| `0x10003685` | L | `4C` | R | `52` |
|
||||
|
||||
Verified directly against the delivered `CTF-01.bin` (ASCII read at
|
||||
`0x10003678` returns exactly `SIGNAL: NORMAL`).
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Recovered Dispatch Frame Solution
|
||||
|
||||
```text
|
||||
WORLDGRID:BLACKSTART:GRID-7:WATER-3
|
||||
```
|
||||
|
||||
Address: `0x100037a0` (flash `.rodata`). It is retained in the image through
|
||||
a non-disclosing runtime anchor (`retain_dispatch_frame()`), so it survives
|
||||
linker garbage collection but is never passed to a print routine. Full
|
||||
credit requires a Ghidra Defined-Strings or cross-reference explanation, not
|
||||
a guess from the narrative. Students must not patch this value.
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Export and Verify Solution
|
||||
|
||||
### Expected UART Transcript — Before Patching
|
||||
|
||||
```text
|
||||
GLOBAL EMBEDDED RESPONSE NETWORK
|
||||
BLACK START WINDOW: 27 MINUTES
|
||||
UART0 115200 8N1 | AUTHORIZED LAB CONSOLE
|
||||
SIGNAL: NORMAL
|
||||
RESPONSE> GRID STATUS: STABLE
|
||||
DISPATCH PATH: AUTHORIZED
|
||||
LAST FRAME: QUARANTINED
|
||||
RESPONSE>
|
||||
```
|
||||
|
||||
### Expected UART Transcript — After All Three Byte Patches
|
||||
|
||||
```text
|
||||
GLOBAL EMBEDDED RESPONSE NETWORK
|
||||
BLACK START WINDOW: 27 MINUTES
|
||||
UART0 115200 8N1 | AUTHORIZED LAB CONSOLE
|
||||
SIGNAL: DANGER
|
||||
RESPONSE> GRID STATUS: CRITICAL
|
||||
DISPATCH PATH: HELD
|
||||
LAST FRAME: QUARANTINED
|
||||
RESPONSE>
|
||||
```
|
||||
|
||||
### Complete Patch Summary Table
|
||||
|
||||
| # | What | Address(es) | Original | Patched |
|
||||
|---|------|--------------|----------|---------|
|
||||
| 1a | GRID STATUS threshold compare | `0x100001fc` | `5E 2B` | `3B 2B` |
|
||||
| 1b | DISPATCH PATH threshold compare | `0x1000020a` | `5E 2B` | `3B 2B` |
|
||||
| 2 | Boot banner signal word | `0x10003680`-`0x10003685` | `4E 4F 52 4D 41 4C` (NORMAL) | `44 41 4E 47 45 52` (DANGER) |
|
||||
|
||||
Total: **8 bytes changed** to correct a false-safe reading on a fleet
|
||||
responsible for tens of millions of people.
|
||||
|
||||
### UF2 Conversion
|
||||
|
||||
```bash
|
||||
python uf2conv.py CTF-01_fixed.bin --base 0x10000000 --family 0xe48bff59 --output CTF-01_fixed.uf2
|
||||
```
|
||||
|
||||
### Hardware Verification Note
|
||||
|
||||
The vector table, boot path, and every byte offset above were verified by
|
||||
direct inspection of the compiled ELF and the delivered `CTF-01.bin` (two
|
||||
independent cross-checks: disassembly-derived addresses and raw hex-dump
|
||||
addresses agree exactly). A live UART capture on physical hardware is the
|
||||
final confirmation step and should be performed with the Pico in BOOTSEL
|
||||
mode before grading a submission that claims hardware verification.
|
||||
|
||||
---
|
||||
|
||||
## Grading Notes
|
||||
|
||||
Accept equivalent addresses when a student's Ghidra auto-analysis produces
|
||||
slightly different intermediate labels, provided the byte-level patch
|
||||
locations and values match this key. Do not award credit for a `0x3C` patch
|
||||
to the threshold immediates without a correct explanation of the `<`/`<=`
|
||||
compiler transform — that is a coincidentally-close but technically
|
||||
incorrect answer for the boundary case `grid_deviation == 60`.
|
||||
|
||||
A complete answer finds both threshold locations, explains the compiler's
|
||||
comparison transform, patches all three locations, and proves the corrected
|
||||
behavior on real hardware.
|
||||
|
||||
---
|
||||
|
||||
## Task 6: Written Reflection Solution Guidance
|
||||
|
||||
There is no single "correct" essay for either question. Grade for specific,
|
||||
grounded reasoning tied to *this* incident, not generic statements.
|
||||
|
||||
**Question 1 — Why "rushed under emergency pressure" is not an excuse:**
|
||||
An acceptable answer names the actual failure mode: an eleven-minute compile
|
||||
with no review path shipped an integer threshold that was never checked
|
||||
against the documented 60-unit engineering limit, and a hardcoded status
|
||||
string that was never wired to the real reading at all. "We were under
|
||||
pressure" explains *why* the review step was skipped; it does not change
|
||||
the fact that the skipped step is what caused the false-safe report. Full
|
||||
credit requires the student to connect the excuse to the specific missing
|
||||
safeguard (code review or automated bounds-checking), not just assert that
|
||||
pressure is never an excuse.
|
||||
|
||||
**Question 2 — One practice per bug:**
|
||||
- Bug #1 (miscalibrated, duplicated threshold): a unit test or static
|
||||
analysis rule that checks every comparison against `SAFE_THRESHOLD`
|
||||
matches a single source of truth, or a code review that would have asked
|
||||
"why is this threshold checked in two places instead of one shared
|
||||
function?"
|
||||
- Bug #2 (hardcoded status string): a hardware-in-the-loop smoke test that
|
||||
compares the boot banner's signal word against the actual latched
|
||||
reading, which would have caught a string that never changes regardless
|
||||
of input.
|
||||
|
||||
Award full credit only when the named practice is specific enough that it
|
||||
would plausibly have caught that exact bug, not a generic "more testing"
|
||||
answer.
|
||||
|
||||
---
|
||||
|
||||
## ⚠ Safety
|
||||
|
||||
Use only the supplied Pico 2, 3.3 V UART adapter, and firmware. Never
|
||||
connect the exercise to an operational grid, water plant, public network,
|
||||
military system, or third-party device.
|
||||
Binary file not shown.
@@ -118,6 +118,12 @@ Embedded System Analysis: Understanding the RP2350 Architecture w/ Comprehensive
|
||||
|
||||
### Week 3 Notebook [HERE](https://github.com/mytechnotalent/Embedded-Hacking/blob/main/WEEK03/WEEK03.md)
|
||||
|
||||
### CTF Instructions [HERE](https://github.com/mytechnotalent/Embedded-Hacking/blob/main/0x0001b_ctf/CTF-I.md)
|
||||
|
||||
### CTF Rubric [HERE](https://github.com/mytechnotalent/Embedded-Hacking/blob/main/0x0001b_ctf/CTF-R.md)
|
||||
|
||||
### CTF Solution [HERE](https://github.com/mytechnotalent/Embedded-Hacking/blob/main/0x0001b_ctf/CTF-S.md)
|
||||
|
||||
### Chapter 4: Embedded System Analysis
|
||||
This chapter covers a comprehensive embedded system analysis reviewing parts of the RP2350 datasheet and helpful firmware analysis tools.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user