Update README.md

This commit is contained in:
Kevin Thomas committed 2026-09-27 19:23:22 -04:00
1 parent 35eacd2c0e
commit b3e0a05ade
24 files changed
+56 -118

No files matched your search

Binary file not shown.
+3 -3
View File
@@ -90,8 +90,8 @@ UART settings: **115200 baud, 8 data bits, no parity, 1 stop bit**.
The instructor-issued artifact hashes are: The instructor-issued artifact hashes are:
```text ```text
CTF-01.bin 6FD296F7A85F243FB26BF6BFFCBEAB26815FD8915101A81F72069063A5635E5A CTF-01.bin 425591AC17FF4C22206286EE6F40B06A89523483804850A41854A9B6F89D7B70
CTF-01.uf2 980F04369C23AD32A063DFE18DE5AF08DF3830138FC7E7898B1F011B4F5E1D9D CTF-01.uf2 B1552EE3BB5763D96C65D8DF1C86984EE842EF1A823FDF5D94132B1E10FF9D16
``` ```
--- ---
@@ -102,7 +102,7 @@ CTF-01.uf2 980F04369C23AD32A063DFE18DE5AF08DF3830138FC7E7898B1F011B4F5E1D9D
| Criterion | Points | Full credit | Partial credit | No credit | | Criterion | Points | Full credit | Partial credit | No credit |
|-----------|--------|-------------|----------------|-----------| |-----------|--------|-------------|----------------|-----------|
| Criterion 1.1: Ghidra Project Setup | 3 | Correct project name, `ARM Cortex 32-bit little endian`, base `0x10000000` | One item off | Not set up | | Criterion 1.1: Ghidra Project Setup | 3 | Correct project name, `ARM:LE:32:Cortex` (ARM Cortex 32-bit little endian), base `0x10000000` | One item off | Not set up |
| Criterion 1.2: main() and Status-Loop Addresses | 4 | Both addresses correct | One correct | Neither found | | Criterion 1.2: main() and Status-Loop Addresses | 4 | Both addresses correct | One correct | Neither found |
| Criterion 1.3: Vector Table Decoding | 4 | Correct base, initial SP, reset pointer | One missing | Not found | | Criterion 1.3: Vector Table Decoding | 4 | Correct base, initial SP, reset pointer | One missing | Not found |
| Criterion 1.4: Thumb Addressing | 4 | Correctly clears bit 0 and identifies `main()` | General explanation | Incorrect | | Criterion 1.4: Thumb Addressing | 4 | Correctly clears bit 0 and identifies `main()` | General explanation | Incorrect |
Binary file not shown.
+3 -3
View File
@@ -34,8 +34,8 @@
| Console | UART0, GPIO 0 TX / GPIO 1 RX, 115200 8N1 | | Console | UART0, GPIO 0 TX / GPIO 1 RX, 115200 8N1 |
```text ```text
CTF-01.bin 6FD296F7A85F243FB26BF6BFFCBEAB26815FD8915101A81F72069063A5635E5A CTF-01.bin 425591AC17FF4C22206286EE6F40B06A89523483804850A41854A9B6F89D7B70
CTF-01.uf2 980F04369C23AD32A063DFE18DE5AF08DF3830138FC7E7898B1F011B4F5E1D9D CTF-01.uf2 B1552EE3BB5763D96C65D8DF1C86984EE842EF1A823FDF5D94132B1E10FF9D16
``` ```
Proof tool: `python3 scripts/verify_ctf.py` returns `11/11 checks passed` against Proof tool: `python3 scripts/verify_ctf.py` returns `11/11 checks passed` against
@@ -87,7 +87,7 @@ mode. Clearing bit 0 (`0x1000015B & ~1`) gives the real instruction address
| Criterion | Points | Full Credit (Answer Key) | Partial Credit | No Credit | | Criterion | Points | Full Credit (Answer Key) | Partial Credit | No Credit |
|-----------|--------|--------------------------|----------------|-----------| |-----------|--------|--------------------------|----------------|-----------|
| Criterion 1.1: Ghidra Project Setup | 3 | Correct project name, `ARM Cortex 32-bit little endian`, base `0x10000000` | One item off | Not set up | | Criterion 1.1: Ghidra Project Setup | 3 | Correct project name, `ARM:LE:32:Cortex` (ARM Cortex 32-bit little endian), base `0x10000000` | One item off | Not set up |
| Criterion 1.2: main() and Status-Loop Addresses | 4 | Both addresses correct | One correct | Neither found | | Criterion 1.2: main() and Status-Loop Addresses | 4 | Both addresses correct | One correct | Neither found |
| Criterion 1.3: Vector Table Decoding | 4 | Correct base, initial SP, reset pointer | One missing | Not found | | Criterion 1.3: Vector Table Decoding | 4 | Correct base, initial SP, reset pointer | One missing | Not found |
| Criterion 1.4: Thumb Addressing | 4 | Correctly clears bit 0 and identifies `main()` | General explanation | Incorrect | | Criterion 1.4: Thumb Addressing | 4 | Correctly clears bit 0 and identifies `main()` | General explanation | Incorrect |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+18 -2
View File
@@ -31,6 +31,9 @@
#ifndef CONSOLE_H #ifndef CONSOLE_H
#define CONSOLE_H #define CONSOLE_H
#include "grid.h"
#include <stdio.h>
/** /**
* @brief Print the response controller's boot identity and unconditional signal line. * @brief Print the response controller's boot identity and unconditional signal line.
* *
@@ -40,7 +43,14 @@
* @param None. * @param None.
* @return None. * @return None.
*/ */
void print_boot_banner(void); static inline void print_boot_banner(void)
{
printf("GLOBAL EMBEDDED RESPONSE NETWORK\r\n");
printf("BLACK START WINDOW: 27 MINUTES\r\n");
printf("UART0 115200 8N1 | AUTHORIZED LAB CONSOLE\r\n");
printf("SIGNAL: NORMAL\r\n");
printf("RESPONSE> ");
}
/** /**
* @brief Print the recurring grid classification and dispatch authorization report. * @brief Print the recurring grid classification and dispatch authorization report.
@@ -51,6 +61,12 @@ void print_boot_banner(void);
* @param None. * @param None.
* @return None. * @return None.
*/ */
void print_status(void); static inline void print_status(void)
{
printf("GRID STATUS: %s\r\n", operator_state ? "STABLE" : "CRITICAL");
printf("DISPATCH PATH: %s\r\n", dispatch_state ? "AUTHORIZED" : "HELD");
printf("LAST FRAME: QUARANTINED\r\n");
printf("RESPONSE> ");
}
#endif // CONSOLE_H #endif // CONSOLE_H
+16 -4
View File
@@ -46,6 +46,22 @@ extern volatile uint32_t operator_state;
// Automated dispatch authorization decision (drives DISPATCH PATH). // Automated dispatch authorization decision (drives DISPATCH PATH).
extern volatile uint32_t dispatch_state; extern volatile uint32_t dispatch_state;
// Quarantined black-start authorization frame, retained in flash, never sent.
static volatile const char dispatch_frame[] =
"WORLDGRID:BLACKSTART:GRID-7:WATER-3";
static inline void retain_dispatch_frame(void)
{
volatile char frame_marker = dispatch_frame[0];
(void)frame_marker;
}
static inline void evaluate_grid(void)
{
operator_state = (grid_deviation < SAFE_THRESHOLD) ? 1 : 0;
dispatch_state = (grid_deviation < SAFE_THRESHOLD) ? 1 : 0;
}
/** /**
* @brief Anchor the hidden dispatch frame in flash without transmitting it. * @brief Anchor the hidden dispatch frame in flash without transmitting it.
* *
@@ -56,8 +72,6 @@ extern volatile uint32_t dispatch_state;
* @param None. * @param None.
* @return None. * @return None.
*/ */
void retain_dispatch_frame(void);
/** /**
* @brief Classify the frozen telemetry reading against the compiled threshold. * @brief Classify the frozen telemetry reading against the compiled threshold.
* *
@@ -68,6 +82,4 @@ void retain_dispatch_frame(void);
* @param None. * @param None.
* @return None. * @return None.
*/ */
void evaluate_grid(void);
#endif // GRID_H #endif // GRID_H
+2 -2
View File
@@ -14,8 +14,8 @@ ROOT = Path(__file__).resolve().parent.parent
BIN = ROOT / "CTF-01.bin" BIN = ROOT / "CTF-01.bin"
UF2 = ROOT / "CTF-01.uf2" UF2 = ROOT / "CTF-01.uf2"
EXPECTED_BIN_SHA = "6fd296f7a85f243fb26bf6bffcbeab26815fd8915101a81f72069063a5635e5a" EXPECTED_BIN_SHA = "425591ac17ff4c22206286ee6f40b06a89523483804850a41854a9b6f89d7b70"
EXPECTED_UF2_SHA = "980f04369c23ad32a063dfe18de5af08df3830138fc7e7898b1f011b4f5e1d9d" EXPECTED_UF2_SHA = "b1552ee3bb5763d96c65d8df1c86984ee842ef1a823fdf5d94132b1e10ff9d16"
CMP_A = 0x100001FC CMP_A = 0x100001FC
CMP_B = 0x1000020A CMP_B = 0x1000020A
-49
View File
@@ -1,50 +1 @@
// MIT License
//
// Copyright (c) 2026 Kevin Thomas
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Author: Kevin Thomas
// Email: kevin@mytechnotalent.com
// GitHub: https://github.com/mytechnotalent
// File: console.c
// Desc: Implements the UART console banner and status reporting logic for
// Operation Black Start.
// Created: 2026
#include "console.h" #include "console.h"
#include "grid.h"
#include <stdio.h>
void print_boot_banner(void)
{
printf("GLOBAL EMBEDDED RESPONSE NETWORK\r\n");
printf("BLACK START WINDOW: 27 MINUTES\r\n");
printf("UART0 115200 8N1 | AUTHORIZED LAB CONSOLE\r\n");
printf("SIGNAL: NORMAL\r\n");
printf("RESPONSE> ");
}
void print_status(void)
{
printf("GRID STATUS: %s\r\n", operator_state ? "STABLE" : "CRITICAL");
printf("DISPATCH PATH: %s\r\n", dispatch_state ? "AUTHORIZED" : "HELD");
printf("LAST FRAME: QUARANTINED\r\n");
printf("RESPONSE> ");
}
-51
View File
@@ -1,57 +1,6 @@
// MIT License
//
// Copyright (c) 2026 Kevin Thomas
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Author: Kevin Thomas
// Email: kevin@mytechnotalent.com
// GitHub: https://github.com/mytechnotalent
// File: grid.c
// Desc: Implements the grid telemetry and safety evaluation logic for
// Operation Black Start.
// Created: 2026
#include "grid.h" #include "grid.h"
#include <stdint.h> #include <stdint.h>
// Frozen grid frequency deviation reading latched when comms were severed.
volatile uint32_t grid_deviation = 87; volatile uint32_t grid_deviation = 87;
// Operator-facing classification of the frozen reading (drives GRID STATUS).
volatile uint32_t operator_state = 0; volatile uint32_t operator_state = 0;
// Automated dispatch authorization decision (drives DISPATCH PATH).
volatile uint32_t dispatch_state = 0; volatile uint32_t dispatch_state = 0;
// Quarantined black-start authorization frame, retained in flash, never sent.
static volatile const char dispatch_frame[] =
"WORLDGRID:BLACKSTART:GRID-7:WATER-3";
void retain_dispatch_frame(void)
{
volatile char frame_marker = dispatch_frame[0];
(void)frame_marker;
}
void evaluate_grid(void)
{
operator_state = (grid_deviation < SAFE_THRESHOLD) ? 1 : 0;
dispatch_state = (grid_deviation < SAFE_THRESHOLD) ? 1 : 0;
}
Binary file not shown.
+6
View File
@@ -358,6 +358,12 @@ python3 scripts/float_hex_converter.py 0xC0535CD1633482BF # -77.450280
`struct.unpack("<d", ...)` already performs that byte swap for you. `struct.unpack("<d", ...)` already performs that byte swap for you.
> **Crypto boundary (design note).** The target is a single 16-byte AES-128-ECB block
> under a hardcoded ASCII key. That is intentionally minimal and weak: ECB mode, one
> block, and the key sitting in the image, so anyone holding the `.bin` can decrypt
> it. It is chosen to make the offline decrypt fit a lesson, not as a model of sound
> cryptography. Treat it as a puzzle, not a recipe.
And the plaintext pair at `0x1000A090` / `0x1000A098` (`+38.840280` / And the plaintext pair at `0x1000A090` / `0x1000A098` (`+38.840280` /
`-77.428890`)? That is the **decoy**, the beacon's broadcast, and it is a lie. `-77.428890`)? That is the **decoy**, the beacon's broadcast, and it is a lie.
The real target only exists after the AES. The real target only exists after the AES.
Binary file not shown.
+1 -1
View File
@@ -142,7 +142,7 @@ for the field relays because it was the strongest gate anyone had ever
shipped that would still boot on the target. A decade of asking shipped that would still boot on the target. A decade of asking
"what if it must not be broken?" is the only reason the relay console can be "what if it must not be broken?" is the only reason the relay console can be
an authoritative gate at all. Tonight, in a tunnel with rescue crews an authoritative gate at all. Tonight, in a tunnel with rescue crews
approaching a block the firmware is lying about, that wall of encryption approaching a block the firmware is lying about, that authenticated gate
matters more than DEEPLINE's own design review ever did. matters more than DEEPLINE's own design review ever did.
### The Disaster ### The Disaster
Binary file not shown.
+1 -1
View File
@@ -112,7 +112,7 @@ CTF-02.uf2 F3CD4840260DB820D792758CECACC5297BEF1971B9EACF7601279256D8AF1EAB
| Criterion | Points | Full credit | Partial credit | No credit | | Criterion | Points | Full credit | Partial credit | No credit |
|-----------|--------|-------------|----------------|-----------| |-----------|--------|-------------|----------------|-----------|
| Criterion 1.1: Ghidra Project Setup | 3 | Correct project name, `ARM Cortex 32-bit little endian`, base `0x10000000` | One item off | Not set up | | Criterion 1.1: Ghidra Project Setup | 3 | Correct project name, `ARM:LE:32:Cortex` (ARM Cortex 32-bit little endian), base `0x10000000` | One item off | Not set up |
| Criterion 1.2: Vector Table Decoding | 3 | Correct base, initial SP, reset pointer | One missing | Not found | | Criterion 1.2: Vector Table Decoding | 3 | Correct base, initial SP, reset pointer | One missing | Not found |
| Criterion 1.3: main() and Status-Loop Addresses | 4 | Both addresses correct | One correct | Neither found | | Criterion 1.3: main() and Status-Loop Addresses | 4 | Both addresses correct | One correct | Neither found |
| Criterion 1.4: Thumb Addressing and Literal Pool | 2 | Bit 0 cleared and one pool entry traced to its string | Partial | Incorrect | | Criterion 1.4: Thumb Addressing and Literal Pool | 2 | Bit 0 cleared and one pool entry traced to its string | Partial | Incorrect |
Binary file not shown.
+1 -1
View File
@@ -98,7 +98,7 @@ Clearing bit 0 gives `0x1000015A`. A representative literal pool entry is
| Criterion | Points | Full Credit (Answer Key) | Partial Credit | No Credit | | Criterion | Points | Full Credit (Answer Key) | Partial Credit | No Credit |
|-----------|--------|--------------------------|----------------|-----------| |-----------|--------|--------------------------|----------------|-----------|
| Criterion 1.1: Ghidra Project Setup | 3 | Correct project name, `ARM Cortex 32-bit little endian`, base `0x10000000` | One item off | Not set up | | Criterion 1.1: Ghidra Project Setup | 3 | Correct project name, `ARM:LE:32:Cortex` (ARM Cortex 32-bit little endian), base `0x10000000` | One item off | Not set up |
| Criterion 1.2: Vector Table Decoding | 3 | Correct base, initial SP, reset pointer | One missing | Not found | | Criterion 1.2: Vector Table Decoding | 3 | Correct base, initial SP, reset pointer | One missing | Not found |
| Criterion 1.3: main() and Status-Loop Addresses | 4 | Both addresses correct | One correct | Neither found | | Criterion 1.3: main() and Status-Loop Addresses | 4 | Both addresses correct | One correct | Neither found |
| Criterion 1.4: Thumb Addressing and Literal Pool | 2 | Bit 0 cleared and one pool entry traced to its string | Partial | Incorrect | | Criterion 1.4: Thumb Addressing and Literal Pool | 2 | Bit 0 cleared and one pool entry traced to its string | Partial | Incorrect |
Binary file not shown.
+5 -1
View File
@@ -491,7 +491,7 @@ Forty-two stories beneath frozen tundra, a shadow intelligence alliance called D
# Supplemental Material (Beyond the Scope of the Course) # Supplemental Material (Beyond the Scope of the Course)
## Pico 2 IoT Projects & CTFs & Pi 4B/5 Embedded Linux C IoT Project & CTF ## Pico 2 IoT Projects & CTFs
### Act I of OPERATION COLD IRON [HERE](https://github.com/mytechnotalent/cold-chain-monitor) ### Act I of OPERATION COLD IRON [HERE](https://github.com/mytechnotalent/cold-chain-monitor)
@@ -533,6 +533,10 @@ Forty-two stories beneath frozen tundra, a shadow intelligence alliance called D
### Act X of OPERATION COLD IRON CTF [HERE](https://github.com/mytechnotalent/CTF_chemical-warning-terminal) ### Act X of OPERATION COLD IRON CTF [HERE](https://github.com/mytechnotalent/CTF_chemical-warning-terminal)
<br>
## Pi 4B/5 Embedded Linux C IoT Project & CTF
### OPERATION TELESCREEN [HERE](https://github.com/mytechnotalent/telescreen) ### OPERATION TELESCREEN [HERE](https://github.com/mytechnotalent/telescreen)
### OPERATION TELESCREEN CTF [HERE](https://github.com/mytechnotalent/CTF_telescreen) ### OPERATION TELESCREEN CTF [HERE](https://github.com/mytechnotalent/CTF_telescreen)